Home > OS >  Django: how to set ForeignKey related_name in Abstract Model class?
Django: how to set ForeignKey related_name in Abstract Model class?

Time:06-12

I want to create on Abstract Model class for future inheriting like this:

class AbstractModel(models.Model):

    created_at = models.DateTimeField(
        auto_now_add=True,
        blank=True,
        null=True,
    )

    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        related_name='XXX_created_by',
        blank=True,
        null=True,
    )

    class Meta:
        abstract = True

Field 'created_at' is working fine, but how to generate related_name in 'created_by' for my child classes to prevent clashing?

CodePudding user response:

As the Be careful with related_name and related_query_name section of the documentation says, you can:

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

  • '%(class)s' is replaced by the lowercased name of the child class that the field is used in.

  • '%(app_label)s' is replaced by the lowercased name of the app the child class is contained within. Each installed application name must be unique and the model class names within each app must also be unique, therefore the resulting name will end up being different.

You thus can work with:

class AbstractModel(models.Model):
    # …
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        related_name='%(class)s_created_by',
        blank=True,
        null=True,
    )

    class Meta:
        abstract = True

Then the related_name will be foo_created_by if the name of the model that inherits is named foo.

Or if the same model name can occur in different apps:

class AbstractModel(models.Model):
    # …
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        related_name='%(app_label)s_%(class)s_created_by',
        blank=True,
        null=True,
    )

    class Meta:
        abstract = True

Then the related_name will be bar_foo_created_by if the name of the model that inherits is named foo in an app named bar.

  • Related