Setting related_name for django abstract base classes

In Django, ForeignKey and ManyToManyField fields have a corresponding backward relation is automatically created for you.  By default, this relation is given a name automatically, but if you want, you can specify your own using the related_name parameter like: ForeignKey (User, related_name='<name-here>') However, things get a bit different when you use abstract classes.  Not sure if other Django versions have the same behavior, but in 1.6.3, this code breaks things if more than one class inherits from the base abstract class:

class TimeStampedModel(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class TimeStampedAuthModel(TimeStampedModel):
    created_by = models.ForeignKey(User)
    updated_by = models.ForeignKey(User)

    class Meta:
        abstract = True

django_abstract_foreign_keys_1

The reason for this can be found in the ever helpful Django docs page

As explained there, you resolve  this as follows:

To work around this problem, when you are using related_name in an abstract base class (only), part of the name should contain '%(app_label)s' and'%(class)s'

So we patch up our declaration to be:

created_by = models.ForeignKey(User, related_name='%(app_label)s_%(class)s_created_by')
updated_by = models.ForeignKey(User, related_name='%(app_label)s_%(class)s_updated_by')

Also, as pointed out in this blog post, any name ending with a ‘+’ also works

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s