如何使用 django-filter 过滤 ManyToMany 字段

问题描述 投票:0回答:1

如何使用 django-filter 过滤 ManyToMany 字段

我想在模板上显示一个输入字段,您可以在其中过滤学生以获得这些结果:

  1. 所有说英语的学生(Student.languages 包含'English')
  2. 所有说英语和德语的学生(Student.languages 包含“英语”和“德语”)
# 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']

但是没有用,滤镜没有效果。

django django-filter manytomanyfield
1个回答
1
投票

您可以在

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

然后您将信息添加到学生与语言的组合中,技能水平是什么。

© www.soinside.com 2019 - 2024. All rights reserved.