2015-03-25 110 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