Dear Michael and SQLAlchemy users,

I have what may be a minor bug report, and a feature request.

The possible bug is that creating an instance of a mapped association 
object<https://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#association-object>
 adds it to an attribute-mapped collection, but using the wrong key. In the 
following example, although the key is a date which is initialised, the key 
used is None instead.

The feature request is for some way to use an association_proxy on such a 
collection to return the instances of the collection (as though it was a 
relationship to the target table), instead of a dictionary from keys to target 
instances. I think it might be possible by supplying a proxy_factory and a 
getset_factory, but I can't find any examples, and it's quite difficult to set 
up in any case.

Here is the sample code illustrating both:

from datetime import date

from sqlalchemy import Column, Date, ForeignKey, Integer, Text, create_engine
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.orm.collections import attribute_mapped_collection

Base = declarative_base()

class Pet(Base):
    __tablename__ = 'pet'
    id = Column(Integer, primary_key=True)
    name = Column(Text)

class HousePet(Base):
    __tablename__ = 'house_pet'
    id_pet = Column(Integer, ForeignKey(Pet.id), primary_key=True)
    id_house = Column(Integer, ForeignKey("house.id"), primary_key=True)
    date_moved_in = Column(Date)
    pet = relationship(Pet)
    # house backref created by House.date_to_new_pet, not here:
    # house = relationship("House")

class House(Base):
    __tablename__ = 'house'
    id = Column(Integer, primary_key=True)
    address = Column(Text)

    date_to_new_pet = relationship(HousePet, cascade='all, delete-orphan',
                                   
collection_class=attribute_mapped_collection("date_moved_in"),
                                   backref=__tablename__)

    pets = association_proxy('date_to_new_pet', 'pet')

engine = create_engine('sqlite://')
Base.metadata.create_all(engine)

DBSession = sessionmaker(bind=engine)
session = DBSession(autocommit=True)

downing = House(address="10 Downing Street")
larry = Pet(name="Larry the Cat")
larry_at_home = HousePet(pet=larry, house=downing, date_moved_in=date(2007, 1, 
1))

# This should pass, but does not because the collection key was not set:
try:
    assert downing.date_to_new_pet == {larry_at_home.date_moved_in: larry}, 
str(downing.date_to_new_pet)
except AssertionError as exc:
    print(exc)

# How can we make House.pets be a list-like collection instead of dict-like?
try:
    assert downing.pets == [larry], str(downing.pets)
except AssertionError as exc:
    print(exc)

# It would be nice to be able to update this collection as well:
downing.pets = []
assert downing.date_to_new_pet == {}, str(downing.date_to_new_pet)
downing.pets = [larry]
assert downing.date_to_new_pet == {larry_at_home.date_moved_in: larry}, 
str(downing.date_to_new_pet)

I would like the latter to work because the documentation for association 
objects<https://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#association-object>
 warns about the dangers of unsynchronised collections, and suggests using an 
association_proxy instead of a relationship with a secondary table, which works 
fine for normal relationship collections, but is very unnatural for 
attribute-mapped ones.

Thanks in advance for your consideration.

Cheers, Chris.



This email is confidential. If you are not the intended recipient, please 
advise us immediately and delete this message. 
The registered name of Cantab- part of GAM Systematic is Cantab Capital 
Partners LLP. 
See - http://www.gam.com/en/Legal/Email+disclosures+EU for further information 
on confidentiality, the risks of non-secure electronic communication, and 
certain disclosures which we are required to make in accordance with applicable 
legislation and regulations. 
If you cannot access this link, please notify us by reply message and we will 
send the contents to you.

GAM Holding AG and its subsidiaries (Cantab – GAM Systematic) will collect and 
use information about you in the course of your interactions with us. 
Full details about the data types we collect and what we use this for and your 
related rights is set out in our online privacy policy at 
https://www.gam.com/en/legal/privacy-policy. 
Please familiarise yourself with this policy and check it from time to time for 
updates as it supplements this notice.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to