I am using Django 4.0
I have the following models:
class Parent(models.Model):
# fields ommitted for the sake of brevity
pass
class Child(Parent):
child_only_field = models.CharField(max_length=64)
p = Parent.objects.create(**fields_dict)
c1 = Child.objects.create(child_only_field='Hello 123', p) # Obviously won't work
# c2 = ...
Is there a way to create child objects from an instance of a parent (without manually "unpacking" the fields of the parent)?
it is easy, if you understand how Django works with implizit o2o relation.
class Parent(Model):
# fields
# implizit o2o
class Child(Parent):
child_only_field = models.CharField(max_length=64)
# explizit o2o
class Child_1(Parent):
parent = models.OneToOneField(Parent)
child_only_field = models.CharField(max_length=64)
1.Save child object by existed Parent class object DON'T USE IT IN NORMAL CODE.
parent = Parent.objects.get(pk=some_pk)
child = Child(child_only_field='Hello 123', pk=parent.pk)
child.save_base(raw=True) # important part of code
Model.save_base - internal method to save information only for child fields. BUT parent data should already exists.
2.Save created Parent as child. DON'T USE IT IN NORMAL CODE:
parent = Parent.objects.get(pk=some_pk)
parent.child_only_field = 'Hello 123'
parent.save_base(class=Child)
Model.save_base method saves information for whole chain of inheritance.
3.Save created child normally. PLEASE USE IT IN NORMAL CODE:
child = Child(child_only_field='Hello 123', **fields_dict)
child.save()
I especially don't use DataManager. I can say, this is more as internal method, than public interface.
Save child through DataManager.
child = Child.objects.create(child_only_field='Hello 123', **fields_dict)
objects.create made point 3. from my answer. You can see it in django.db.models.query.py
I hope it helps.
The following 1-liner will produce a new field dictionary containing only shared fields, looping through Django's _meta.fields (does not include M2M fields), which you can then pass to the child instance.
p = Parent.objects.create(**fields_dict)
new_fields_dict = {f.name: getattr(p, f.name) for f in p._meta.fields
if f in Child._meta.fields and f != p._meta.pk}
c = Child.objects.create(child_only_field='Hello 123', **new_fields_dict)
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