首页 > 解决方案 > 有没有办法在 Django ORM 的 Case-When 查询中使用任何用户定义的 Python 方法?

问题描述

我已经定义了一个类及其必要的方法,如下所示。

class Location(models.Model):
    latitude = models.DecimalField(max_digits=20, decimal_places=8, default=Decimal("0.00"), null=True)
    longitude = models.DecimalField(max_digits=20, decimal_places=8, default=Decimal("0.00"), null=True)

    @staticmethod
    def prepare_location_hotlink(latitude=None, longitude=None):
        returm mark_safe(s="<a class='inline-link' href='https://maps.google.com/maps?z=17&q={lat},{lng}' target='_blank'>{lat}, {lng}</a>".format(lat=latitude, lng=longitude))

    @classmethod
    def retrieve_location_data(cls):
        annotated_case_query = {
            "location": Case(
                When(Q(location__isnull=False, longitude__isnull=False),
                     then=cls.prepare_location_hotlink(latitude=F("latitude"), longitude=F("longitude"))
                ), default=Value("Not Available"), output_field=CharField()
            )
        }
        return [loc for loc in cls.objects.annotate(**annotated_case_query).values_list("location", flat=True)]

在这里,在retrieve_location_data方法中,我尝试在查询中使用用户定义的( prepare_location_hotlink) Python 方法Case来检索所有作为热链接的位置数据。似乎不能以上述方式工作。但无论如何我都需要在查询中使用用户定义的python 方法Case,因为它检索和准备数据的速度要快得多。我已经研究并阅读了Django文档,但不幸的是,我找不到这种情况的任何解决方案。

关于如何在查询中使用任何用户定义的Python 方法,是否有任何适当且准确的方法?CaseDjango ORM

标签: pythondjangopostgresqldjango-orm

解决方案


您可以使用该Concat函数在数据库级别连接您的字符串,但是,在这种情况下,我会选择@Willem Van Onsem 答案,它更具可读性和可维护性。

您还可以包装您的查询集list()以使其成为一个列表。

from django.db.models import Q, Case, When, Value, F
from django.db.models.functions import Concat

annotated_case_query = {
    "location": Case(
        When(Q(location__isnull=False, longitude__isnull=False),
            then=Concat(Value("<a class='inline-link' href='https://maps.google.com/maps?z=17&q="), F("latitude"), Value(","), F("longitude"), Value("' target='_blank'>"), F("latitude"), Value(", "), F("longitude"), Value('</a>'))
        ), default=Value("Not Available"), output_field=CharField()
    )
}
return list(cls.objects.annotate(**annotated_case_query).values_list("location", flat=True))


推荐阅读