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"]