Django 根据条件获取带注释字段的值?
Django get a value for annotated field based on condition?
我有几个简单的模型,想用基于条件的值的字段注释查询。
class Book(models.Model):
price = models.DecimalField('Price', null=True, default=None, max_digits=32, decimal_places=2)
...
class Config(models.Model):
city_prices = models.JSONField(default={"Paris": 10, "London": 15}, null=True)
...
我试过这样查询这个模型:
from django.db.models import F, When, Case, Subquery
config = Config.objects.first()
Book.objects.annotate(custom_price=Case(
When(price__isnull=False, then=F('price')),
When(price__isnull=True, then=Subquery(config.city_prices.get(F('city'))))
)
我尝试使用 OuterRef 而不是 F() 但没有成功 either.The 第一个“When”效果很好但第二个让我在两种情况下都使用 F() 或OuterRef()
When(price__isnull=True, then=Subquery(db_conf.get(OuterRef('city'))))
AttributeError: 'NoneType' object has no attribute 'all'
我试图去掉第二个“When”和铁杆城市名称中的“F()”,但又出现另一个错误。
When(price__isnull=True, then=Subquery(config.city_prices.get('London')))
AttributeError: 'int' object has no attribute 'all'
此错误表明我得到了“伦敦”的值,但子查询尝试查询它。所以我得出一个结论,当我在之前的查询中尝试使用“F('city')”时,它返回了 None,我认为这是因为 F('city') refer到 Config 模型而不是 Book。
我尝试了不同的方法,但也不成功。
>>>from django.db.models.expressions import RawSQL
>>>Books.objects.annotate(custom_price=RawSQL('SELECT d.city_prices ->> %s FROM CONFIG_CONFIG d WHERE d.id = 1', (F('price'),)))
ProgrammingError: can't adapt type 'F'
我在这里读到 F() 无法与 RawSQL 协作。认为问题是我在查询结束时得到 dict 并想从中提取价值。那么我怎样才能实现我的目标,即根据条件为带注释的字段获取值?
第一种方法:在申请时计算 custom_price
。它更简单,但您不能按 custom_price
订购图书
from django.db.models import F, When, Case, Subquery
config = Config.objects.first()
books = list(Book.objects.all())
for book in books:
if book.price is not None:
book.custom_price = book.price
else:
book.custom_price = config.city_prices.get(book.city)
第二种方法:计算 config.city_prices 的 Case-When 表达式并注释它:
from django.db.models import F, When, Case, Subquery, Value
config = Config.objects.first()
whens = []
for city, price in config.city_prices.items():
whens.append(When(city=city, then=Value(price))
Book.objects.annotate(custom_price=Case(*whens))
我有几个简单的模型,想用基于条件的值的字段注释查询。
class Book(models.Model):
price = models.DecimalField('Price', null=True, default=None, max_digits=32, decimal_places=2)
...
class Config(models.Model):
city_prices = models.JSONField(default={"Paris": 10, "London": 15}, null=True)
...
我试过这样查询这个模型:
from django.db.models import F, When, Case, Subquery
config = Config.objects.first()
Book.objects.annotate(custom_price=Case(
When(price__isnull=False, then=F('price')),
When(price__isnull=True, then=Subquery(config.city_prices.get(F('city'))))
)
我尝试使用 OuterRef 而不是 F() 但没有成功 either.The 第一个“When”效果很好但第二个让我在两种情况下都使用 F() 或OuterRef()
When(price__isnull=True, then=Subquery(db_conf.get(OuterRef('city'))))
AttributeError: 'NoneType' object has no attribute 'all'
我试图去掉第二个“When”和铁杆城市名称中的“F()”,但又出现另一个错误。
When(price__isnull=True, then=Subquery(config.city_prices.get('London')))
AttributeError: 'int' object has no attribute 'all'
此错误表明我得到了“伦敦”的值,但子查询尝试查询它。所以我得出一个结论,当我在之前的查询中尝试使用“F('city')”时,它返回了 None,我认为这是因为 F('city') refer到 Config 模型而不是 Book。
我尝试了不同的方法,但也不成功。
>>>from django.db.models.expressions import RawSQL
>>>Books.objects.annotate(custom_price=RawSQL('SELECT d.city_prices ->> %s FROM CONFIG_CONFIG d WHERE d.id = 1', (F('price'),)))
ProgrammingError: can't adapt type 'F'
我在这里读到 F() 无法与 RawSQL 协作。认为问题是我在查询结束时得到 dict 并想从中提取价值。那么我怎样才能实现我的目标,即根据条件为带注释的字段获取值?
第一种方法:在申请时计算 custom_price
。它更简单,但您不能按 custom_price
from django.db.models import F, When, Case, Subquery
config = Config.objects.first()
books = list(Book.objects.all())
for book in books:
if book.price is not None:
book.custom_price = book.price
else:
book.custom_price = config.city_prices.get(book.city)
第二种方法:计算 config.city_prices 的 Case-When 表达式并注释它:
from django.db.models import F, When, Case, Subquery, Value
config = Config.objects.first()
whens = []
for city, price in config.city_prices.items():
whens.append(When(city=city, then=Value(price))
Book.objects.annotate(custom_price=Case(*whens))