基于同一模型中的另一个外键,动态限制Django模型中的ForeignKey选项 [英] Dynamically limit choices for Foreignkey in Django models based on another foreign key in the same model

查看:168
本文介绍了基于同一模型中的另一个外键,动态限制Django模型中的ForeignKey选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

类对话框(models.Model):
belong_to = models.ManyToManyField(用户配置)

类消息(models.Model):
#此消息所属的对话框
part_of = models.ForeignKey(Dialog)

发送消息的用户
sender = models.ForeignKey(UserProfile,related_name ='sender ')
#收到消息的用户
receiver = models.ForeignKey(UserProfile,related_name ='receiver')

我想要做的是限制发送者和接收者字段的选择,以便他们只能是整个对话所属的用户。
我试过这个:

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

id = 1的对话的成员。我想知道这是否可以动态地完成?

解决方案

我不相信有什么办法像你一样动态过滤想要使用limit_choices_to,因为你将无法访问所需的对象来形成这样的查询。

相反,你应该创建自己的模型形式的消息和设置那里的那些字段的查询集。类似下面的...

$ p $ 类MessageForm(forms.ModelForm):
类Meta:
模型= Message
$ b def __init __(self,* args,** kwargs):
super(MessageForm,self).__ init __(* args,** kwargs)

如果self.instance.part_of和self.instance.part_of.id:
用户= self.instance.part_of.belong_to.all()
self.fields [ '发送']查询集=用户
self.fields ['receiver']。queryset = users

为什么 limit_choices_to 适用于您的示例,但不是动态的。


$ b Django只处理 limit_choices_to 表达式作为应用于ModelForm字段queryset的额外过滤器。您的表达式 {dialog:1} 在语义上与分配 UserProfile.objects.filter(dialog = 1) / code>到我的例子中的查询集。



Django不知道具有该id的对话是否作为UserProfile上的关系存在,过滤。在这种情况下,存在一个id为1的对话框,因此它可以运行。如果你在你的示例中粘贴一个无效的对话框id,它会计算一个空的查询集,你将在你的表单中得到0个选项。

它不能动态因为在 limit_choices_to 中,您只能为UserProfile模型创建一个过滤器表达式。您无权访问该字段所属的Message实例,也无法访问该消息所属的Dialog模型...因此您无法创建过滤器来动态限制这些字段。



创建您自己的ModelForm并限制字段的查询集,在那里您有需要的信息,是正确的方法。


I have these models:

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')

What I want to do is limit the choices for the sender and receiver fields so that they can only be the users to which the whole dialog belongs. I tried this:

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

which limits the choices but only for members of dialog with id=1. I'm wondering if this can be done dynamically?

解决方案

I don't believe there is any way to dynamically filter like you want using limit_choices_to, as you won't have access to the needed objects to form such a query there.

Instead you should probably create your own model form for message and set the queryset for those fields there. Something like below...

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

Further, why limit_choices_to works for your example, but is not dynamically useful.

Django simply processes the limit_choices_to expression as an extra filter to be applied to the ModelForm fields queryset. Your expression {dialog: 1} is semantically no different than if you were to assign the result of UserProfile.objects.filter(dialog=1) to the queryset in my example.

Django does not know if a dialog with that id exists as a relation on the UserProfile, it just applies the filter. In this case a dialog with id 1 exists and so it works out. If you stick an invalid dialog id in your example instead..it would evaluate to an empty queryset and you would have get 0 choices in your form.

It cannot be dynamic because in limit_choices_to you can only create a filter expression for the UserProfile model. You have no access to the Message instance the field belongs to, nor the Dialog model the message belongs to...hence you cannot create a filter to dynamically limit to those.

Creating your own ModelForm and limiting the queryset for the field there, where you have the information you need, is the proper way to do it.

这篇关于基于同一模型中的另一个外键,动态限制Django模型中的ForeignKey选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆