如何以 django 形式过滤多对多字段

Posted

技术标签:

【中文标题】如何以 django 形式过滤多对多字段【英文标题】:How to filter many to many field in django form 【发布时间】:2021-07-10 10:35:41 【问题描述】:

我有一个模型选举,它有一个与候选模型有多对多关系的“候选人”字段和一个与区域模型有一对多关系的“区域”字段。此外,Candidate 模型也有一个 region 字段,它与 Region 模型也有一对多的关系。

现在我创建了模型选举的模型形式。我的问题是如何过滤特定区域的候选人

这是我的模型和表格

 class Region(models.Model):
    region_name = models.CharField(max_length=200, null=True)
    region_id = models.CharField(max_length=20, null=True, unique=True)

    def __str__(self):
        return self.region_name

 class Candidate(models.Model):
    region = models.ForeignKey(Region, null=True, on_delete=models.SET_NULL)
    name = models.CharField(max_length=200, null=True)
    party_name = models.CharField(max_length=200, null=True)
    candidate_id = models.CharField(max_length=10, null=True, unique=True)

    def __str__(self):
        return self.name

 class Election(models.Model):
    admin = models.ForeignKey(Admin, null=True, on_delete=models.SET_NULL)
    region_name = models.ForeignKey(Region, null=True, on_delete=models.SET_NULL)
    region_id = models.CharField(max_length=200, null=True)
    date_created = models.DateField(null=True)
    candidates = models.ManyToManyField(Candidate)
    winner = models.CharField(max_length=200, blank=True) 

 class NewElectionForm(forms.ModelForm):
    class Meta:
        model = Election
        exclude = ['winner']
    def __init__ (self, *args, **kwargs):
        super(NewElectionForm, self).__init__(*args, **kwargs)
        self.fields["candidates"].widget = forms.widgets.CheckboxSelectMultiple()
                #below query is for testing
        #region = Region.objects.get(region_name='Mumbai')
        self.fields["candidates"].queryset = region.candidate_set.all()

每个地区都有一个管理员将发布此表单。由于 region_name 在这里是可变的,我无法运行 region.candidate_set 查询 如果上述方法不可行,还有其他解决方案吗?

【问题讨论】:

太宽泛了,REGION 变量是从哪里来的?是登录用户所在的地区,还是访问者提供的? 【参考方案1】:
Candidate.objects.filter(region__region_name="Mumbai")

以上查询将为您提供 region="Mumbai" 的所有候选人

【讨论】:

【参考方案2】:

由于表单将由区域管理员发布,并且 Election 模型具有 Admin 的外键,因此您可以按管理员过滤选举,从而为您提供来自管理员区域的候选人

在呈现此表单的 VIEW 中,添加一个方法

    class YourView(...):
        .....

        # This inserts 'admin' into kwargs of the form BEFORE it's loaded
        def get_form_kwargs(self):
            kwargs = super(YourView, self).get_form_kwargs()
            kwargs['admin'] = self.request.user
            return kwargs


    class NewElectionForm(forms.ModelForm):
        class Meta:
            model = Election
            exclude = ['winner']
        def __init__ (self, *args, **kwargs):

            #instanciate the admin variable that you inserted into kwargs
            admin = kwargs.pop('admin')
            super(NewElectionForm, self).__init__(*args, **kwargs)
            self.fields["candidates"].widget = forms.widgets.CheckboxSelectMultiple()
            self.fields["candidates"].queryset = Election.objects.filter(admin=admin)

或 如果您的 Admin 模型有 Region 字段

        def get_form_kwargs(self):
            kwargs = super(YourView, self).get_form_kwargs()
            kwargs['region'] = self.request.user.region
            return kwargs

然后查询候选模型为

    class NewElectionForm(forms.ModelForm):
        class Meta:
            model = Election
            exclude = ['winner']
        def __init__ (self, *args, **kwargs):

            #instanciate the region variable that you inserted into kwargs
            region = kwargs.pop('region')
            super(NewElectionForm, self).__init__(*args, **kwargs)
            self.fields["candidates"].widget = forms.widgets.CheckboxSelectMultiple()
            self.fields["candidates"].queryset = Candidate.objects.filter(region=region)

【讨论】:

以上是关于如何以 django 形式过滤多对多字段的主要内容,如果未能解决你的问题,请参考以下文章

Django 多对多字段过滤器列表

如何过滤和访问 Django QuerySet 中的多对多字段?

如何在引导选项卡块中按 django 模板中的多对多字段过滤对象

在Django中按关系字段过滤多对多关系

过滤多对多字段Django

Django Rest Framework(多对多字段上的 GET 过滤器)