django - 在 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 文档。
为了用序列化器实现你需要的东西,你必须滥用视图、序列化器字段和序列化器本身。这根本不是它应该做的。另外,我认为您不需要对搜索进行太多验证。
自定义和使用Django 过滤器应该可以解决您的问题。
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
注意我没有测试上面的代码,但它应该告诉你如何解决这个问题。
推荐阅读
- javascript - 暂停 chart.js 水平滚动
- postgresql - Postgresql 自动清理耗时过长
- ios - 字符串中日期的可访问性语音一
- laravel - Laravel 7 无法解析的依赖解析 - 刀片组件
- flutter - 在flutter中按钮的onPressed回调中调用flutterTts.setStartHandler()方法是一个好习惯吗?(flutter_tts插件)
- javascript - 柏树对象模型中的错误:找不到模块'../ObjectModel/LoginPage'
- node.js - 如何在 nestjs 中间件中获取更改请求?
- python - 在 vshpere 客户端中将 VMware OVF 导出到本地磁盘的 Python 代码
- java - 如何使用 .sh 文件运行 javafx?
- node.js - 如何管理要在 AWS Lambda 中使用的双向 TLS 的客户端证书