#python #django-rest-framework
#python #django-rest-framework
Вопрос:
Модель:
class EmployeeModel(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
Сериализатор:
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = EmployeeModel
fields = '__all__'
Viewset:
class EmployeeViewSet(viewsets.ModelViewSet):
queryset = EmployeeModel.objects.all()
serializer_class = EmployeeSerializer
filterset_class = EmployeeFilterSet
Мой EmployeeFilterSet выглядит следующим образом:
class EmployeeFilterSet(django_filters.FilterSet):
first_name__equals = django_filters.CharFilter(method='get_first_name_equals', field_name='first_name')
last_name__equals = django_filters.CharFilter(method='get_last_name_equals', field_name='last_name')
def get_first_name_equals(self, queryset, field_name, value):
query = Q()
for q_query in [Q(first_name__iexact=name) for name in (value.split(',') if value else [])]:
query |= q_query
return queryset.filter(query).all()
def get_last_name_equals(self, queryset, field_name, value):
query = Q()
for q_query in [Q(last_name__iexact=name) for name in (value.split(',') if value else [])]:
query |= q_query
return queryset.filter(query).all()
Как мы можем видеть, оба get_first_name_equals и get_last_name_equals имеют похожие определения. Единственная причина, по которой у меня разные методы, заключается в том, что выражения поиска имеют разные имена полей first_name__iexact и last_name__iexact в выражении цикла for. Есть ли способ, с помощью которого я могу использовать один метод, такой как get_equals(), и сформировать выражение поиска в выражении цикла for на основе переданного field_name? Это помогло бы избежать написания нескольких функций, выполняющих аналогичное выражение поиска, но с разными именами полей.
Комментарии:
1. Рассматривали ли вы возможность использования
field_name
вdict
расширении using — например**{f"{field_name}__iexact": name}
?2. @Rfroes87 спасибо за ответ. Я не понимаю, как именно мне нужно это сделать. Я пробовал это, но не работает :
for q_query in [Q{f"{field_name}__iexact": name} for name in (value.split(',') if value else [])]:
. Не могли бы вы помочь мне с функцией о том, как именно это можно сделать? Это было бы очень полезно.3. Измените его на
for q_query in [Q(**{f"{field_name}__iexact": name}) for name in (value.split(',') if value else [])]:
и повторите попытку.
Ответ №1:
Вы можете использовать универсальную функцию, которая (уже) получает field_name
и создает dict
на ее основе объединенную с __iexact
.
Это будет работать следующим образом:
class EmployeeFilterSet(django_filters.FilterSet):
first_name__equals = django_filters.CharFilter(method='get_field_equals', field_name='first_name')
last_name__equals = django_filters.CharFilter(method='get_field_equals', field_name='last_name')
def get_field_equals(self, queryset, field_name, value):
query = Q()
for q_query in [Q(**{f"{field_name}__iexact": name}) for name in (value.split(',') if value else [])]:
query |= q_query
return queryset.filter(query).all()
После расширения dict с **
аргументами Q
объект будет выглядеть как предполагаемый Q(first_name__iexact=name)
и так далее.