On Fri, Mar 2, 2018 at 1:17 AM,  <jens.troe...@gmail.com> wrote:
> Hi,
>
> I've been playing with the Many-to-Many relationship from the documentation.
> Suppose I have a student and teacher and would like to define a
> bidirectional “favorite” relationship between the two, i.e. if a student is
> a favorite of a teacher then the teacher is also a favorite of that student:
>
> favorite_association_table = Table("favorite_associations", Base.metadata,
>     Column("student_id", Integer, ForeignKey("students.id"),
> nullable=False),
>     Column("teacher_id", Integer, ForeignKey("teachers.id"),
> nullable=False),
>     )
>
> and in the Teacher class:
>
> favs = relationship("Student", secondary=favorite_association_table,
> backref="favs")
>
> Now I observe the following:
>
>>>> teacher.favs
> []
>>>> student.favs
> []
>>>> student.favs.append(teacher)
>>>> teacher.favs.append(student)
>
> which creates two entries in the association table:
>
> mysql> select * from favorite_associations;
> +----------------------------------+----------------------------------+
> | student_id                       | instructor_id                    |
> +----------------------------------+----------------------------------+
> | 030ced9060d2460fa30936cffd2e0a0a | 08315ae48d574bc3ac29526c675e67fc |
> | 030ced9060d2460fa30936cffd2e0a0a | 08315ae48d574bc3ac29526c675e67fc |
> +----------------------------------+----------------------------------+
> 2 rows in set (0.00 sec)
>
> That is probably alright, but not really desirable. Now, when I attempt to
> delete either the student or the teacher from the other, I get an error:


the above table is relationally incorrect - you should never have
duplicate data inside of a table like that, and the student_id and
instructor_id columns should normally form the primary key, or at
least a unique constraint of some kind.   But beyond that, is a
"favorite" inherently bidirectional?   usually "favorites" have a
direction,   A might be B's favorite, but B is not A's favorite.


>
>>>> student.favs.remove(teacher)
> […]
> sqlalchemy.orm.exc.StaleDataError: DELETE statement on table
> 'favorite_association' expected to delete 1 row(s); Only 2 were matched.
>
> I guess I could avoid the list.remove() and build a query like:

if you *do* want to add on both ends but it's "unique" anyway, try
using collection_class=set with your relationship.  that will
eliminate dupes on the Python side and you can set up the table rows
as unique.

>
> delete from favorite_associations where student_id='...'
>
> but that seems clumsy in the context of the ORM.
>
> So my question is: what is the proper and recommended way of implementing
> and handling such a bidirectional relationship?
>
> Thank you!
> Jens
>
>
>
>
>
>
>
>
> --
> 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.

-- 
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