Commit f838738c authored by VAN ZUIJLEN Nils's avatar VAN ZUIJLEN Nils
Browse files

Refactor Event.to_come to speed it up

Use 4 simple SQL requests instead of a big one

Decreases complexity on SQL side by not JOINing the three inscription
sources in one request.

Previous function ran in 40 to 50 seconds
The new one runs in ~70 milliseconds
parent 765baa25
......@@ -90,14 +90,35 @@ class Event(models.Model):
@staticmethod
def to_come(user):
events = [event for event in Event.objects.filter(
Q(model=False),
Q(end_inscriptions__gt=timezone.now()),
Q(inscriptions__user=user) | Q(private=False)
).distinct().prefetch_related('formulas').order_by('start_time')
.annotate(reg_nb=(Count('inscriptions', distinct=True) + Count('extern_inscriptions', distinct=True) + Count('invitations', distinct=True)))
.extra(select={'ins': "(SELECT COUNT(*) FROM events_inscription WHERE events_inscription.event_id=events_event.id AND events_inscription.user_id=%d)" % user.id})]
return [(event.ins, event) for event in events]
events = list(
Event.objects.filter(
Q(model=False),
Q(end_inscriptions__gt=timezone.now()),
Q(inscriptions__user=user) | Q(private=False)
).distinct().prefetch_related('formulas').order_by('start_time')
.extra(select={
# Pour savoir si l'utilisateur actuel est inscrit
'ins': "(SELECT COUNT(*) FROM events_inscription "
"WHERE events_inscription.event_id=events_event.id "
"AND events_inscription.user_id=%d)" % user.id
})
)
events_by_id = {e.pk: [e, 0] for e in events}
counts_ins = Event.objects.filter(pk__in=events_by_id.keys()).annotate(ins_cnt=Count('inscriptions'))
counts_ext = Event.objects.filter(pk__in=events_by_id.keys()).annotate(ext_cnt=Count('extern_inscriptions'))
counts_inv = Event.objects.filter(pk__in=events_by_id.keys()).annotate(inv_cnt=Count('invitations'))
for e in counts_ins:
events_by_id[e.pk][1] += e.ins_cnt
for e in counts_ext:
events_by_id[e.pk][1] += e.ext_cnt
for e in counts_inv:
events_by_id[e.pk][1] += e.inv_cnt
for e, cnt in events_by_id.values():
e.reg_nb = cnt
return [(e.ins, e) for e in events]
def formulas_json(self):
res = {f.name: "{} <br>(Cotisant: {}€ / Non cotisant: {}€)".format(f.name, f.price_contributor, f.price_non_contributor) for f in self.formulas.all()}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment