Max*_*her 1 django django-models python-3.x 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_data(data=self.initial_data, user=self.instance)
return data
Run Code Online (Sandbox Code Playgroud)
用户在 uid 上应该是唯一的,所以当收到 post 请求时,我真正想要的是将 uid 字段更改为:
uid = serializers.IntegerField(required=True, validators=[validators.UniqueValidator(queryset=User.objects.all())])
Run Code Online (Sandbox Code Playgroud)
这可能会起作用,问题是,这将触发一个 sql 查询,该查询将选择所有用户。这可能会对系统产生非常大的影响,因为它们可能有数以万计。我真正想要的是将查询更改为User.objects.get(uid=uid),这不会从数据库中选择每个用户。但是,因为我在 uid 的序列化程序定义中,所以我不能使用 uid=uid 因为 uid 刚刚被定义。
(...) 这可能会起作用,问题是,这将触发一个 sql 查询,将选择所有用户。
这是不正确的。Django 将过滤查询集,但过滤本身发生在数据库端。
这不会查询User表中的所有项目。该查询集是不进行评估。它充当“根查询集”,将针对该查询构建查询。
我们可以在 GitHub 上查找源代码:
Run Code Online (Sandbox Code Playgroud)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')
这里查询集因此被过滤。这种过滤不是在 Python/Django 级别完成的,但它构造了一个过滤变体。事实上,如果我们查看filter_queryset函数,我们会看到:
Run Code Online (Sandbox Code Playgroud)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)
与qs_filter:
Run Code Online (Sandbox Code Playgroud)def qs_filter(queryset, **kwargs): try: return queryset.filter(**kwargs) except (TypeError, ValueError, DataError): return queryset.none()
如您所见,它将因此生成一个查询 User.objects.filter(uid=the_uid).exclude(pk=item_that_is_updated)
因此,它将检查User该数据库中是否存在与uid您设置的对象相同的对象,并排除您正在更新的对象(如果适用)。查询将如下所示:
SELECT user.*
FROM user
WHERE uid = the_uid
AND id <> item_that_is_updatedRun Code Online (Sandbox Code Playgroud)
因此,它将在数据库级别进行过滤,从而提高效率。
| 归档时间: |
|
| 查看次数: |
463 次 |
| 最近记录: |