#34207: Incorrect SQL query when adding a ManyToMany related object with a
"through" table prevents adding a new relationship if the new relationship
is identical except for a different value for "through_defaults"
-------------------------------------+-------------------------------------
     Reporter:  Credentive           |                    Owner:  nobody
         Type:  Bug                  |                   Status:  closed
    Component:  Database layer       |                  Version:  4.1
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:  duplicate
     Keywords:  ManyToManyField      |             Triage Stage:
  through                            |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Credentive):

 I've re-read the section, and while it's not stated that it will work,
 it's also not clear to me that it won't.

 {{{
 Now that you have set up your ManyToManyField to use your intermediary
 model (Membership, in this case), you’re ready to start creating some
 many-to-many relationships. You do this by creating instances of the
 intermediate model:

 >>> ringo = Person.objects.create(name="Ringo Starr")
 >>> paul = Person.objects.create(name="Paul McCartney")
 >>> beatles = Group.objects.create(name="The Beatles")
 >>> m1 = Membership(person=ringo, group=beatles,
 ...     date_joined=date(1962, 8, 16),
 ...     invite_reason="Needed a new drummer.")
 >>> m1.save()
 >>> beatles.members.all()
 <QuerySet [<Person: Ringo Starr>]>
 >>> ringo.group_set.all()
 <QuerySet [<Group: The Beatles>]>
 >>> m2 = Membership.objects.create(person=paul, group=beatles,
 ...     date_joined=date(1960, 8, 1),
 ...     invite_reason="Wanted to form a band.")
 >>> beatles.members.all()
 <QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>


 You can also use add(), create(), or set() to create relationships, as
 long as you specify through_defaults for any required fields:

 >>> beatles.members.add(john, through_defaults={'date_joined': date(1960,
 8, 1)})
 >>> beatles.members.create(name="George Harrison",
 through_defaults={'date_joined': date(1960, 8, 1)})
 >>> beatles.members.set([john, paul, ringo, george],
 through_defaults={'date_joined': date(1960, 8, 1)})
 You may prefer to create instances of the intermediate model directly.

 If the custom through table defined by the intermediate model does not
 enforce uniqueness on the (model1, model2) pair, allowing multiple values,
 the remove() call will remove all intermediate model instances:

 >>> Membership.objects.create(person=ringo, group=beatles,
 ...     date_joined=date(1968, 9, 4),
 ...     invite_reason="You've been gone for a month and we miss you.")
 >>> beatles.members.all()
 <QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>, <Person: Ringo
 Starr>]>
 >>> # This deletes both of the intermediate model instances for Ringo
 Starr
 >>> beatles.members.remove(ringo)
 >>> beatles.members.all()
 <QuerySet [<Person: Paul McCartney>]>
 }}}

 Looking at that text again, it is not clear that add() will not work for
 multiple references to the same object, it's just suggested that adding
 relationship objects directly is a matter of preference. It may be good to
 clarify in the documentation that add does not support adding multiple
 references to the same object. Would have saved me a few hours :)

 In fact, all of the calls through the intermediate model kind of break
 down, because you can't filter on attributes of the intermediate model in
 the calls. I will be using the intermediate model for this, but actually
 removing the manytomany relationship, as it doesn't really work. For
 anyone who wants to create a self-referential relationship where the
 values of the intermediate objects are intended to be used to filter the
 relationship sets, the ManyToMany field won't support this, while the
 intermediate objects themselves work fine. The only thing I could think of
 that might make the work the way I want would be to write a custom
 ManyRelatedManager, but I haven't seen any documentation on how to do
 this, and it might not be worth the time just to get the ability to use
 the manytomany methods.

 If, in the example in the documentation, you wanted to query for the
 members of the beatles as of a particular date, you would run into the
 same problems I have. My whole use case is built around this, so I will
 just use the intermediate table, and ignore all(), get(), add() etc.. The
 use of the date in the example kind of suggests this could be possible
 when in fact it isn't.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34207#comment:4>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018505fe455e-af20fa87-2eb6-4514-8bb2-4e4bfc72c7a2-000000%40eu-central-1.amazonses.com.

Reply via email to