From Django 2.2 the .add()
, .create()
, etc. methods are able to work with a custom through
Model as long as you provide the corresponding values for the required fields of the intermediate model using through_defaults
:
From the documentation:
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.
The .remove()
method's behavior needs a bit of attention:
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>]>
About the _meta
field I haven't been able to access it from the m2m field, but the above part of the documentation seems to allow avoiding the "gymnastics" of accessing _meta
.
If I find anything interesting I will update my answer accordingly.