On 6/13/15 10:09 AM, SC wrote:
Hi

I'm struggling with an SQLAlchemy issue.

I have a one to many relationship like so:

|
users_tags =Table(
"users_tags",Base.metadata,
Column("user_id",Integer,ForeignKey("users.id")),
Column("tag_id",Integer,ForeignKey("tags.id"))
)

classTag(Base):
    __tablename__ ="tags"

    id =Column(Integer(),primary_key=True)
    name =Column(String(255),nullable=False,unique=True)


classUser(Base):
    __tablename__ ="users"

    id =Column(Integer(),primary_key=True)
    name =Column(String(255),nullable=False)
    tags =relationship("Tag",secondary=users_tags,cascade="all, delete",
single_parent=True,backref=backref("user",cascade="all"),
                        lazy="subquery")

|

If I do the following:

|
tag =Tag()
tag.name ="C"

user =User()
user.name ="A"
user.tags.append(tag)
session.add(user)

user2 =User()
user2.name ="B"
user2.tags.append(tag)
session.add(user2)

session.commit()

|

I have two rows in users, two in users_tags and 1 in tags - as expected.

that's not possible. You have single_parent=True on User.tags. If I run your program as is, I get:

2015-06-14 09:49:19,715 INFO sqlalchemy.engine.base.Engine COMMIT
Traceback (most recent call last):
  File "test.py", line 44, in <module>
    user2.tags.append(tag)
File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/collections.py", line 1072, in append
    item = __set(self, item, _sa_initiator)
File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/collections.py", line 1044, in __set
    item = executor.fire_append_event(item, _sa_initiator)
File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/collections.py", line 716, in fire_append_event
    item, initiator)
File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/attributes.py", line 936, in fire_append_event
    initiator or self._append_token or self._init_append_token())
File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/strategies.py", line 1594, in append
    return _do_check(state, value, None, initiator)
File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/strategies.py", line 1589, in _do_check
    (orm_util.instance_str(value), state.class_, prop)
sqlalchemy.exc.InvalidRequestError: Instance <Tag at 0x1030b9410> is already associated with an instance of <class '__main__.User'> via its User.tags attribute, and is only allowed a single parent.



I then do:

|
userdel =session.query(User).filter_by(name="A").first()
session.delete(userdel)
session.commit()
|


And I end up with 3 empty tables in my DB. I want to still have 1 entry in users, 1 in users_tags and 1 in tags.
lose the "cascade='delete'" and the "single_parent". Traditional many-to-many doesn't need any of these directives. See http://docs.sqlalchemy.org/en/rel_1_0/orm/basic_relationships.html#many-to-many for an example.



The problem clearly comes from trying to maintain uniqueness within the tags table. The cascading delete is removing the single entry from the tags table which in turn is deleting the other user who is using that tag.

How can I achieve what I want without having to have duplicate entries in the tags table?

I get the impression maybe you want a Tag to delete itself once no User points to it, otherwise I'm not sure what duplicate entries has to do with deletions. There's a recipe for that here: http://stackoverflow.com/questions/9234082/setting-delete-orphan-on-sqlalchemy-relationship-causes-assertionerror-this-att/9264556#9264556




Thanks in advance!

--
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 <mailto:sqlalchemy+unsubscr...@googlegroups.com>. To post to this group, send email to sqlalchemy@googlegroups.com <mailto:sqlalchemy@googlegroups.com>.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

--
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 http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to