【问题标题】:Django Rest Framework how to filter nested data?Django Rest Framework 如何过滤嵌套数据?
【发布时间】:2021-02-27 06:37:08
【问题描述】:

我想过滤嵌套数据,这些是我的序列化器和视图

型号:

class Employee(models.Model):
    employee_identity = models.CharField(max_length=255, blank=True, null=True)
    full_name = models.CharField(max_length=255, blank=True, null=True)
    place_birth = models.CharField(max_length=255, blank=True, null=True)
    date_birth = models.DateField(blank=True, null=True)
    role = models.CharField(max_length=255, blank=True, null=True)
    no_hp = models.CharField(max_length=255, blank=True, null=True)
    address = models.CharField(max_length=255, blank=True, null=True)
    class Meta:
        managed = False
        db_table = 'employee'

class Penalty(models.Model):
    employee = models.ForeignKey(Employee,on_delete=models.CASCADE)
    type = models.CharField(max_length=255, blank=True, null=True)
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    doc = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'penalty'

序列化器:

class PenaltySerializer (serializers.ModelSerializer):
    employee_identity = serializers.CharField(source="employee.employee_identity")
    month = serializers.SerializerMethodField()
    year = serializers.SerializerMethodField()

    def get_month(self,obj):
        value_start_date = obj.start_date
        month_value = value_start_date.strftime("%b")
        return bulan_value
    def get_year(self,obj):
        value_start_date = obj.start_date
        year_value = value_start_date.strftime("%Y")
        return year_value
    class Meta:
        model = Penalty
        fields = ('id','employee','employee_identity','type','start_date','end_date','month','year') 

class EmployeeSerializer (serializers.ModelSerializer):
    penalty = PenaltySerializer(many=True,read_only=True)

    class Meta:  
        model = Employee
        fields =  ('employee_identity','full_name','penalty')

观看次数:

class EmployeeViewSet(viewsets.ModelViewSet):
    queryset = Employee.objects.all()
    serializer_class = PegawaiSerializer
    http_method_names = ['get','head']
    pagination_class = LimitPagination

class PenaltyViewSet(viewsets.ModelViewSet): 
    queryset = Penalty.objects.all()
    serializer_class = PenaltySerializer
    http_method_names = ['get','head']
    pagination_class = LimitPagination
    filter_backends = [filters.SearchFilter,DjangoFilterBackend]
    filter_fields = ['employee','type']
    search_fields = ['^start_date']

class DetailDataEmployeeViewSet(viewsets.ModelViewSet):
    queryset = Employee.objects.all()
    serializer_class = EmployeeSerializer
    http_method_names = ['get','head']
    pagination_class = LimitPagination
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['id','employee_identity']

没有日期过滤器的结果

 "results": [
         {
             "id": 13886,
             "employee_identity": "A3014",
             "full_name": "AAAA",
             "penalty": []
         },
         {
             "id": 13887,
             "employee_identity": "A3015",
             "full_name": "BBB",
             "penalty": [
               {
                     "id": 1,
                     "employee": 20924,
                     "employee_identity": "A3015",
                     "type": "low",
                     "start_date": "2021-01-01",
                     "end_date": "2021-01-02",
                     "month": "Jan",
                     "year": "2021"
                 },
                 {
                     "id": 2,
                     "employee": 20924,
                     "employee_identity": "A3015",
                     "type": "low",
                     "start_date": "2021-02-11",
                     "end_date": "2021-02-12",
                     "month": "Feb",
                     "year": "2021"
                 }
              ]
         }

如果我按日期过滤数据,我想要的结果(例如:过滤日期:2021-01)

"results": [
            {
                "id": 13886,
                "employee_identity": "A3015",
                "full_name": "BBB",
                "penalty": [
                  {
                        "id": 1,
                        "employee": 20924,
                        "employee_identity": "A3015",
                        "type": "low",
                        "start_date": "2021-01-01",
                        "end_date": "2021-01-02",
                        "month": "Jan",
                        "year": "2021"
                    }
                 ]
            }

我可以根据 DetailDataEmployeeViewSet 中的 DjangoFilterBackend 生成结果,但我不知道如何按日期生成惩罚数据。我如何让它发生?提前致谢。

【问题讨论】:

    标签: django api rest django-rest-framework


    【解决方案1】:

    一个简单的解决方案是扩展 ViewSet 的 filter_queryset 方法

    class DetailDataEmployeeViewSet(viewsets.ModelViewSet):
        queryset = Employee.objects.all()
        serializer_class = EmployeeSerializer
        http_method_names = ['get','head']
        filter_backends = [DjangoFilterBackend]
        filterset_fields = ['id','employee_identity']
    
        def filter_queryset(self, queryset):
            queryset = super().filter_queryset(queryset)
            start_date = self.request.query_params.get("start_date", None)
    
            if start_date is not None:
                print(start_date)
                queryset = queryset.filter(penalty__start_date=start_date)
    
            return queryset
    

    用法:

    GET /employee/?start_date=2021-02-27

    【讨论】:

    • 感谢您的回答,但是在我使用 2021-01 过滤后,start_date 2021-02 的惩罚数据也会显示出来。我正在使用惩罚__start_date__contains=start_date
    猜你喜欢
    • 2017-10-19
    • 2015-09-21
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 2018-06-04
    • 2017-12-28
    • 2015-03-25
    • 2019-07-11
    相关资源
    最近更新 更多