Joey Coder
Joey Coder

Reputation: 3529

Django: Transform dict of queryset

I use the following code to get my data out of the dict.

test = self.events_max_total_gross()
events = organizer.events.all()
    for event in events:
        test.get(event.pk, {}).values()
        [...]

I use this query set to get the data. My question is: Does the transformation at the end makes sense or is there a better way to access the dict (without transforming it first). As I have several of these my approach doesn't seem to follow the DRY principle.

def events_max_total_gross(self):

    events_max_total_gross = (
        Event.objects.filter(
            organizer__in=self.organizers,
            status=EventStatus.LIVE
        )
        .annotate(total_gross=Sum(F('tickets__quantity') * F('tickets__price_gross')))
        .values('pk', 'total_gross')
    )

    """
    Convert this
    [
        {
            'pk': 2,
            'total_gross': 12345
        },
        {
            'pk': 3,
            'total_gross': 54321
        },
        ...
    ]

    to this:
    {
        2: {
            'total_gross': 12345,
        },
        3: {
            'total_gross': 12345,
        }
        ...
    }
    """

    events_max_total_gross_transformed = {}

    for item in events_max_total_gross:
        events_max_total_gross_transformed.setdefault(
            item['pk'], {}
        ).update({'total_gross': item['total_gross']})

    return events_max_total_gross_transformed

Upvotes: 0

Views: 175

Answers (2)

bak2trak
bak2trak

Reputation: 1120

If I understood it correctly, then for every organiser's event you need total_gross, you can query like this instead of going over events and events_max_total_gross in loop.

  1. First get all the events of that particular organizer.

    event_ids = Event.objects.filter(organizer=organizer).values_list('id',flat=True)

  2. Run this then:

    Event.objects.filter( id__in=event_ids, organizer__in=self.organizers, status=EventStatus.LIVE ) .annotate(total_gross=Sum(F('tickets__quantity') * F('tickets__price_gross'))) .values('pk', 'total_gross') )

This way you will save your transformation of dict and looping it over again.

In case you need to do like this because of some other requirement then you can use python dict comprehension:

events_max_total_gross_transformed = { event['pk']: { 'total_gross': event['total_gross'] } for event in events_max_total_gross }

But as you have several of these, you might wanna have a look at proxy-models also which might help. Here you can write manager functions to help you with your queries.

Upvotes: 0

nigel222
nigel222

Reputation: 8222

Use:

transformed = { 
    v['pk']: { 'total_gross': v['total_gross'] } for v in events_max_total_gross 
}

This is called a python dict comprehension. Google that term if you want tutorials or examples.

Upvotes: 1

Related Questions