0001-agendas-slug-unicity-for-Agenda-Desk-and-MeetingType.patch
chrono/agendas/migrations/0030_auto_20191107_1200.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
from __future__ import unicode_literals |
|
3 | ||
4 |
from django.db import migrations |
|
5 |
from django.utils.text import slugify |
|
6 | ||
7 | ||
8 |
def generate_slug(instance, **query_filters): |
|
9 |
base_slug = slugify(instance.label) |
|
10 |
slug = base_slug |
|
11 |
i = 1 |
|
12 |
while True: |
|
13 |
queryset = instance._meta.model.objects.filter(slug=slug, **query_filters).exclude(pk=instance.pk) |
|
14 |
if not queryset.exists(): |
|
15 |
break |
|
16 |
slug = '%s-%s' % (base_slug, i) |
|
17 |
i += 1 |
|
18 |
return slug |
|
19 | ||
20 | ||
21 |
def set_slug_on_agendas(apps, schema_editor): |
|
22 |
Agenda = apps.get_model('agendas', 'Agenda') |
|
23 |
for agenda in Agenda.objects.all().order_by('-pk'): |
|
24 |
if not Agenda.objects.filter(slug=agenda.slug).exclude(pk=agenda.pk).exists(): |
|
25 |
continue |
|
26 |
agenda.slug = generate_slug(agenda) |
|
27 |
agenda.save(update_fields=['slug']) |
|
28 | ||
29 | ||
30 |
def set_slug_on_desks(apps, schema_editor): |
|
31 |
Desk = apps.get_model('agendas', 'Desk') |
|
32 |
for desk in Desk.objects.all().order_by('-pk'): |
|
33 |
if not Desk.objects.filter(slug=desk.slug, agenda=desk.agenda).exclude(pk=desk.pk).exists(): |
|
34 |
continue |
|
35 |
desk.slug = generate_slug(desk, agenda=desk.agenda) |
|
36 |
desk.save(update_fields=['slug']) |
|
37 | ||
38 | ||
39 |
def set_slug_on_meetingtypes(apps, schema_editor): |
|
40 |
MeetingType = apps.get_model('agendas', 'MeetingType') |
|
41 |
for meetingtype in MeetingType.objects.all().order_by('-pk'): |
|
42 |
if not MeetingType.objects.filter(slug=meetingtype.slug, agenda=meetingtype.agenda).exclude(pk=meetingtype.pk).exists(): |
|
43 |
continue |
|
44 |
meetingtype.slug = generate_slug(meetingtype, agenda=meetingtype.agenda) |
|
45 |
meetingtype.save(update_fields=['slug']) |
|
46 | ||
47 | ||
48 |
class Migration(migrations.Migration): |
|
49 | ||
50 |
dependencies = [ |
|
51 |
('agendas', '0029_auto_20191106_1320'), |
|
52 |
] |
|
53 | ||
54 |
operations = [ |
|
55 |
migrations.RunPython(set_slug_on_agendas, lambda x, y: None), |
|
56 |
migrations.RunPython(set_slug_on_desks, lambda x, y: None), |
|
57 |
migrations.RunPython(set_slug_on_meetingtypes, lambda x, y: None), |
|
58 |
] |
chrono/agendas/migrations/0031_auto_20191107_1225.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
# Generated by Django 1.11.18 on 2019-11-07 11:25 |
|
3 |
from __future__ import unicode_literals |
|
4 | ||
5 |
from django.db import migrations, models |
|
6 | ||
7 | ||
8 |
class Migration(migrations.Migration): |
|
9 | ||
10 |
dependencies = [ |
|
11 |
('agendas', '0030_auto_20191107_1200'), |
|
12 |
] |
|
13 | ||
14 |
operations = [ |
|
15 |
migrations.AlterField( |
|
16 |
model_name='agenda', |
|
17 |
name='slug', |
|
18 |
field=models.SlugField(max_length=160, unique=True, verbose_name='Identifier'), |
|
19 |
), |
|
20 |
migrations.AlterUniqueTogether( |
|
21 |
name='desk', |
|
22 |
unique_together=set([('agenda', 'slug')]), |
|
23 |
), |
|
24 |
migrations.AlterUniqueTogether( |
|
25 |
name='meetingtype', |
|
26 |
unique_together=set([('agenda', 'slug')]), |
|
27 |
), |
|
28 |
] |
chrono/agendas/models.py | ||
---|---|---|
49 | 49 |
return dtime.hour == 0 and dtime.minute == 0 |
50 | 50 | |
51 | 51 | |
52 |
def generate_slug(instance, **query_filters): |
|
53 |
base_slug = slugify(instance.label) |
|
54 |
slug = base_slug |
|
55 |
i = 1 |
|
56 |
while True: |
|
57 |
if not instance._meta.model.objects.filter(slug=slug, **query_filters).exists(): |
|
58 |
break |
|
59 |
slug = '%s-%s' % (base_slug, i) |
|
60 |
i += 1 |
|
61 |
return slug |
|
62 | ||
63 | ||
52 | 64 |
class ICSError(Exception): |
53 | 65 |
pass |
54 | 66 | |
... | ... | |
59 | 71 | |
60 | 72 |
class Agenda(models.Model): |
61 | 73 |
label = models.CharField(_('Label'), max_length=150) |
62 |
slug = models.SlugField(_('Identifier'), max_length=160) |
|
74 |
slug = models.SlugField(_('Identifier'), max_length=160, unique=True)
|
|
63 | 75 |
kind = models.CharField(_('Kind'), max_length=20, choices=AGENDA_KINDS, default='events') |
64 | 76 |
minimal_booking_delay = models.PositiveIntegerField( |
65 | 77 |
_('Minimal booking delay (in days)'), default=1) |
... | ... | |
77 | 89 | |
78 | 90 |
def save(self, *args, **kwargs): |
79 | 91 |
if not self.slug: |
80 |
base_slug = slugify(self.label) |
|
81 |
slug = base_slug |
|
82 |
i = 1 |
|
83 |
while True: |
|
84 |
try: |
|
85 |
Agenda.objects.get(slug=slug) |
|
86 |
except self.DoesNotExist: |
|
87 |
break |
|
88 |
slug = '%s-%s' % (base_slug, i) |
|
89 |
i += 1 |
|
90 |
self.slug = slug |
|
92 |
self.slug = generate_slug(self) |
|
91 | 93 |
super(Agenda, self).save(*args, **kwargs) |
92 | 94 | |
93 | 95 |
def get_absolute_url(self): |
... | ... | |
149 | 151 |
except Group.DoesNotExist: |
150 | 152 |
raise AgendaImportError(_('Missing "%s" role') % permissions[permission]) |
151 | 153 |
agenda, created = cls.objects.get_or_create(slug=data['slug'], defaults=data) |
154 |
if not created: |
|
155 |
for k, v in data.items(): |
|
156 |
setattr(agenda, k, v) |
|
152 | 157 |
if data['kind'] == 'events': |
153 | 158 |
if overwrite: |
154 | 159 |
Event.objects.filter(agenda=agenda).delete() |
... | ... | |
252 | 257 | |
253 | 258 |
class Meta: |
254 | 259 |
ordering = ['duration', 'label'] |
260 |
unique_together = ['agenda', 'slug'] |
|
255 | 261 | |
256 | 262 |
def save(self, *args, **kwargs): |
257 | 263 |
if not self.slug: |
258 |
base_slug = slugify(self.label) |
|
259 |
slug = base_slug |
|
260 |
i = 1 |
|
261 |
while True: |
|
262 |
try: |
|
263 |
MeetingType.objects.get(slug=slug, agenda=self.agenda) |
|
264 |
except self.DoesNotExist: |
|
265 |
break |
|
266 |
slug = '%s-%s' % (base_slug, i) |
|
267 |
i += 1 |
|
268 |
self.slug = slug |
|
264 |
self.slug = generate_slug(self, agenda=self.agenda) |
|
269 | 265 |
super(MeetingType, self).save(*args, **kwargs) |
270 | 266 | |
271 | 267 |
@classmethod |
272 | 268 |
def import_json(cls, data): |
273 |
return cls(**data) |
|
269 |
meeting_type, created = cls.objects.get_or_create( |
|
270 |
slug=data['slug'], agenda=data['agenda'], defaults=data) |
|
271 |
if not created: |
|
272 |
for k, v in data.items(): |
|
273 |
setattr(meeting_type, k, v) |
|
274 |
return meeting_type |
|
274 | 275 | |
275 | 276 |
def export_json(self): |
276 | 277 |
return { |
... | ... | |
307 | 308 |
def save(self, *args, **kwargs): |
308 | 309 |
self.check_full() |
309 | 310 |
if not self.slug: |
310 |
base_slug = slugify(self.label) |
|
311 |
slug = base_slug |
|
312 |
i = 1 |
|
313 |
while True: |
|
314 |
if not Event.objects.filter(slug=slug).exists(): |
|
315 |
break |
|
316 |
slug = '%s-%s' % (base_slug, i) |
|
317 |
i += 1 |
|
318 |
self.slug = slug |
|
311 |
self.slug = generate_slug(self) |
|
319 | 312 |
return super(Event, self).save(*args, **kwargs) |
320 | 313 | |
321 | 314 |
def check_full(self): |
... | ... | |
447 | 440 | |
448 | 441 |
class Meta: |
449 | 442 |
ordering = ['label'] |
443 |
unique_together = ['agenda', 'slug'] |
|
450 | 444 | |
451 | 445 |
def save(self, *args, **kwargs): |
452 | 446 |
if not self.slug: |
453 |
base_slug = slugify(self.label) |
|
454 |
slug = base_slug |
|
455 |
i = 1 |
|
456 |
while True: |
|
457 |
try: |
|
458 |
Desk.objects.get(slug=slug, agenda=self.agenda) |
|
459 |
except self.DoesNotExist: |
|
460 |
break |
|
461 |
slug = '%s-%s' % (base_slug, i) |
|
462 |
i += 1 |
|
463 |
self.slug = slug |
|
447 |
self.slug = generate_slug(self, agenda=self.agenda) |
|
464 | 448 |
super(Desk, self).save(*args, **kwargs) |
465 | 449 | |
466 | 450 |
@classmethod |
467 | 451 |
def import_json(cls, data): |
468 | 452 |
timeperiods = data.pop('timeperiods') |
469 | 453 |
exceptions = data.pop('exceptions') |
470 |
instance, created = cls.objects.get_or_create(**data) |
|
454 |
instance, created = cls.objects.get_or_create( |
|
455 |
slug=data['slug'], agenda=data['agenda'], defaults=data) |
|
456 |
if not created: |
|
457 |
for k, v in data.items(): |
|
458 |
setattr(instance, k, v) |
|
471 | 459 |
for timeperiod in timeperiods: |
472 | 460 |
timeperiod['desk'] = instance |
473 | 461 |
TimePeriod.import_json(timeperiod).save() |
474 |
- |