I am using the django-model-utils InheritanceManager. I have a super Notification(models.Model) class which I use to create many notification subclasses such as PostNotification(Notification)
, CommentNotification(Notification)
, etc., and when trying to run CommentNotification.objects.bulk_create(list_of_comment_notification_objects)
, i get the following traceback:
File "/home/me/.virtualenvs/project/local/lib/python2.7/site-packages/django/db/models/query.py", line 429, in bulk_create
raise ValueError("Can't bulk create a multi-table inherited model")
ValueError: Can't bulk create a multi-table inherited model
and upon inspecting the query.py file, we get this causes the error:
for parent in self.model._meta.get_parent_list():
if parent._meta.concrete_model is not self.model._meta.concrete_model:
raise ValueError("Can't bulk create a multi-table inherited model")
Environment Django Model Utils version: 3.1.1 Django version: 1.11.7 Python version: 2.7.3
PostNotification.objects.bulk_create(
[PostNotification(related_user=user, post=instance) for user in users]
)
throws the above exception
I though that simply running:
BaseClass.objects.bulk_create(list_of_SubClass_objects)
instead of SubClass.objects.bulk_create(list_of_SubClass_objects)
would work and return a list of SubClass values, but subsequently running SubClass.objects.all()
would return an empty result. The bulk_create() would only create a Notification base class object for each item in the list.
Found a hacky solution. I hope it works in your case. The trick is create a model (which is not an inherited one) dynamically that has some meta (db_table) set. And use this dynamic model to create Child objects in bulk (in other words write into Child's DB table).
class Parent(models.Model):
name = models.CharField(max_length=10)
class Child(Parent):
phone = models.CharField(max_length=12)
# just an example. Should be expanded to work properly.
field_type_mapping = {
'OneToOneField': models.IntegerField,
'CharField': models.CharField,
}
def create_model(Model, app_label='children', module='', options=None):
"""
Create specified model
"""
model_name = Model.__name__
class Meta:
managed = False
db_table = Model._meta.db_table
if app_label:
# app_label must be set using the Meta inner class
setattr(Meta, 'app_label', app_label)
# Update Meta with any options that were provided
if options is not None:
for key, value in options.iteritems():
setattr(Meta, key, value)
# Set up a dictionary to simulate declarations within a class
attrs = {'__module__': module, 'Meta': Meta}
# Add in any fields that were provided
fields = dict()
for field in Model._meta.fields:
if field.attname == 'id':
continue
if field.model.__name__ == model_name:
field_class_name = type(field).__name__
print(field.attname)
fields[field.attname] = field_type_mapping[field_class_name]()
# Create the class, which automatically triggers ModelBase processing
attrs.update(fields)
model = type(f'{model_name}Shadow', (models.Model,), attrs)
return model
mod = create_model(Child)
parents = [Parent(name=i) for i in range(15)]
parents = Parent.objects.bulk_create(parents)
children = [mod(phone=parent.name, parent_ptr_id=parent.id) for parent in parents]
mod.objects.bulk_create(children)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With