如何使用 django-filter 过滤 ManyToMany 字段
我想在模板上显示一个输入字段,您可以在其中过滤学生以获得这些结果:
# models.py
class Student(models.Model):
name = models.CharField(...)
languages = models.ManyToManyField(Language)
class Language(models.Model):
language = models.CharField(...) # English / German / ...
level = models.CharField(...) # B1 / B2 / C1 / ...
#filters.py
import django_filters as filters
from .models import Employee
class EmployeeFilter(filters.FilterSet):
class Meta:
model = Employee
fields = ['name', 'languages']
我应该如何修改 EmployeeFilter 以使其准备好根据学生的口语过滤学生?
我试着像这样声明一个名为 languages 的类变量:
class EmployeeFilter(filters.FilterSet):
languages = filters.ModelChoiceFilter(
queryset = Languages.objects.all()
)
class Meta:
model = Employee
fields = ['name', 'languages']
但是没有用,滤镜没有效果。
您可以在
language
的languages
字段上进行过滤:
class EmployeeFilter(filters.FilterSet):
languages = filters.CharField(
field_name='languages__language', lookup_expr='iexact'
)
class Meta:
model = Employee
fields = ['name', 'languages']
这意味着您可以使用
English
或 english
进行过滤。
您也可以使用
ModelMultipleChoiceFilter
例如:
class EmployeeFilter(filters.FilterSet):
languages = filters.ModelMultipleChoiceFilter(
field_name='languages__language',
to_field_name='language',
conjoined=True,
queryset=Language.objects.all()
)
class Meta:
model = Employee
fields = ['name', 'languages']
话虽如此,造型看起来很奇怪。人们会期望级别是联结表的一部分,而不是语言本身,所以:
from django.db import Models
class Student(models.Model):
# …
languages = models.ManyToManyField('Language', through='LanguageSkill')
class Language(models.Model):
language = models.CharField(max_length=128, unique=True)
class LanguageSkill(models.Model):
language = models.ForeignKey(Language, on_delete=models.CASCADE)
student = models.ForeignKey(Student, on_delete=models.CASCADE)
level = models.CharField(
max_length=2, choices=[('B1', 'B1'), ('B2', 'B2'), ('C1', 'C1')]
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=('language', 'student'), name='unique_lang_per_student'
)
]
然后您将信息添加到学生与语言的组合中,技能水平是什么。