Projet

Général

Profil

0001-manager-slug-generation-optimization-on-event-import.patch

Lauréline Guérin, 11 septembre 2020 09:40

Télécharger (4,18 ko)

Voir les différences:

Subject: [PATCH 1/2] manager: slug generation optimization on event import
 (#46100)

 chrono/agendas/models.py | 23 +++++++++++++++++++----
 chrono/manager/views.py  |  4 +++-
 tests/test_manager.py    | 14 +++++++++-----
 3 files changed, 31 insertions(+), 10 deletions(-)
chrono/agendas/models.py
68 68
    return dtime.hour == 0 and dtime.minute == 0
69 69

  
70 70

  
71
def generate_slug(instance, **query_filters):
71
def generate_slug(instance, seen_slugs=None, **query_filters):
72 72
    base_slug = instance.base_slug
73 73
    slug = base_slug
74 74
    i = 1
75
    while instance._meta.model.objects.filter(slug=slug, **query_filters).exists():
75

  
76
    if seen_slugs is None:
77
        # no optimization: check slug in DB each time
78
        while instance._meta.model.objects.filter(slug=slug, **query_filters).exists():
79
            slug = '%s-%s' % (base_slug, i)
80
            i += 1
81
        return slug
82

  
83
    # seen_slugs is filled
84
    while True:
85
        if slug not in seen_slugs:
86
            # check in DB to be sure, but only if not seen
87
            queryset = instance._meta.model.objects.filter(slug=slug, **query_filters)
88
            if not queryset.exists():
89
                break
76 90
        slug = '%s-%s' % (base_slug, i)
77 91
        i += 1
92
    seen_slugs.add(slug)
78 93
    return slug
79 94

  
80 95

  
......
810 825
        if self.cancellation_scheduled:
811 826
            return _('Cancellation in progress')
812 827

  
813
    def save(self, *args, **kwargs):
828
    def save(self, seen_slugs=None, *args, **kwargs):
814 829
        assert self.agenda.kind != 'virtual', "an event can't reference a virtual agenda"
815 830
        assert not (self.slug and self.slug.isdigit()), 'slug cannot be a number'
816 831
        self.check_full()
817 832
        if not self.slug:
818
            self.slug = generate_slug(self, agenda=self.agenda)
833
            self.slug = generate_slug(self, seen_slugs=seen_slugs, agenda=self.agenda)
819 834
        return super(Event, self).save(*args, **kwargs)
820 835

  
821 836
    @property
chrono/manager/views.py
1337 1337

  
1338 1338
    def form_valid(self, form):
1339 1339
        if form.events:
1340
            # existing event slugs for this agenda
1341
            seen_slugs = set(self.agenda.event_set.values_list('slug', flat=True))
1340 1342
            for event in form.events:
1341 1343
                event.agenda_id = self.kwargs['pk']
1342
                event.save()
1344
                event.save(seen_slugs=seen_slugs)  # optimization: seen_slugs
1343 1345
            messages.info(self.request, _('%d events have been imported.') % len(form.events))
1344 1346
        return super(AgendaImportEventsView, self).form_valid(form)
1345 1347

  
tests/test_manager.py
1581 1581
    resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
1582 1582
    resp.form['events_csv_file'] = Upload(
1583 1583
        't.csv',
1584
        b'2016-09-16,18:00,10,5,label,,,pricing,\n'
1585
        b'2016-09-17,18:00,10,5,label,,,pricing,\n'
1586
        b'2016-09-18,18:00,10,5,label,,,pricing,\n',
1584
        b'2016-09-16,18:00,10,5,labela,,,pricing,\n'
1585
        b'2016-09-17,18:00,10,5,labela,,,pricing,\n'
1586
        b'2016-09-18,18:00,10,5,labela,,,pricing,\n'
1587
        b'2016-09-18,18:00,10,5,labelb,,,pricing,\n'
1588
        b'2016-09-18,18:00,10,5,labelb,,,pricing,\n',
1587 1589
        'text/csv',
1588 1590
    )
1589
    resp = resp.form.submit(status=302)
1590
    assert Event.objects.count() == 3
1591
    with CaptureQueriesContext(connection) as ctx:
1592
        resp = resp.form.submit(status=302)
1593
        assert len(ctx.captured_queries) == 24
1594
    assert Event.objects.count() == 5
1591 1595

  
1592 1596
    # forbidden numerical slug
1593 1597
    Event.objects.all().delete()
1594
-