django - Django - 提供 .values() 时,StringRelatedField() 不应用于查询结果
问题描述
在我的 Django 应用程序中,我发现StringRelatedField()
当序列化程序用于已指定一组字段值的过滤器查询时,没有应用序列化程序类上的 a - 尽管如果查询返回所有字段它确实有效。唷,那是一口,让我分解一下-
我有两个模型,Report
和User
;每个Report
都与一个User
. 理想情况下,我想通过get_queryset
和在每个报告记录中查询报告,关联的值user
应该是模型上方法StringRelatedField()
的返回值(即用户的名字和姓氏)的结果。__str__
User
如果我的查询返回所有字段,这完美地工作......所以查询
Report.objects.filter(location__within=some_other_model.region)
成功了。
但是,我发现只查询values
我实际需要的可以极大地提高性能,所以我更喜欢这样查询:
Report.objects.filter(location__within=some_other_model.region).values('id',
'location',
'user',)
但是该查询的结果具有User
表中记录的 UUID 外键,它们似乎没有被替换为StringRelatedField()
.
下面,我有 的视图和序列化程序Report
,以及User
模型。
# report/view.py
class ReportViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = ReportReadSerializer
def get_queryset(self):
some_other_model = get_object_or_404(Organization, pk='some_other_model_id')
# remove the .values() and this works correctly
return Report.objects.filter(location__within=some_other_model.region).values('id',
'location',
'user',)
# report/serializers.py
class ReportReadSerializer(serializers.GeoFeatureModelSerializer):
location = serializers.GeometryField(precision=4)
user = StringRelatedField()
class Meta:
model = Observation
geo_field = 'location'
fields = [
'id',
'location',
'user',
]
# user/models.py
class User(SoftDeletionModel):
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
任何指导将不胜感激。
解决方案
这是预期的行为StringRelatedField()
StringRelatedField
返回值的表示str
形式,在您的情况下,用户具有整数值。如果您使用的是QuerySet
(不调用values()
),则用户将拥有一个User
实例,因此str
表示将为您提供正确的结果。
values('id', 'location', 'user', )
由于从单个表中获取值(请注意,调用user
不会在此处进行内部连接)并且没有出现问题的机会,您已经感受到了性能改进N+1
。但是,如果您使用 User 的str
方法,Django 将进行内部连接,并且会出现N+1
问题,因此您将遇到性能问题。
所以,你有两个选择,
- 使用值并忽略
User
' 表示 - 利用
select_related()
class ReportViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = ReportReadSerializer
def get_queryset(self):
some_other_model = get_object_or_404(Organization, pk='some_other_model_id')
return Report.objects.filter(
location__within=some_other_model.region
).select_related("user")
推荐阅读
- xml - 使用 xslt 从 xml 中删除换行符
- perl - 如何管理大型 Perl 环境从一个网络到另一个网络的传输
- bash - 仅在第一次匹配后在另一个文件中添加文件内容
- sapui5 - 如何将键字段作为变量而不是硬编码的键值传递给 OData 操作?
- c - 我怎样才能正确输入双关语?
- javascript - 提交时在 Aurelia 中找到图像并保存在 JSON 类型数组中
- javascript - 检查用户是否在亚像素精度时代滚动到底部
- php - 是否有运行 PHP v7.0 的 PSWebServiceLibrary.php 版本?
- javascript - 在 npm 构建期间找不到模块 @restart/context/forwardRef
- c# - C#中包含html转义字符的字符串大写