Django: как фильтровать по пользовательскому полю

У меня есть пользовательское поле в моем представлении extra action, которое добавляется путем переопределения to_representation() в сериализаторе. Я хочу добавить фильтр на основе этого значения. Как я могу этого добиться?

views.py

class MyFiltersetclass(filters.Filterset):
  name = filters.CharFilter(lookup_expr="exact", field_name="name")
  
  class Meta:
     model= MyModel
     fields = ["name"]

class MyViewset():
   ....
   @action(detail=True, method=["get"], queryset=MyModel.objects.filter(type=1), serilizer=MyModelSerializer, filterset_class=MyFiltersetclass)
   def action(self, request, *args, **kwargs):
      qs = self.get_object()
      queryset = obj.filter_queryset(queryset)

      page = obj.paginate_queryset(queryset)
      if page:
         serializer = obj.get_serializer(page, many=True)
      else:
         serializer = obj.get_serializer(queryset, many=True)

    return obj.get_paginated_response(serializer.data)

model.py

class MyModel(models.Model):
    name = models.TextField(blank=True, null=True)
    summaries = models.JSONField(blank=True, null=True)

    @property
    def summary(self):
        if not self.summaries:
            return {}

        return custom_func(self.summaries)

    class Meta:
        db_table = "model_view_1"
        managed = False

serializer.py

class MyModelSerializer(serializers.ModelSerializer):
    summary = serializers.ReadOnlyField()

    def to_representation(self, instance):
        data = super().to_representation(instance)
        summary = data.pop("summary")

        data["field_1"] = summary.get("field_1")

        return {**data}

    class Meta:
        model = MyModel
        exclude = ["summaries"]

Теперь я хочу добавить фильтр, который мог бы фильтровать на основе field_1 точно так же, как мы добавили фильтр для name в классе filterset.

Вы можете создать пользовательский метод фильтрации в своем MyFiltersetclass. Однако, поскольку поле field_1 не является непосредственным полем в модели базы данных, а является производным от свойства summary, вам придется по-другому обрабатывать логику фильтрации.

class MyFiltersetclass(filters.Filterset):
    name = filters.CharFilter(lookup_expr="exact", field_name="name")
    field_1 = filters.CharFilter(method="filter_field_1")

    def filter_field_1(self, queryset, name, value):
        filtered_queryset = []
        for obj in queryset:
            serializer = MyModelSerializer(obj)
            if serializer.data.get("field_1") == value:
                filtered_queryset.append(obj)
        return filtered_queryset

    class Meta:
        model = MyModel
        fields = ["name", "field_1"]
Вернуться на верх