2👍
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.
- [Django]-Docker-compose cannot wait for mysql database
- [Django]-Django: manage.py custom command not found
0👍
For django 2.2 you can directly check the whether the through model is autocreated or not
This can be checked through a direct check like the following
# check for the auto_created value
m2m_field.through._meta.auto_created == False
To test this I created some sample clases with multiple M2M fields one with a custom through field and one with default class.
from django.db import models
import uuid
class Leaf(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(null=True, max_length=25, blank=True)
# Create your models here.
class MainTree(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
new_leaves = models.ManyToManyField(Leaf, through='LeafTree')
leaves = models.ManyToManyField(Leaf, related_name='main_branch')
class LeafTree(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
tree = models.ForeignKey(MainTree, on_delete=models.CASCADE)
leaf = models.ForeignKey(Leaf, on_delete=models.CASCADE)
Testing our method
In [2]: from trees.models import MainTree
In [3]: m = MainTree()
In [4]: m.leaves.through._meta
Out[4]: <Options for MainTree_leaves>
In [5]: m.leaves.through._meta.auto_created
Out[5]: trees.models.MainTree
In [6]: m.new_leaves.through._meta.auto_created
Out[6]: False
In [7]: m.new_leaves.through._meta.auto_created == False
Out[7]: True
In [8]: m.leaves.through._meta.auto_created == False
Out[8]: False
- [Django]-How to delete a record after a certain time of it's creation in Django?
- [Django]-Localhost django dev server vs. postgres slow on mac os?
- [Django]-Fresh python 3.7 / django 2.2.1 installation not recognising that mysqlclient is installed
- [Django]-Django admin action