Как создать словарь с двумя наборами запросов из разных моделей, используя общее поле DateTimeField в качестве ключей словаря?
Я хочу создать словарь из двух моделей, имеющих общее поле dt
. Это поле должно быть ключами словаря, а поля value
и last
- значениями ключей. Каков наиболее эффективный способ сделать это?
class Balance(models.Model):
value = models.FloatField(default=0)
dt = models.DateTimeField()
class Price(models.Model):
last = models.FloatField(default=0)
dt = models.DateTimeField()
Желаемый результат будет примерно таким :
{
"2022-10-11T00:00:00Z": {
"value": 151.05,
"last": 1,
},
"2022-10-10T00:00:00Z": {
"value": 151.1,
"last": 1.1,
},
"2022-10-09T00:00:00Z": {
"value": 152,
"last": 1.1,
},
"2022-10-08T00:00:00Z": {
"value": 154,
"last": 1.23,
}
}
Я мог бы перебирать все словари кверисетов с помощью вложенного цикла и искать элементы с общим dt
затем заполнять ключ:значение в новом словаре, но это не элегантно и я не верю, что это эффективно.
Это подойдет, но не уверен в эффективности.
import datetime
balance = Balance.objects.annotate(date_only=Cast('dt',DateField())).values("date_only", "value")
price = Price.objects.annotate(date_only=Cast('dt',DateField())).values("date_only", "last")
data = {}
for (a, b) in zip(balance, price):
str_date = a['date_only'].strftime("%Y/%m/%d")
if a['date_only'] == b['date_only']:
data[str_date] = {}
data[str_date]['last'] = b['last']
data[str_date]['value'] = a['value']
print(data)
Эта версия должна справиться с дополнительными несбалансированными строками Price, описанными OP в комментариях:
balances = (
Balance
.objects
.annotate(date_only=Cast('dt', DateField()))
.order_by("dt")
.values("date_only", "value")
)
balance_dates = {balance.dt for balance in balances}
prices = (
Price
.objects
.annotate(date_only=Cast('dt', DateField()))
.filter(dt__in=balance_dates)
.order_by("dt")
.values("date_only", "last")
)
data = {
balance['date_only'].strftime("%Y/%m/%d"): {
"last": price["last"],
"value": balance["value"],
}
for (balance, price) in zip(balances, prices)
}
Эффективность на стороне Python примерно такая же, как в ответе Хемала Пателя (на котором основан этот ответ)
Но запрос в db выиграет от индекса на dt
столбце и может быть медленным, если таблицы очень большие.
В этом случае вам, вероятно, лучше использовать необработанный SQL для вывода набора данных, который вы хотите.