2015-03-25 57 views
4

我有這些模型:動態極限選擇爲外鍵

class UserProfile(models.Model): 
    name = models.CharField(max_length=100) 

class Dialog(models.Model): 
    belong_to = models.ManyToManyField(UserProfile) 

class Message(models.Model): 
    # Dialog to which this message belongs 
    part_of = models.ForeignKey(Dialog) 

    # User who sends message 
    sender = models.ForeignKey(UserProfile, related_name='sender') 
    # User who receives message 
    receiver = models.ForeignKey(UserProfile, related_name='receiver') 

我想要做的是限制發送者和接收者領域的選擇,使他們只能是整個對話所屬的用戶。 我嘗試這樣做:

sender = models.ForeignKey(UserProfile, 
          related_name='sender', 
          limit_choices_to={'dialog':1}) 

這限制了選擇,但僅用於與ID = 1對話框的成員。我想知道這是否可以動態完成?

回答

0

如果Message的實例全都屬於Dialog,爲什麼不在Dialog模型上創建字段messages?然後,您可以將發件人和收件人附加到每個Dialog。總之,沿着這些線:

class Dialog(models.Model): 
    messages = models.ManyToManyField(Message) 
    sender = models.ForeignKey(UserProfile) 
    receiver = models.ForeignKey(UserProfile) 

class Message(models.Model): 
    # Other fields 

消息的發送者和接收者,然後始終是對話框所屬的那些。

+0

這個想法是不可接受的,因爲每個消息的發送者 - 接收者是不同的。當我發佈內容時 - 我是發件人,你是收件人,反之亦然。因此,在同一個對話框中,發送者 - 接收者可能會改變 – wasd 2015-03-25 13:07:34

4

我不認爲有任何方法可以像使用limit_choices_to一樣動態過濾,因爲您無法訪問所需的對象以在那裏形成這樣的查詢。

相反,您應該創建自己的消息模型表單併爲那些字段設置查詢集。類似下面...

class MessageForm(forms.ModelForm): 
    class Meta: 
     model = Message 

    def __init__(self, *args, **kwargs): 
     super(MessageForm, self).__init__(*args, **kwargs) 

     if self.instance.part_of and self.instance.part_of.id: 
      users = self.instance.part_of.belong_to.all() 
      self.fields['sender'].queryset = users 
      self.fields['receiver'].queryset = users 

而且,爲什麼limit_choices_to作品爲你的榜樣,而不是動態的有用。

Django只是將limit_choices_to表達式作爲一個額外的過濾器應用於ModelForm字段queryset。您的表達{dialog: 1}在語義上與在我的示例中將UserProfile.objects.filter(dialog=1)的結果指派給查詢集的語義上沒有區別。

Django不知道具有該ID的對話是否作爲UserProfile上的關係存在,它只是應用過濾器。在這種情況下,存在一個ID爲1的對話框,因此它可以運行。如果你在你的例子中粘貼一個無效的對話框id,它會計算一個空的查詢集,你將在你的表單中得到0個選擇。

它不能動態,因爲在limit_choices_to中,您只能爲UserProfile模型創建過濾器表達式。您無權訪問字段所屬的消息實例,也無法訪問消息所屬的對話模型...因此,您無法創建過濾器來動態限制這些消息。

創建您自己的ModelForm並限制該字段的查詢集,那裏有您需要的信息,是正確的方法。

+0

恐怕我必須這樣做,但首先:它不是_forms.py_它的_models.py_第二:奇怪我可以用數字訪問,所以它已經知道有這樣的對話對象,但不能動態地執行它( – wasd 2015-03-25 16:02:23

+0

我不知道你指的是什麼與models.py和forms.py – 2015-03-25 18:20:09

+0

更新我的答案來解釋更多如何limit_choices_to工作/ doesn' t按照你想要的方式工作... – 2015-03-25 19:18:46