简体   繁体   中英

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM