api: add a field 'slug' to Event (#15726)
This commit is contained in:
parent
befaa3b365
commit
0f4040f9a5
|
@ -0,0 +1,37 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.utils.text import slugify
|
||||
|
||||
|
||||
def set_slug_on_events(apps, schema_editor):
|
||||
Event = apps.get_model('agendas', 'Event')
|
||||
for event in Event.objects.filter(slug=''):
|
||||
base_slug = slugify(event.label)
|
||||
slug = base_slug
|
||||
i = 1
|
||||
while True:
|
||||
if not Event.objects.filter(slug=slug).exists():
|
||||
break
|
||||
slug = '%s-%s' % (base_slug, i)
|
||||
i += 1
|
||||
event.slug = slug
|
||||
event.save(update_fields=['slug'])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('agendas', '0027_event_description'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='slug',
|
||||
field=models.SlugField(default='', max_length=160, verbose_name='Identifier'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.RunPython(set_slug_on_events, lambda x, y: None),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.18 on 2019-11-06 12:20
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('agendas', '0028_event_slug'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=160, unique=True, verbose_name='Identifier'),
|
||||
),
|
||||
]
|
|
@ -289,6 +289,7 @@ class Event(models.Model):
|
|||
_('Places in waiting list'), default=0)
|
||||
label = models.CharField(_('Label'), max_length=150, null=True, blank=True,
|
||||
help_text=_('Optional label to identify this date.'))
|
||||
slug = models.SlugField(_('Identifier'), max_length=160, unique=True)
|
||||
description = models.TextField(_('Description'), null=True, blank=True,
|
||||
help_text=_('Optional event description.'))
|
||||
full = models.BooleanField(default=False)
|
||||
|
@ -305,6 +306,16 @@ class Event(models.Model):
|
|||
|
||||
def save(self, *args, **kwargs):
|
||||
self.check_full()
|
||||
if not self.slug:
|
||||
base_slug = slugify(self.label)
|
||||
slug = base_slug
|
||||
i = 1
|
||||
while True:
|
||||
if not Event.objects.filter(slug=slug).exists():
|
||||
break
|
||||
slug = '%s-%s' % (base_slug, i)
|
||||
i += 1
|
||||
self.slug = slug
|
||||
return super(Event, self).save(*args, **kwargs)
|
||||
|
||||
def check_full(self):
|
||||
|
@ -345,6 +356,12 @@ class Event(models.Model):
|
|||
def import_json(cls, data):
|
||||
data['start_datetime'] = make_aware(datetime.datetime.strptime(
|
||||
data['start_datetime'], '%Y-%m-%d %H:%M:%S'))
|
||||
if 'slug' in data:
|
||||
event, created = cls.objects.get_or_create(slug=data['slug'], defaults=data)
|
||||
if not created:
|
||||
for k, v in data.items():
|
||||
setattr(event, k, v)
|
||||
return event
|
||||
return cls(**data)
|
||||
|
||||
def export_json(self):
|
||||
|
@ -353,6 +370,7 @@ class Event(models.Model):
|
|||
'places': self.places,
|
||||
'waiting_list_places': self.waiting_list_places,
|
||||
'label': self.label,
|
||||
'slug': self.slug,
|
||||
'description': self.description,
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,16 @@ class AgendaEditForm(AgendaAddForm):
|
|||
fields = ['label', 'slug', 'edit_role', 'view_role', 'minimal_booking_delay', 'maximal_booking_delay']
|
||||
|
||||
|
||||
class NewEventForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Event
|
||||
widgets = {
|
||||
'agenda': forms.HiddenInput(),
|
||||
'start_datetime': DateTimeWidget(),
|
||||
}
|
||||
exclude = ['full', 'meeting_type', 'desk', 'slug']
|
||||
|
||||
|
||||
class EventForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Event
|
||||
|
@ -220,9 +230,14 @@ class ImportEventsForm(forms.Form):
|
|||
except ValueError:
|
||||
raise ValidationError(_('Invalid file format. (number of places in waiting list, line %d)') % (i+1))
|
||||
if len(csvline) >= 5:
|
||||
event.label = ' '.join([force_text(x) for x in csvline[4:]])
|
||||
event.label = force_text(csvline[4])
|
||||
exclude = ['agenda', 'desk', 'meeting_type']
|
||||
if len(csvline) >= 6:
|
||||
event.slug = ' '.join([force_text(x) for x in csvline[5:]])
|
||||
else:
|
||||
exclude += ['slug']
|
||||
try:
|
||||
event.full_clean(exclude=['agenda', 'desk', 'meeting_type'])
|
||||
event.full_clean(exclude=exclude)
|
||||
except ValidationError as e:
|
||||
errors = [
|
||||
_('Invalid file format. (%(label)s: %(errors)s, line %(line)d)') % {
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
data-total="{{event.waiting_list_places}}" data-booked="{{event.waiting_list}}"
|
||||
{% endif %}
|
||||
><a rel="popup" href="{% if user_can_manage %}{% url 'chrono-manager-event-edit' pk=event.id %}{% else %}#{% endif %}">
|
||||
{% if event.label %}{{event.label}} / {% endif %}
|
||||
{% if event.label %}{{event.label}} {% endif %}[{% trans "identifier:" %} {{ event.slug }}] /
|
||||
{{ event.start_datetime }}
|
||||
{% if event.full %}/ <span class="full">{% trans "full" %}</span>{% endif %}
|
||||
(
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{% load i18n %}{% trans 'date' %},{% trans 'time' %},{% trans 'number of places' %},{% trans 'number of places in waiting list' %},{% trans 'label' %}
|
||||
{{ some_future_date|date:"Y-m-d" }},{{ some_future_date|date:"H:i" }},15,0,{% trans "example event" %}
|
||||
{% load i18n %}{% trans 'date' %},{% trans 'time' %},{% trans 'number of places' %},{% trans 'number of places in waiting list' %},{% trans 'label' %},{% trans 'identifier' %}
|
||||
{{ some_future_date|date:"Y-m-d" }},{{ some_future_date|date:"H:i" }},15,0,{% trans "example event" as label %}{{ label }},{{ label|slugify }}
|
||||
|
|
|
@ -36,7 +36,7 @@ from chrono.agendas.models import (Agenda, Event, MeetingType, TimePeriod,
|
|||
Booking, Desk, TimePeriodException,
|
||||
ICSError, AgendaImportError)
|
||||
|
||||
from .forms import (AgendaAddForm, AgendaEditForm, EventForm, NewMeetingTypeForm, MeetingTypeForm,
|
||||
from .forms import (AgendaAddForm, AgendaEditForm, NewEventForm, EventForm, NewMeetingTypeForm, MeetingTypeForm,
|
||||
TimePeriodForm, ImportEventsForm, NewDeskForm, DeskForm, TimePeriodExceptionForm,
|
||||
ExceptionsImportForm, AgendasImportForm, TimePeriodAddForm)
|
||||
from .utils import import_site
|
||||
|
@ -567,7 +567,7 @@ agenda_export = AgendaExport.as_view()
|
|||
class AgendaAddEventView(ManagedAgendaMixin, CreateView):
|
||||
template_name = 'chrono/manager_event_form.html'
|
||||
model = Event
|
||||
form_class = EventForm
|
||||
form_class = NewEventForm
|
||||
|
||||
agenda_add_event = AgendaAddEventView.as_view()
|
||||
|
||||
|
|
|
@ -123,11 +123,19 @@ def test_slug():
|
|||
agenda.save()
|
||||
assert agenda.slug == 'foo-bar'
|
||||
|
||||
event = Event.objects.create(start_datetime=now(), places=42, agenda=agenda, label='Foo bar')
|
||||
assert event.slug == 'foo-bar'
|
||||
|
||||
|
||||
def test_existing_slug():
|
||||
agenda = Agenda(label=u'Foo bar', slug='bar')
|
||||
agenda.save()
|
||||
assert agenda.slug == 'bar'
|
||||
|
||||
event = Event.objects.create(start_datetime=now(), places=42, agenda=agenda, label='Foo bar', slug='bar')
|
||||
assert event.slug == 'bar'
|
||||
|
||||
|
||||
def test_duplicate_slugs():
|
||||
agenda = Agenda(label=u'Foo baz')
|
||||
agenda.save()
|
||||
|
@ -139,6 +147,14 @@ def test_duplicate_slugs():
|
|||
agenda.save()
|
||||
assert agenda.slug == 'foo-baz-2'
|
||||
|
||||
event = Event.objects.create(start_datetime=now(), places=42, agenda=agenda, label='Foo bar')
|
||||
assert event.slug == 'foo-bar'
|
||||
event = Event.objects.create(start_datetime=now(), places=42, agenda=agenda, label='Foo bar')
|
||||
assert event.slug == 'foo-bar-1'
|
||||
event = Event.objects.create(start_datetime=now(), places=42, agenda=agenda, label='Foo bar')
|
||||
assert event.slug == 'foo-bar-2'
|
||||
|
||||
|
||||
def test_event_manager():
|
||||
agenda = Agenda(label=u'Foo baz')
|
||||
agenda.save()
|
||||
|
|
|
@ -636,6 +636,22 @@ def test_import_events(app, admin_user):
|
|||
'"2016-09-19"\t"18:00"\t"10"'.encode('iso-8859-15'), 'text/csv')
|
||||
resp = resp.form.submit(status=302)
|
||||
assert Event.objects.count() == 2
|
||||
Event.objects.all().delete()
|
||||
|
||||
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
||||
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5,label,slug', 'text/csv')
|
||||
resp = resp.form.submit(status=302)
|
||||
assert Event.objects.count() == 1
|
||||
event = Event.objects.latest('pk')
|
||||
assert event.start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
||||
assert event.places == 10
|
||||
assert event.waiting_list_places == 5
|
||||
assert event.label == 'label'
|
||||
assert event.slug == 'slug'
|
||||
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
||||
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5,label,slug', 'text/csv')
|
||||
resp = resp.form.submit(status=200)
|
||||
assert 'Invalid file format. (slug: Event with this Identifier already exists.' in resp.text
|
||||
|
||||
|
||||
def test_add_meetings_agenda(app, admin_user):
|
||||
|
|
Loading…
Reference in New Issue