Django группировка по агрегации внешних ключей
У меня есть три таких модели:
class Coin(models.Model):
symbol = models.Charfield()
class User(models.Model):
phone_number = models.Charfield()
class Portfo(models.Model):
class Meta:
unique_together = (
"user",
"coin",
)
user = models.ForeignKey(
to=User,
on_delete=models.CASCADE,
null=False,
related_name="portfo",
)
coin = models.ForeignKey(
to=Coin,
on_delete=models.CASCADE,
null=False,
related_name="owners",
)
available = models.DecimalField(
max_digits=40,
decimal_places=20,
default=Decimal(0),
)
blocked = models.DecimalField(
max_digits=40,
decimal_places=20,
default=Decimal(0)
)
Я собираюсь вычислить значение portfo каждого пользователя, поэтому я хочу объединить объекты portfo, сгруппированные по пользователям, следующим образом:
[
{
"user_id":1,
"portfo":{
"coin_1_symbol":Decimal("1"),
"coin_2_symbol":Decimal("2"),...
}
},
{
"user_id":2,...
},...
]
или так:
[
{
"user_id":1,
"portfo":[
{"coin_symbol":"some_symbol","total":Decimal("1")},
{"coin_symbol":"some_symbol2","total":Decimal("2")},...
]
},...
]
Я пробовал агрегировать со значениями, но он возвращает такой результат:
>> Portfo.objects.exclude(available=0,blocked=0).annotate(total=Sum(F("available")+F("blocked"))).values("user_id","total","coin__symbol")
[{"user_id":1,"coin__symbol":"some_symbol","total":Decimal("1")},{"user_id":1,"coin__symbol":"some_symbol2", "total":Decimal("2")},...]
Есть ли способ сделать это с помощью django orm?
Вы не сможете сделать это просто используя annotate. Предпочтительный способ делать такие вещи - использовать вложенные сериализаторы.
На данный момент вы можете вручную преобразовать результат запроса в желаемый результат, используя следующий код.
for d in data: # data is your mentioned output from query.
user_id = d["user_id"]
if not converted_data:
converted_data.append({"user_id":user_id,"portfo":[d]})
continue
for c in converted_data:
if c["user_id"] == user_id:
c["portfo"].append(d)
break
else:
converted_data.append({"user_id":user_id,"portfo":[d]})