Django: как установить ForeignKey related_name в классе Abstract Model?

Я хочу создать класс Abstract Model для будущего наследования следующим образом:

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

Поле 'created_at' работает нормально, но как генерировать related_name в 'created_by' для моих дочерних классов, чтобы предотвратить столкновение?

Как говорится в разделе Be careful with related_name и related_query_name документации , вы можете:

Чтобы обойти эту проблему, когда вы используете related_name или related_query_name в абстрактном базовом классе (только), часть значения должна содержать '%(app_label)s' и '%(class)s'.

  • '%(class)s' заменяется строчным именем дочернего класса, в котором используется поле.

  • '%(app_label)s' заменяется строчным именем приложения, в котором содержится дочерний класс. Имя каждого установленного приложения должно быть уникальным, и имена классов моделей в каждом приложении также должны быть уникальными, поэтому результирующее имя будет отличаться.

Таким образом, вы можете работать с:

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

Тогда related_name будет foo_created_by, если имя модели, которая наследуется, имеет имя foo.

Или если одно и то же имя модели может встречаться в разных приложениях:

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

Тогда related_name будет bar_foo_created_by, если имя модели, которая наследуется, названо foo в приложении с именем bar.

Вернуться на верх