python - 在 Django 中使用具有不同字段类型的注释和案例

标签 python django postgresql django-annotate

我有一个包含这些字段的模型:

class ModelA(models.Model):
    parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.PROTECT, related_name='child')
    number = models.PositiveIntegerField()
    text_code = models.CharField(max_length=255, blank=True, null=True)

我想使用带有这些规则的注释和案例对该模型进行查询:

  • 当 parent 为 null 时,它返回 text_code 字段
  • 当 parent 不为 null 时返回 parent__number 字段

我可以用 PostgreSQL 中的 SQL 实现它,例如:

CASE WHEN "ModelA"."parent_id" IS NOT NULL 
    THEN T3."number"**::integer** 
ELSE "ModelA"."text_code"**::integer** END AS "control_field" 

但我无法使用 Django ORM 实现。我尝试了以下方法:

query = ModelA.objects.all().select_related('parent').annotate(
    control_field=Case(
        When(parent_id__isnull=False, then='parent__number'),
        default='text_code',
        output_field=IntegerField(),
    ),
)

但是当我调用查询结果时,它引发了以下错误:

django.db.utils.ProgrammingError: CASE types character varying and integer cannot be matched

我知道这是一个数据库错误,因为 django 构造的 SQL 结果没有添加 ::integer

CASE WHEN "ModelA"."parent_id" IS NOT NULL 
    THEN T3."number" 
ELSE "ModelA"."text_code" END AS "control_field"

我该如何解决这个问题?我正在使用 Django 1.11

最佳答案

答案是,使用 Cast:

query = ModelA.objects.all().select_related('parent').annotate(
    control_field=Case(
        When(parent_id__isnull=False, then=Cast('parent__number', IntegerField())),
        default=Cast('text_code', IntegerField()),
        output_field=IntegerField(),
    ),
)

关于python - 在 Django 中使用具有不同字段类型的注释和案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51518005/

相关文章:

python - 使用 setuid/setgid 包装器执行 Python 命令

python - 无法使用 seaborn barplot 绘制数据框

python - 如何将 postgresql 字段名称输出到字典中,而不是仅在 python 中输出列名称?

database - 在运行测试之前在 Django 中创建数据库条目

ruby-on-rails - 测试环境中未启用 Postgresql 扩展

ruby-on-rails - 如何让 postgres 在 big sur 上启动?

Python:提取不同的表并将它们合并到一个 CSV 文件中

python - 如何删除字符串中的重复字符?

没有外键的两个表之间的django queryset

django - 亚马逊 FPS vs PayPal vs Google Checkout