我有以下用django编写的代码
from django.db import models
from django.contrib.auth.models import User
class AuditColumns(models.Model):
created_at=models.DateField("Created at")
created_by=models.ForeignKey(User, db_column="created_by", related_name="poll_user_created_by")
updated_at=models.DateTimeField("Updated at")
updated_by=models.ForeignKey(User, db_column="updated_by", null=True, related_name="poll_user_updated_by")
class Meta:
abstract = True
class Poll(AuditColumns):
question=models.CharField(max_length=300)
start_poll_at=models.DateTimeField(null=True)
end_poll_at=models.DateTimeField(null=True)
is_active=models.BooleanField(default=True)
class Choice(AuditColumns):
choice=models.CharField(max_length=200)
当我执行此代码时出现以下错误
mo@debian:~/PycharmProjects/KlamTam$ ./manage.py sql polls
Error: One or more models did not validate:
polls.poll: Accessor for field 'created_by' clashes with related field 'User.poll_user_created_by'. Add a related_name argument to the definition for 'created_by'.
polls.poll: Reverse query name for field 'created_by' clashes with related field 'User.poll_user_created_by'. Add a related_name argument to the definition for 'created_by'.
polls.poll: Accessor for field 'updated_by' clashes with related field 'User.poll_user_updated_by'. Add a related_name argument to the definition for 'updated_by'.
polls.poll: Reverse query name for field 'updated_by' clashes with related field 'User.poll_user_updated_by'. Add a related_name argument to the definition for 'updated_by'.
polls.choice: Accessor for field 'created_by' clashes with related field 'User.poll_user_created_by'. Add a related_name argument to the definition for 'created_by'.
polls.choice: Reverse query name for field 'created_by' clashes with related field 'User.poll_user_created_by'. Add a related_name argument to the definition for 'created_by'.
polls.choice: Accessor for field 'updated_by' clashes with related field 'User.poll_user_updated_by'. Add a related_name argument to the definition for 'updated_by'.
polls.choice: Reverse query name for field 'updated_by' clashes with related field 'User.poll_user_updated_by'. Add a related_name argument to the definition for 'updated_by'.
这与设置唯一的related_name有关,有没有办法动态生成related_names以确保它们始终是唯一的?当然最好知道什么是related_name,如果可能的话,避免设置它们?
此致
答案 0 :(得分:8)
Django ORM提供了相关名称,使您可以轻松找到键入当前模型的所有模型。因此,如果您有一个从Foo到Bar的键,默认情况下,Bar的实例将具有一个名为foo_set的属性,该属性将为您提供链接到该特定Bar的所有Foo的列表。
您可以使用更自然/适当的related_names指定您自己的相关名称,以便更容易回读代码。
然而,正如您所看到的,Django的ORM需要唯一的related_name值,并且因为您的基类中有FK,它会自动为所有子模型创建这些FK并使用相同的名称,这显然是 - - 不可行。
好消息是,this note in the documentation shows a workaround for Django 1.2+
如果由于某种原因,你不得不使用Django 1.1或更早版本,这里有一个替代的解决方法:不使用抽象模型上的FK,只需使用一个字段来存储键控模型的pk,并添加访问器因此。例如:
class AuditBase(models.Model):
created_at = models.DateTimeField("Created at", auto_now_add=True)
created_by = models.IntegerField(required=True)
updated_at = models.DateTimeField("Updated at", auto_now=True)
updated_by = models.IntegerField(required=True)
class Meta:
abstract = True
@property
def creator(self):
return User.objects.get(id=self.created_by)
@property
def last_editor(self):
return User.objects.get(id=self.updated_by)
def save(self, *args, **kwargs):
#track the creator/last editor via an optional kwarg
active_user = self.kwargs.get('user')
if active_user:
self.updated_by = active_user
if active_user and not self.created_by:
self.created_by = active_user
return super(AuditBase, self).save(*args, **kwargs)