繁体   English   中英

在get_queryset()中使用序列化程序验证的数据

[英]Use serializer validated data in get_queryset()

我想基于查询参数为序列化程序编写自定义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'))

如果modelA的对象存在 - 验证将返回一个实例。 但我不想在我的if分支中的get_queryset()中执行相同的查询。

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不喜欢这个解决方案

我强烈反对您滥用序列化程序。 在快速分析您的问题后,我认为您需要DRF过滤

序列化程序处理request.data ,它只是Django request.POSTrequest.FILES在你的get_queryset实现中你在request.query_params中进行查找,在Django术语中是request.GET 检查DRF文档。

为了通过Serializers实现您所需的功能,您必须滥用Views,Serializer Fields和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

注意我没有测试上面的代码,但它应该告诉你如何解决这个问题。

如何关于user = get_object_or_404(queryset, id=ModelA_id) 它对我来说看起来更好。 get_object_or_404将捕获您需要的对象,或者将引发Not Found响应。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM