Django drf如何避免UniqueValidator中的objects.all()
我有一个表示用户的序列化器类Django drf如何避免UniqueValidator中的objects.all(),django,python-3.x,django-models,django-rest-framework,Django,Python 3.x,Django Models,Django Rest Framework,我有一个表示用户的序列化器类 class UserSerializer(BaseSerializer): uid = serializers.IntegerField(required=True) class Meta: model = User fields = "all" def validate(self, data): super().validate(data) validate_user_da
class UserSerializer(BaseSerializer):
uid = serializers.IntegerField(required=True)
class Meta:
model = User
fields = "all"
def validate(self, data):
super().validate(data)
validate_user_data(data=self.initial_data, user=self.instance)
return data
用户的uid应该是唯一的,因此当收到post请求时,我真正想要的是将uid字段更改为:
uid = serializers.IntegerField(required=True, validators=[validators.UniqueValidator(queryset=User.objects.all())])
这可能会起作用,问题是,这会触发一个sql查询,选择所有用户。
这可能会对系统产生非常大的影响,因为可能会有成千上万个这样的系统。
我真正想要的是将查询更改为User.objects.get(uid=uid)
,它不会从数据库中选择每个用户。
但是,因为我在uid的序列化程序定义中,所以不能使用uid=uid,因为uid刚刚被定义
(…)这可能会起作用,问题是,这将触发一个sql查询,该查询将选择所有用户
这是不正确的。Django将过滤queryset,但过滤本身发生在数据库端
这不会查询User
表中的所有项目。查询集不会被计算。它充当“根查询集”,将根据它构造查询
我们可以查阅:
使用asqs\U过滤器
:
因此,它将在数据库级别进行过滤,从而提高效率
(…)这可能会起作用,问题是,这将触发一个sql查询,该查询将选择所有用户
这是不正确的。Django将过滤queryset,但过滤本身发生在数据库端
这不会查询User
表中的所有项目。查询集不会被计算。它充当“根查询集”,将根据它构造查询
我们可以查阅:
使用asqs\U过滤器
:
因此,它将在数据库级别进行过滤,从而提高效率。请注意,这不会在数据库中触发.all()
。Django将安装queryset。此处提供的queryset
充当“根queryset”,其他查询可以从中产生。请注意,这不会在数据库中触发.all()
。Django将安装queryset。这里提供的queryset
充当“根queryset”,其他查询可以从中产生。
class UniqueValidator(object):
# ...
def __call__(self, value):
queryset = self.queryset
queryset = self.filter_queryset(value, queryset)
queryset = self.exclude_current_instance(queryset)
if qs_exists(queryset):
raise ValidationError(self.message, code='unique')
def filter_queryset(self, value, queryset):
"""
Filter the queryset to all instances matching the given attribute.
"""
filter_kwargs = {'%s__%s' % (self.field_name, self.lookup): value}
return qs_filter(queryset, **filter_kwargs)
def qs_filter(queryset, **kwargs):
try:
return queryset.filter(**kwargs)
except (TypeError, ValueError, DataError):
return queryset.none()
SELECT user.*
FROM user
WHERE uid = the_uid
AND id <> item_that_is_updated