3

我目前正在做一个 django 项目,我需要做多个遗留。该项目本身有一个拥有多个网站的管理员。在我的管理部分,我创建了一个 Member 类,其中包含成员的所有必需信息。然后,所有单个站点都有一个 MemberExtra 类,它是从管理员的 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")

程序站点/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)

美食家/models.py:

class MemberExtra(Member):
     email = models.EmailField(_("Email"), max_length=100, null=True)
4

2 回答 2

2

这里的问题是您继承了您的模型两次,并且两个子模型具有相同的名称。这导致有两次相同的相关名称,这对 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 实际上创建了一个OneToOneFieldhttps://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance)。在您的情况下<parentclass>_ptr,此字段称为。member_ptr

如果你手动创建一个OneToOneFieldnamed<parentclass>_ptr并给它一个 related_name,Django 仍然能够找到父模型,并且不会抱怨相同的 related_names。

在您的情况下,只需添加

member_ptr = models.OneToOneField(Member, related_name="%(app_label)s_%(class)s_related")"

在您的两个MemberExtra模型定义中。

此解决方案有效,但不应该这样做。Django 提供了一个标志parent_link,当设置为 true 时,它​​将告诉 Django 这是将用于访问父类的字段。

所以你可以添加一个字段

member = models.OneToOneField(Member, parent_link=True, related_name="%(app_label)s_%(class)s_related")"

如果出于某种原因,Django 需要重命名指向父级的默认指针,它仍然可以工作。

于 2013-05-07T05:59:00.587 回答
1

FK的related_name必须是唯一的。当您有一个具有默认related_name(未指定)的 FK 时,该 FK 被多个其他模型继承,所有模型最终都具有相同的related_name. 请参阅 Django 文档中题为“小心使用related_name.

解决方案是将related_nameFK 的参数设置为:

prog = models.ForeignKey(Program, verbose_name=_("Program"), related_name="%(app_label)s_%(class)s_related")

然后 Django 会将应用程序标签和模块名称分到字符串中,使related_name每个子类都是唯一的。

于 2012-08-22T14:35:48.557 回答