I'm upgrading a project from django 1.8 to 1.10 and it looks like django has improved the check of eventual name collision between foreign keys and model inheritance. This is obviously a good thing, but the projet I need to upgrade is a big one and it would be a hell to rename a model.
Let me explain the problem : I have a base class called Parent
and many children which are linked together, like so :
class Parent(models.Model):
title = models.CharField(max_length=10)
class ChildA(Parent):
description = models.TextField()
class ChildB(Parent):
description = models.TextField()
childa = models.ForeignKey(ChildA)
The clash here is that a childb
object has 2 "childa" attributes :
parent
attributes).The 2 obvious solutions here are :
ChildB.childa
to ChildB.somethingelse
ChildA
model to something else. Both solutions costs a lot and will probably introduce new bugs. So I wondered : Is it possible to rename the reverse related name of the inherited object ?
For example :
p = Parent.objects.get(pk=1)
print p.childa_child # Hit the ChildA instance
I have no idea if I'm clear enough but I'll keep this question up to date.
==== EDIT ====
To be more concise, if I have 2 models class Parent(models.Model)
and class Child(Parent)
, a dynamic attribute parent.child
is created.
Is it possible to edit this attribute name without touching the class name ?
Multi-table inheritance creates an implicit OneToOneField
field between the base model and the subclass.
Django allows you to modify this relationship by explicitly setting the one to one field.
class Parent(models.Model):
title = models.CharField(max_length=10)
class ChildA(Parent):
parent = models.OneToOneField(to=Parent, parent_link=True)
description = models.TextField()
class ChildB(Parent):
parent = models.OneToOneField(to=Parent, parent_link=True)
description = models.TextField()
childa = models.ForeignKey(ChildA)
The important bit here is the parent_link=True
argument which tells Django to use this field declaration for managing the multi-table inheritance with these two models.
So you can now set related_name='+'
to prevent Django from creating a reverse relationship or you can set related_name
to a more unique name:
class ChildA(Parent):
parent = models.OneToOneField(to=Parent, parent_link=True, related_name='child_a_here')
description = models.TextField()
class ChildB(Parent):
parent = models.OneToOneField(to=Parent, parent_link=True, related_name='child_b_here')
description = models.TextField()
childa = models.ForeignKey(ChildA)
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