【发布时间】:2018-05-01 18:51:40
【问题描述】:
我有一个相当复杂的查询,它生成了一个 Django RawQuerySet。此特定查询返回一些不属于RawQuerySet 所基于的模型的字段,因此我使用.annotate(field_name=models.Value('field_name')) 将其作为属性附加到RawQuerySet 中的各个记录。最重要的自定义字段实际上是 uuid,我使用 Django 的 {% url %} 功能来编写 URL。
问题是:我没有在我的应用程序中使用标准的uuids,我使用的是SmallUUIDs(压缩的UUID。)它们作为本机uuidfields 存储在数据库中,然后转换为更短的字符串在蟒蛇。所以我需要以某种方式将作为RawQuerySet 的一部分返回的uuid 转换为SmallUUID,以便在模板中使用以生成URL。
我的代码看起来有点像这样:
query = "SELECT othertable.uuid_field as my_uuid FROM myapp_mymodel
JOIN othertable o ON myapp_mymodel.x = othertable.x"
MyModel.objects.annotate(
my_uuid=models.Value('my_uuid'),
).raw(query)
现在这里有一个合乎逻辑的解决方案,models.Value 有一个可选的 kwarg,称为 output_field,使代码如下所示:
MyModel.objects.annotate(
my_uuid=models.Value('my_uuid', output_field=SmallUUIDField()),
).raw(query)
但它不起作用!该 kwarg 被完全忽略,属性的类型基于从数据库返回的类型,而不是 output_field 中的内容。在我的例子中,我得到一个 uuid 输出,因为 Postgres 正在返回一个 UUID 类型,但是如果我要将查询更改为 SELECT cast othertable.uuid_field as text) as my_uuid 我会以字符串的格式获得属性。在这种情况下,Django(至少版本 1.11.12)似乎并不真正关心 kwarg 中的内容。
以下是我认为的潜在解决方案,排名不分先后:
- 以某种方式更改查询的格式(在 Django 或 SQL 中)
- 在将生成的 RawQuerySet 传递给视图之前以某种方式更改它
- 更改模板中的某些内容以将 UUID 转换为 smalluuid,以便在 URL 反向过程中使用。
接下来我最好的步骤是什么?
【问题讨论】:
-
由于
SmallUUIDField不是原生 Django 模型字段类型,您确定它与您要执行的操作兼容吗?如果你想要文本输出,为什么不直接使用TextField? -
实际上,在这种情况下,
output_field甚至会忽略本机模型字段类型。您可以将output_field设置为IntField,如果它是来自数据库的字符串,它仍会显示为字符串。事实上,它甚至没有显示为标准的 django“字段”,它只是显示为一个字符串(或者在我的情况下为 uuid。)它确实只是返回数据库返回的内容。我需要 UUID 的缩短版本,这是该字段的自定义功能。
标签: django django-models django-queryset django-postgresql