2012-08-22 140 views
3

我目前正在一個Django項目,我需要做多個遺產。其中的項目自我有一個管理員與多個網站。在我的管理部分中,我創建了一個包含成員所有必需信息的成員類。然後,所有單個網站都有一個MemberAdtra類,由管理員的成員類創建,我添加所有補充信息。當我啓動我的服務器(蟒蛇manage.py runserver命令......)我的錯誤:django多繼承

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) 

回答

1

FK的必須是唯一的。當您有一個默認的related_name(未指定)的FK時,它將由多個其他型號繼承,所有型號最終都會使用相同的related_name。請參閱Django文檔中名爲Be careful with related_name的部分。

的解決方案是將FK的related_name參數設置爲一樣的東西:

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

Django會再分應用標籤和模塊名稱爲字符串,使related_name唯一的每個子類中。

+1

我解決了我的問題,我在我的「MemberExtra」中添加了「member = models.OneToOneField(Member,related_name =」%(app_label)s _%(class)s_related「)」。 –

2

這裏的問題是您繼承了兩次模型,並且兩個子模型都具有相同的名稱。這導致有兩次相同的related_name,這是Django的一個問題。

你解決你的MemberExtra模型添加

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

工作,但你失去了隱性遺傳魔法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>_ptrmember_ptr

如果手動創建一個名爲 OneToOneField <parentclass>_ptr,並給它一個related_name,Django是仍然能夠找到父模型,並不會抱怨相同related_names。

在你的情況,只是在這兩個你MemberExtra模型定義添加

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

此解決方案的工作原理,但不是它應該如何完成。 Django提供了一個標誌parent_link,當設置爲true時,它將告訴Django這是將用於訪問父類的字段。

所以,你可以添加一個字段

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

如果由於某種原因,Django的需要默認指向重命名爲母公司,這將仍然有效。