I need to make up an advanced query that allows me get a queryset containing dictionaries with strings for keys and lists with all possible values for values. Here is what I got:
In [26]: Offer.objects.values('partner', 'partner_id')
Out[26]: <QuerySet [{'partner': 'xex', 'partner_id': 'x_999'}, {'partner': 'xex', 'partner_id': 'x_888'}, {'partner': 'quiup', 'partner_id': 'q_888'}, {'partner': 'quiup', 'partner_id': 'q_777'}]>
Here is what I need to get:
<QuerySet [{'partner': 'xex', 'partner_ids': ['x_999', 'x_888']}, {'partner': 'quiup', 'partner_ids': ['q_888', 'q_777']}
I've tried annotations, F-expressions, `Value`, `.dictinct('partner')` but nothing brings me any closer. Any suggestions will be much appreciated and thank you very much for your attention.
UPD. Related model provided:
class Offer(models.Model):
partner = models.CharField(
verbose_name='Partner',
max_length=50
)
partner_id = models.CharField(
verbose_name='Partner ID',
max_length=100,
unique=True,
null=False,
blank=False,
default=''
)
def __str__(self):
return f'{self.partner} - {self.partner_id}'
It is possible, but likely not a good idea. We can generate this with an ArrayAgg
expression [Django-doc]:
from django.contrib.postgres.aggregates import ArrayAgg
Offer.objects.values('partner').annotate(
partners_ids=ArrayAgg('partner_id')
).order_by('partner')
Since the partner
seems a categorical, it is better to work with a ForeignKey
to something, like:
class PartnerType(models.Model):
id = models.CharField(primary_key=True)
class Partner(models.Model):
pass
class Offer(models.Model):
partner_type = models.ForeignKey(PartnerType, on_delete=models.PROTECT)
parter = models.ForeignKey(Partner, on_delete=models.PROTECT)
in that case, we can use:
PartnerType.objects.prefech_related('offer_set')
This will also prevent us from primitive obsession [refactoring.guru].