我想基于查询参数为序列化程序编写自定义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不喜欢这种解决方案
答案 0 :(得分:3)
我对您误用了Serializer印象很深。快速分析您的问题后,我认为您需要DRF filtering
Serializers处理request.data
,实际上是Django request.POST
和request.FILES
,但是在您的get_queryset
实现中,您在request.query_params
中进行查找,以Django的术语是request.GET
。查看有关此内容的DRF文档。
为了实现序列化器所需的功能,您将不得不滥用视图,序列化器字段和序列化器本身。这根本不是它应该做的。 另外,我认为您不需要在搜索中进行太多验证。
自定义和使用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
注意我没有在上面测试代码,但是它应该向您展示如何解决此问题。
答案 1 :(得分:0)
user = get_object_or_404(queryset, id=ModelA_id)
的情况如何。对我来说看起来更好。
get_object_or_404
将捕获您需要的对象,或引发Not Found
响应。