Могу ли я объявить два ForeignKey для одной таблицы в одной абстрактной модели Django ORM?

Подскажите, могу ли я объявить два ForeignKey для одной таблицы в одной абстрактной модели? Я могу сделать так:

class TrackableDateModel(models.Model):
    """Abstract model to Track the creation/updated date for a model."""""
    create_date = models.DateTimeField(auto_now_add=True, help_text="Creation time", verbose_name="Created", null=True, blank=True)
    create_user = models.ForeignKey(User, related_name="create_user", on_delete=models.CASCADE, help_text="Who created", verbose_name="Author", null=True, blank=True)
    update_date = models.DateTimeField(auto_now=True, help_text="Time of change", verbose_name="Changed", null=True, blank=True)

    class Meta:
        abstract = True


class A(TrackableDateModel):
    ....

class B(TrackableDateModel):
    .....

Но не может добавить в TrackableDateModel:

    update_user = models.ForeignKey(User, related_name="update_user", on_delete=models.CASCADE, help_text="Who modified", verbose_name="Author of change", null=True, blank=True)

Потому что makemigrations клянется.

ERRORS:
DjModule.A.create_user: (fields.E304) Reverse accessor 'User.create_user' for 'DjModule.A.create_user' clashes with reverse accessor for DjModule.B.create_user'.
        HINT: Add or change a related_name argument to the definition for 'DjModule.A.Export4Payment.create_user' or 'DjModule.B.create_user'.

и разбивается...

TLDR: You can do this, but not with a fixed related_name=… [Django-doc]. You can use %(class)s and %(app_label)s to make the related_name=… items unique, as is discussed in the Be careful with related_name and related_query_name section [Django-doc].

Причина, по которой моделирование в вашем вопросе не будет работать, заключается в том, что related_name - это имя отношения в reverse, то есть от User к подклассу (или потомку в общем случае) TrackableDateModel. Теперь, если это create_user, что тогда делать some_user.create_user.all()? Какую модель он должен выбрать?

Вы можете создавать различные отношения, каждое из которых будет иметь свое имя, например:

class TrackableDateModel(models.Model):
    'Abstract model to Track the creation/updated date for a model.'
    create_date = models.DateTimeField(
        auto_now_add=True,
        help_text='Creation time',
        verbose_name='Created',
        null=True,
        blank=True,
    )
    create_user = models.ForeignKey(
        User,
        related_name='created_%(class)ss',
        on_delete=models.CASCADE,
        help_text='Who created',
        verbose_name='Author',
        null=True,
        blank=True,
    )
    update_date = models.DateTimeField(
        auto_now=True,
        help_text='Time of change',
        verbose_name='Changed',
        null=True,
        blank=True,
    )

тогда модель User будет иметь дополнительные атрибуты .created_as, .created_bs и т.д.


Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation [Django-doc].

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