Django Annotation F() value
У меня есть вопрос относительно аннотаций Django:
tickers = {
"BCO": 10.0,
"AIR": 50.0,
}
assets = Asset.objects.annotate(
price=(tickers[F("fk_security__ticker_symbol")]))
Я хотел бы аннотировать значение из словаря к активу, но всегда получаю ошибку ключа: F(fk_security__ticker_symbol)
Что я делаю не так? Возможно ли это вообще сделать? Заранее большое спасибо!
Если это поможет, вот моя модель:
class Asset(models.Model):
fk_security = models.ForeignKey(Security, on_delete=models.CASCADE, blank=False, verbose_name="Security",related_name="security",
)
class Security(models.Model):
ticker_symbol = models.CharField(
max_length=5,
verbose_name="Ticker Symbol",
default="",
)
Если вам не нужно фильтровать, агрегировать или что-то еще по цене, я бы посоветовал не делать это в ORM, поскольку JOINing с словарем будет медленным и сложным.
Так что мы можем сделать это с помощью:
tickers = {
'BCO': 10.0,
'AIR': 50.0,
}
assets = Asset.objects.select_related('fk_security')
for asset in assets:
asset.price = tickers.get(asset.fk_security.ticker_symbol)
иначе мы можем использовать:
from django.db.models import Case, Value, When
Asset.objects.annotate(
price=Case(
*[
When(fk_security__ticker_symbol=k, then=Value(v))
for k, v in tickers.items()
]
)
)
Но оба варианта - не хорошая идея. Лучший способ - работать с моделью, хранящей цены, и делать JOINы.
Note: Normally one does not add a prefix
fk_…
to aForeignKey
field, since Django will automatically add a "twin" field with an…_id
suffix. Therefore it should besecurity
, instead of. You can use thefk_security
db_column=…
parameter [Django-doc] to specify the name of the column in the database if you want to name this differently from the field name.