我目前正在开发一个django项目,我需要做多个遗产。它自己的项目有一个管理员与多个网站。在我的管理部分,我创建了一个包含成员所有必填信息的成员类。然后,所有单个站点都有一个MemberExtra类,该类是从admin中的Member类创建的,其中我添加了所有补充信息。当我启动我的服务器(python manage.py runserver ...)时,我遇到了这个错误:
Error: One or more models did not validate:
programsite.memberextra: Accessor for field 'member_ptr' clashes with related field 'Member.memberextra'. Add a related_name argument to the definition for 'member_ptr'.
programsite.memberextra: Reverse query name for field 'member_ptr' clashes with related field 'Member.memberextra'. Add a related_name argument to the definition for 'member_ptr'.
gourmandiz.memberextra: Accessor for field 'member_ptr' clashes with related field 'Member.memberextra'. Add a related_name argument to the definition for 'member_ptr'.
gourmandiz.memberextra: Reverse query name for field 'member_ptr' clashes with related field 'Member.memberextra'. Add a related_name argument to the definition for 'member_ptr'.
管理员/ models.py:
class Member(models.Model):
prog = models.ForeignKey(Program, verbose_name=_("Program"))
status = models.CharField(_("Status"), m status = models.CharField(_("Status"), max_length=1, choices=STATUS_CHOICE\
S)
points_avai = models.BigIntegerField(_("
Current Points"), null=True)
points_notavai = models.BigIntegerField(_("Future Points"), null=True)
cn = models.CharField(_("Company name"), max_length=250)
full_name = models.CharField(_("Full name"), max_length=250)
b_add = models.CharField(_("Billing address"), max_length=250)
b_city = models.CharField(_("Billing City"), max_length=250)
b_zip = models.CharField(_("Billing ZIP code"), max_length=250)
b_country = models.CharField(_("Billing country"), max_length=250)
prog_start_date = models.DateField(_("Program start date"), null=True)
prog_end_date = models.DateField(_("Program end date"), null=True)
member_id = models.CharField(_("Member ID"), max_length=250, primary_key=T\
rue)
client_id = models.CharField(_("Client ID"), max_length=250, help_text="Nu\
méro de client.")
user = models.OneToOneField(User)
def __unicode__(self):
return self.full_name + " (" + str(self.member_id) + ")"
class Meta:
verbose_name = _("Member")
verbose_name_plural = _("Members")
programsite / models.py:
class MemberExtra(Member):
email = models.EmailField(_("Email"), max_length=100, null=True)
tel = models.CharField(_("Tel"), max_length=100, null=True)
patrick = models.CharField(_("Patrick"), max_length=100, null=True)
test42 = models.CharField(_("Test42"), max_length=100, null=True)
gourmandiz / models.py:
class MemberExtra(Member):
email = models.EmailField(_("Email"), max_length=100, null=True)
答案 0 :(得分:2)
这里的问题是你继承了你的模型两次,并且两个子模型都有相同的名称。这导致两次相同的related_name,这对Django来说是一个问题。
您要添加的解决方案
member = models.OneToOneField(Member, related_name="%(app_label)s_%(class)s_related")"
你的MemberExtra
模型中的是有效的,但是你放弃了Django所做的隐式继承魔法,让你可以在一个模型中访问你的模型:
使用您的解决方案,您必须:
from programsite.models import MemberExtra
m = MemberExtra.objects.get(member__full_name = "Foobar")
m.email # -> returns the email of your MemberExtra instance
m.member.b_add # -> returns the address of the inherited member instance
使用Django本机继承,您可以执行以下操作:
from programsite.models import MemberExtra
m = MemberExtra.objects.get(full_name = "Foobar")
m.email # -> returns the email of your MemberExtra instance
m.b_add # -> returns the address of the inherited member instance
在我看来哪个更干净。
为了管理继承,Django实际上创建了一个OneToOneField
(https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance)。
在这种情况下,此字段称为<parentclass>_ptr
,member_ptr
。
<击>
如果你手动创建一个名为OneToOneField
的{{1}},并给它一个related_name,Django仍然可以找到父模型,并且不会抱怨相同的related_names。
在您的情况下,只需添加
<parentclass>_ptr
<{1}}模型定义中的 。
击>
此解决方案有效,但不是应该如何完成。 Django提供了一个标志member_ptr = models.OneToOneField(Member, related_name="%(app_label)s_%(class)s_related")"
,当设置为true时,将告诉Django这是用于访问父类的字段。
所以你可以添加一个字段
MemberExtra
如果由于某种原因,Django需要将默认指针重命名为父级,那么它仍然可以工作。
答案 1 :(得分:1)
FK的related_name
必须是唯一的。如果您的FK具有默认related_name
(未指定),并且由多个其他模型继承,则所有模型最终都具有相同的related_name
。请参阅名为Be careful with related_name
的Django文档中的部分。
解决方案是将FK的related_name
参数设置为:
prog = models.ForeignKey(Program, verbose_name=_("Program"), related_name="%(app_label)s_%(class)s_related")
Django然后将app标签和模块名称转换为字符串,使每个子类的related_name
唯一。