I get this exception:
django.core.exceptions.FieldError:
Local field 'ticket' in class 'SpecialPlugin' clashes with field of similar name from base class 'BasePlugin'
Here are my models:
class BasePlugin(models.Model): ticket = models.OneToOneField('foobar.ticket', primary_key=True, related_name='%(app_label)s_%(class)s') class Meta(IndexImplementation.Meta): abstract = True # .. Other stuff which should be available for SpecialPlugin # and other child classes. class SpecialPlugin(BasePlugin): ticket = models.OneToOneField('foobar.ticket', primary_key=True, related_name='special') I only found this note, but in my case the parent class is abstract. I am unsure if it applies here.
I want to give the child class SpecialPlugin the related name "special" since the related name (%(app_label)s_%(class)s) of the BasePlugin would break old code.
Is there a way to give SpecialPlugin.ticket the related_name "special"?
2 Answers
Answers 1
It might look like an ugly hack, but you can set a function call to the related_name argument instead of string. And then override that function in the child class/model.
class BasePlugin(models.Model): @staticmethod def get_ticket_related_name(): return '%(app_label)s_%(class)s' ticket = models.OneToOneField('foobar.ticket', primary_key=True, related_name=get_ticket_related_name.__func__()) class Meta(IndexImplementation.Meta): abstract = True class SpecialPlugin(BasePlugin): @staticmethod def get_ticket_related_name(): return 'special' Answers 2
It looks like the core of the problem is in the overriding of model field Django model inheritance, overriding fields
Simple workaround for you problem will be to decouple BasePlugin to to class without ticket field and then create a child class that contains ticket field
class BaseWithoutTicketPlugin(models.Model): # .. Other stuff which should be available for SpecialPlugin # and other child classes. class Meta(IndexImplementation.Meta): abstract = True class BasePlugin(BaseWithoutTicketPlugin): ticket = models.OneToOneField('foobar.ticket', primary_key=True, related_name='%(app_label)s_%(class)s') class Meta(BaseWithoutTicketPlugin.Meta): abstract = True class SpecialPlugin(BaseWithoutTicketPlugin): ticket = models.OneToOneField('foobar.ticket', primary_key=True, related_name='special') Idea is to use BaseWithoutTicketPlugin when you need to customize ticket and use BasePlugin when you don't.
0 comments:
Post a Comment