Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在Django DRF中过滤嵌套序列化程序的字段_Python_Django_Django Rest Framework - Fatal编程技术网

Python 如何在Django DRF中过滤嵌套序列化程序的字段

Python 如何在Django DRF中过滤嵌套序列化程序的字段,python,django,django-rest-framework,Python,Django,Django Rest Framework,我有两个模型,分别是“学校”和“学生”。我为学校创建了每个序列化程序和嵌套序列化程序,并将学生序列化程序作为嵌套字段 在这里,我想使用“django filters”对序列化程序的字段应用过滤器,它几乎可以工作,但是……问题是,当我过滤嵌套字段,即“学生字段”时,它不会显示所需的结果。 我的模型是: class School(models.Model): name = models.CharField(max_length=256) principal = models.Char

我有两个模型,分别是“学校”和“学生”。我为学校创建了每个序列化程序和嵌套序列化程序,并将学生序列化程序作为嵌套字段

在这里,我想使用“django filters”对序列化程序的字段应用过滤器,它几乎可以工作,但是……问题是,当我过滤嵌套字段,即“学生字段”时,它不会显示所需的结果。 我的模型是:

class School(models.Model):
    name = models.CharField(max_length=256)
    principal = models.CharField(max_length=256)
    location = models.CharField(max_length=256)
    is_government = models.BooleanField(default=True)

    def __str__(self):
        return self.name


class Student(models.Model):
    name = models.CharField(max_length=256)
    age = models.PositiveIntegerField()
    school = models.ForeignKey(School,related_name='students',on_delete = models.CASCADE)
    is_adult  = models.BooleanField(default=True)

    def __str__(self):
        return self.name
我的序列化程序是:

class SchoolSerializer(serializers.ModelSerializer):

    def __init__(self, *args, **kwargs):
    # Don't pass the 'fields' arg up to the superclass
        # Instantiate the superclass normally
        super(SchoolSerializer, self).__init__(*args, **kwargs)
        allow_students = self.context.get("allow_students",None)
        if allow_students:
            self.fields['students'] = StudentSerializer(many=True, context=kwargs['context'], fields=['name','age','is_adult']) 


    class Meta():
        model = School
        fields = '__all__'


class StudentSerializer(DynamicFieldsModelSerializer):
    class Meta():
        model = Student
        fields = '__all__'
以下是我在视图中使用的过滤器:

from django_filters.rest_framework import DjangoFilterBackend
from django_filters import FilterSet
from django_filters import rest_framework as filters


class SchoolStudentAPIView(generics.ListAPIView, mixins.CreateModelMixin):
    queryset              = School.objects.all()
    serializer_class      = SchoolSerializer

    filter_backends       = (DjangoFilterBackend,)
    filter_fields         = ('is_government','students__is_adult')
这里的问题是,当我搜索students_uuis_u成人(这是一个嵌套字段)时,它会过滤掉成人学生和非成人学生的列表

有人能补充一些额外的东西或提供另一种解决方案吗?谢谢你解决了这个问题 首先,Django Rest框架没有执行您期望的查询。让我们看看如何检查

调试实际查询的一种方法是向SchoolStudentAPIView类添加自定义列表方法,如下所示:

def listself,请求,*args,**kwargs: resp=super.listrequest,*args,**kwargs 从django.db导入连接 printconnection.Query或在此处设置断点 返回响应 这个方法只是将所有执行的查询转储到控制台

connection.querys的最后一个元素是我们应该关注的。它将是一个dict,其sql键类似于:

选择'school`.'id`、'school`.'name`、'school`.'location`、'school`.'isu government`` 从'school'在'school'上的'school'内部连接'student'。'id`='student`.'school\u id` 其中'student`.'u成人`=1 此查询意味着SchoolSerializer将通过至少有一名成人学生的所有学校

顺便说一下,同一所学校可以出现多次,因为上面的查询为每个成年学生生成一行

最后,SchoolSerializer显示学校中的所有学生,而不考虑任何过滤选项:这就是此行的目的

如果允许学生: self.fields['students']=studentserializerName=True。。。 建议的解决方案 在序列化程序中找不到简单的解决方案。也许更简单的方法是在SchoolStudentAPIView类中编写一个自定义列表方法

该方法将:

查找查询字符串参数student\u is\u成人:如果有,该方法将在我命名为filtered\u students的queryset中的每个学校上创建一个自定义字段,并使该字段指向正确的student queryset。 将上下文参数传递给SchoolSerializer,告诉它已筛选学生 SchoolSerializer类将以两种不同的方式填充其students字段,具体取决于上下文参数的存在与否。特别是,如果传递的上下文中存在students\u is\u成人密钥,则StudentSerializer字段将具有源kwarg

代码:

类SchoolStudentAPIViewgenerics.ListAPIView,mixin.CreateModelMixin: ... def listself,请求,*args,**kwargs: 学校=self.get\u queryset ctx={} 如果request.query参数中的“学生”是“成人”: 按成人过滤=boolrequest.query参数['students\uuu是成人'] ctx={ “学生是成人”:按成人筛选, “允许学生”:对, } 对于学校的学生: s、 过滤的学生=s.students.filteris\u成人=按成人过滤 ser=SchoolSerializerdata=schools,many=True,context=ctx ser.U有效吗 返回应答器数据 类SchoolSerializerserializers.ModelSerializer: 定义初始自我,*args,**kwargs: 超级学校序列化程序,self.\u初始参数,**kwargs allow_students=self.context.getallow_students,无 如果允许学生: 如果已筛选学生,则将“源”更改为自定义字段 filter\u active=self.context.getposts\u处于活动状态,无 如果筛选器_未处于活动状态,请执行以下操作: stud=StudentSerializer source='filtered_students',many=True, context=kwargs['context'], 字段=[“姓名”、“年龄”、“是否成年”] 其他: stud=StudentSerializer many=True,context=kwargs['context'], 字段=[“姓名”、“年龄”、“是否成年”] self.fields['student']=stud
谢谢@paolo,但这并没有解决问题,相反,现在它只显示自己的字段,这意味着不显示嵌套字段。列表代码没有设置所需的dict键-我已修复。请再试一次。无论如何,试着调试代码以了解发生了什么。例如,PyCharm有一个很好的内置调试器。