如何以 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 QuerySet 中的多对多字段?