m2m, through fields and _bulk_create seems broken
mm-matthias opened this issue · 0 comments
Describe the issue
Bakery fails with an exception when trying to bulk create models that are using ManyToManyField with a through
attribute.
To Reproduce
Suppose you have models like these:
class MyGroup(models.Model):
id = models.CharField(max_length=255, primary_key=True)
class MyUser(models.Model):
id = models.CharField(max_length=255, primary_key=True)
groups = models.ManyToManyField(MyGroup, through="MyUserGroupMembership", related_name="users")
class MyUserGroupMembership(models.Model):
user = models.ForeignKey(MyUser, on_delete=models.PROTECT, related_name="memberships")
group = models.ForeignKey(MyGroup, on_delete=models.PROTECT, related_name="memberships")
And then you run code similar to
recipe = Recipe(MyUser, groups=(baker.make(MyGroup),))
recipe.make(_quantity=10, _bulk_create=True)
You will receive an exception like this:
File "python3.12/site-packages/model_bakery/baker.py", line 131, in make
return bulk_create(baker, _quantity, _save_kwargs=_save_kwargs, **attrs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "python3.12/site-packages/model_bakery/baker.py", line 840, in bulk_create
through_model(
File "python3.12/site-packages/django/db/models/base.py", line 567, in __init__
raise TypeError(
TypeError: MyUserGroupMembership() got unexpected keyword arguments: 'users', 'mygroup'
Obviously these fields are not valid to create an instance of MyUserGroupMembership
.
The offending code in bakery is in baker.bulk_create
:
through_model = getattr(entry, field.name).through
through_model.objects.bulk_create(
[
through_model(
**{
field.remote_field.name: entry,
field.related_model._meta.model_name: obj,
}
)
for obj in kwargs[field.name]
]
)
You can see that the arguments used to create the through
model are field.remote_field.name
and field.related_model._meta.model_name
. These are incorrect as shown above and need to be fixed.
Maybe through fields are best used for this (or pose an additional complication, not sure without further digging).
Expected behavior
Bakery can actually bulk create models that are using ManyToManyField with a through
attribute.
Versions
- Python: 3.12
- Django 4.2
- Model Bakery 1.18.0