Использовать проверенные данные сериализатора в get_queryset () - PullRequest
0 голосов
/ 16 октября 2018

Я хочу написать собственный метод get_queryset () для сериализатора на основе параметров запроса.

Вот мой сериализатор:

class SearchRequestSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=255, required=False)
    nickname = serializers.RegexField(
        r'^(?!(.*?\_){2})(?!(.*?\.){2})[A-Za-z0-9\._]{3,24}$',
        max_length=24,
        min_length=3,
        required=False,
    )
    modelA_id = serializers.CharField(max_length=11, min_length=11,
                                      required=False)

    def validate_modelA_id(self, value):
        queryset = modelA.objects.filter(id=value)
        if queryset.exists():
            return queryset.first()
        else:
            raise serializers.ValidationError(_('Not found'))

Если объект модели A существует - проверка вернет экземпляр,Но я не хочу выполнять тот же запрос в get_queryset () в моей ветви if.

def get_queryset(self):
    name = self.request.query_params.get('name', None)
    nickname = self.request.query_params.get('nickname', None)
    queryset = User.objects.filter(Q(name__contains=name)|Q(nickname__contains=nickname))
    if 'modelA_id' in self.request.query_params:
       # in this case will be annotated extra field to queryset
       # extra field will be based on 'modelA' instance which should be returned by serializer
    return queryset

Я нашел только одно решение - добавьте следующую строку в мой метод GET:

self.serializer = self.get_serializer()

Чем можно будет получить проверенные значения в моемметод get_queryset ().Но PyCharm не нравится это решение

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

У меня сильное впечатление, что вы неправильно используете сериализатор.После быстрого анализа вашей проблемы, я думаю, вам нужно фильтрация DRF

Процесс сериализатора request.data, который под капотом пока только Django request.POST и request.FILESв вашей реализации get_queryset вы выполняете поиск в request.query_params, что в терминах Django равно request.GET.Проверьте документы DRF по этому вопросу.

Для того, чтобы добиться того, что вам нужно, с Serializer, вам придется злоупотреблять видами, полями Serializer и самим Serializer.Это просто не то, что он должен делать.Кроме того, я не думаю, что вам нужно так много проверять при поиске.

Настройка и использование Django Filter должны решить вашу проблему.

class UserFilter(filters.FilterSet):
    class Meta:
        model = User
        fields = ['name', 'nickname', 'modelA_id']

    def filter_queryset(self, queryset):
        name = self.form.cleaned_data.get('name', None)
        nickname = self.form.cleaned_data.get('nickname', None)
        queryset = queryset.filter(Q(name__contains=name)|Q(nickname__contains=nickname))
        if 'modelA_id' in self.form.cleaned_data:
            # in this case will be annotated extra field to queryset
            # extra field will be based on 'modelA' instance which should be returned by serializer
        return queryset


class UserListView(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
    filterset_class = UserFilter

ПРИМЕЧАНИЕ Я не тестировал код выше, но он должен показать вам, как решить эту проблему.

0 голосов
/ 16 октября 2018

Как насчет user = get_object_or_404(queryset, id=ModelA_id).Это выглядит лучше, как для меня.get_object_or_404 поймает нужный вам объект или вызовет Not Found ответ.

...