2014-04-28 19 views
0

目前我有在模型4類:條件OneToOne在Django

User(models.Model): 
    .... 
     class Meta: 
      abstract=True 
    Sender(User): 
    .... 
    Owner(User): 
    .... 
    Report(models.Model): 
     sender = models.OneToOneField(Sender) 
     owner = models.OneToOneField(Owner) 

發件人/所有者擴展抽象基類用戶。我需要發件人,報告和所有者之間的一對一關係。

問題是我無法創建發件人或所有者模型,因爲它們的字段沒有區別(他們需要的所有數據均在抽象用戶模型中創建,並且爲便於表示而創建子類)。我提出的解決方案是這樣的:

User(models.Model): 
    .... 
     user_type = models.CharField(max_length=200) 

     class Meta: 
      abstract=True 

    Report(models.Model): 
     sender = models.OneToOne(User) 
     owner = models.OneToOne(User) 

但是我想確保每個報表有一個發件人和一個所有者。有沒有一種方法可以指定用戶必須具有「發件人」的user_type或其他內容?或者是否有更好的解決方案呢?

+0

django - polymorhpic可以幫助你創建你的模型/關係嗎? https://github.com/chrisglass/django_polymorphic – dm03514

回答

2

我不是一個經驗豐富的用戶,所以請原諒我,如果我在這裏錯了,但我不知道定義一個名爲User的新模型是個好習慣,django.contrib.auth.models提供了一個名爲User的基本用戶模型。在我看來,這會讓你陷入潛在的衝突。

既然你想有兩個不同的「類型」的用戶,我會使用舊的方法從相關模型鏈接回來。

from django.contrib.auth.models import User 
from django.db import models 


class Sender(models.Model): 
    user = models.OneToOneField(User, related_name='sender') 
    is_active = models.BooleanField(default=True) 


class Owner(models.Model): 
    user = models.OneToOneField(User, related_name='owner') 
    is_active = models.BooleanField(default=True) 

假設你創建id=1新的用戶,然後創建一個名爲s新發件人鍵入該用戶。請記住,s是發件人對象,而不是用戶對象。

>>s.user 
<user: username> #can vary with your own unicode definitions 
>>s.user.id 
1 
>>print hasattr(s.user, 'sender') 
True 
>>print hasattr(s.user, 'owner') 
False 
>>print s.is_active 
True 
>>u = User.objects.get(id=1) 
>>u.sender 
<Sender: username> #again, what actually displays is controlled by your own 'def __unicode__' 
>>print u.sender.is_active 
True 
>>print hasattr(u, 'sender') 
True 
>>print hasattr(u, 'owner') 
False 

然後爲報表模型:

class Report(models.Model): 
    sender = models.ForeignKey(Sender, related_name='report_sender') 
    owner = models.ForeignKey(Owner, related_name='report_owner') 

編輯回答您的其他問題:你如何確保用戶只有一個發送者或擁有者的模式,但不能兩者兼而有之?

我不知道如何在模型層面上實現這一點。在實踐中,我可以想到的最簡單的方法是防止這個問題成爲問題,當創建新的發件人/所有者時,通過一些自定義表單驗證。如果您要創建一個新的發件人,作爲驗證的一部分,請確保您綁定的用戶尚未擁有與其綁定的所有者模型 - 反之亦然。或者同時創建用戶和適當的配置文件模型。

你可以改變你的用戶登記表有一個額外的領域:

class UserRegistrationForm(UserCreationForm): 

    CHOICES = (
     ('s', 'Sender'), 
     ('o', 'Owner'), 
    ) 

    type = models.ChoiceField(max_length=2, choices=CHOICES) 

    class Meta: ... 

然後,當你正在處理您的視圖形式:

... 
if form.is_valid(): 
    u = form.save() 
    type = form.cleaned_data['type'] 
    if type == 's': 
     Sender.objects.create(user=u) 
    elif type == 'o': 
     Owner.objects.create(user=u) 

(我很抱歉,但我不是我可以測試的地方,請告訴我它是否不適合你)

+0

is_active的用途是什麼?還有一種方法可以確保用戶只有發件人或所有者? –

+0

除了讓你做's.is_active'之外,沒有必要這麼做。額外的數據字段對我來說很有用,可以說明這兩個模型如何相互關聯,但是您可以將其忽略。我將在上面的主要答案中編輯對第二個問題的回覆。 – souldeux

0

我認爲解決這個問題最直接的方法是覆蓋報告模式的save()方法l並插入(在super()調用之前)驗證檢查以執行您的要求。