DJANGO - Как отобразить несколько строк базы данных в одной строке в представлении
Я работаю с отношениями 1-N (1 билет имеет N сообщений), в представлении администратора я пытаюсь получить данные из базы данных, но N сообщений, относящихся к билету X, приходят в виде N строк (одна строка для каждого сообщения из билета X) в представлении (я отображаю его в таблице), мне нужно, чтобы N сообщений передавались только в одной строке, ниже приведен пример того, как это происходит и как мне нужно, чтобы это было.
Текущий выход:
| Ticket id | Msg id | Content | Status |
|:---------:|:-------:|:-----------------:|:------:|
| 1 | 1 | msg 1 of ticket 1 | Open |
| 2 | 2 | msg 1 of ticket 2 | Closed |
| 2 | 3 | msg 2 of ticket 2 | Closed |
| 3 | 4 | ticket 3 - msg 1 | Open |
| 4 | 5 | msg 1 of ticket 2 | Closed |
| 3 | 6 | ticket 3 - msg 2 | Open |
Как мне нужно:
| Ticket id | Msg id | Content | Status |
|:---------:|:-------:|:------------------------------------:|:------:|
| 1 | 1 | msg 1 of ticket 1 | Open |
| 2 | 2 | msg 1 of ticket 2; msg 2 of ticket 2 | Closed |
| 3 | 4 | ticket 3 - msg 1; ticket 3 - msg 2 | Open |
| 4 | 5 | msg 1 of ticket 2 | Closed |
Например, в детальном просмотре каждого билета мне удалось сделать то, что я хотел выше, но в этом случае я вытаскиваю только билет X и его сообщения, теперь, когда я вытаскиваю все из банка, я не знаю, как это сделать
Мой детальный просмотр каждого билета:
def ticket_by_id(request, ticket_id):
ticket = Ticket.objects.get(id=ticket_id)
mesTicket = MessageTicket.objects.filter(fk_ticket=ticket_id)
aux = ''
for itens in mesTicket:
aux += str(itens.content) + '; '
Если ваша база данных Postgres, вы можете агрегировать с помощью StringAgg или ArrayAgg. Возможно, что-то вроде этого:
from django.contrib.postgres.aggregates import StringAgg
from django.db.models import Min
messages = MessageTicket.objects\
.values('ticket_id', 'status')\
.annotate(
agg_content=StringAgg('content', ','),
min_msg_id=Min('msg_id'))
или
from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import Min
messages = MessageTicket.objects\
.values('ticket_id', 'status')\
.annotate(
agg_content=ArrayAgg('content'),
min_msg_id=Min('msg_id'))
Я мог бы решить ее следующим образом:
Consulte do banco (набор запросов)
tickets = Ticket.objects.order_by('id')[:]
mesTickets = MessageTicket.objects.order_by('id')[:]
array = [] # list array auxiliar
Для каждого тикета в 'tickets' я создал новое поле 'msg' и выделил тикет в массиве
for i in tickets:
i.msg = []
array.append(i)
Для каждого msg в 'mesTickets' я проверяю, равен ли msg.id билету.id, если да, то присваиваю msgs в списке 'msg' внутри 'массива'
{% for i in array %}
<tr>
<td>{{i.id}}</td>
<td>
<ul>
{% for j in i.msg %}
<li>{{j.content}}</li>
{% endfor %}
</ul>
</td>
</tr>
{% endofr %}
Мне удалось решить ее следующим образом:
Запрос из банка (набор запросов)
tickets = Ticket.objects.order_by('id')[:]
mesTickets = MessageTicket.objects.order_by('id')[:]
array = [] # list array auxiliar
Для каждого тикета в 'tickets' я создал новое поле 'msg' и распределил тикеты в массиве
for i in tickets:
i.msg = []
array.append(i)
Для каждого msg в 'mesTickets' я проверял, равен ли msg.id билету.id, если да, я присваивал msgs в списке 'msg' внутри списка 'array'
{% for i in array %}
<tr>
<td>{{i.id}}</td>
<td>
<ul>
{% for j in i.msg %}
<li>{{j.content}}</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}