[英]django-rest-framework override get_queryset and pass additional data to serializer along 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.POST
和request.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.