Skip to content
Snippets Groups Projects
Commit 04dd46e8 authored by Benjamin Hättasch's avatar Benjamin Hättasch
Browse files

Merge branch 'unique_fix' into 'master'

fix event-dependent unique constraints in AKModel

See merge request kif/akplanning!11
parents 8437ee5a 1fbfaa72
No related branches found
No related tags found
No related merge requests found
# Generated by Django 2.2.6 on 2020-05-10 10:48
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('AKModel', '0027_event_timezone'),
]
operations = [
migrations.AlterField(
model_name='akcategory',
name='name',
field=models.CharField(help_text='Name of the AK Category', max_length=64, verbose_name='Name'),
),
migrations.AlterField(
model_name='akowner',
name='slug',
field=models.SlugField(blank=True, help_text='Slug for URL generation', max_length=64, verbose_name='Slug'),
),
migrations.AlterField(
model_name='akrequirement',
name='name',
field=models.CharField(help_text='Name of the Requirement', max_length=128, verbose_name='Name'),
),
migrations.AlterField(
model_name='aktrack',
name='name',
field=models.CharField(help_text='Name of the AK Track', max_length=64, verbose_name='Name'),
),
migrations.AlterUniqueTogether(
name='ak',
unique_together={('event', 'name'), ('event', 'short_name')},
),
migrations.AlterUniqueTogether(
name='akcategory',
unique_together={('event', 'name')},
),
migrations.AlterUniqueTogether(
name='akowner',
unique_together={('event', 'name', 'institution'), ('event', 'slug')},
),
migrations.AlterUniqueTogether(
name='akrequirement',
unique_together={('event', 'name')},
),
migrations.AlterUniqueTogether(
name='aktrack',
unique_together={('event', 'name')},
),
migrations.AlterUniqueTogether(
name='room',
unique_together={('event', 'name', 'building')},
),
]
......@@ -50,8 +50,7 @@ class AKOwner(models.Model):
""" An AKOwner describes the person organizing/holding an AK.
"""
name = models.CharField(max_length=64, verbose_name=_('Nickname'), help_text=_('Name to identify an AK owner by'))
slug = models.SlugField(max_length=64, blank=True, unique=True, verbose_name=_('Slug'),
help_text=_('Slug for URL generation'))
slug = models.SlugField(max_length=64, blank=True, verbose_name=_('Slug'), help_text=_('Slug for URL generation'))
institution = models.CharField(max_length=128, blank=True, verbose_name=_('Institution'), help_text=_('Uni etc.'))
link = models.URLField(blank=True, verbose_name=_('Web Link'), help_text=_('Link to Homepage'))
......@@ -62,7 +61,7 @@ class AKOwner(models.Model):
verbose_name = _('AK Owner')
verbose_name_plural = _('AK Owners')
ordering = ['name']
unique_together = [['name', 'institution']]
unique_together = [['event', 'name', 'institution'], ['event', 'slug']]
def __str__(self):
if self.institution:
......@@ -73,15 +72,15 @@ class AKOwner(models.Model):
max_length = self._meta.get_field('slug').max_length
slug_candidate = slugify(self.name)[:max_length]
if not AKOwner.objects.filter(slug=slug_candidate).exists():
if not AKOwner.objects.filter(event=self.event, slug=slug_candidate).exists():
self.slug = slug_candidate
return
slug_candidate = slugify(slug_candidate + '_' + self.institution)[:max_length]
if not AKOwner.objects.filter(slug=slug_candidate).exists():
if not AKOwner.objects.filter(event=self.event, slug=slug_candidate).exists():
self.slug = slug_candidate
return
for i in itertools.count(1):
if not AKOwner.objects.filter(slug=slug_candidate).exists():
if not AKOwner.objects.filter(event=self.event, slug=slug_candidate).exists():
break
digits = len(str(i))
slug_candidate = '{}-{}'.format(slug_candidate[:-(digits + 1)], i)
......@@ -95,14 +94,14 @@ class AKOwner(models.Model):
super().save(*args, **kwargs)
@staticmethod
def get_by_slug(slug):
return AKOwner.objects.get(slug=slug)
def get_by_slug(event, slug):
return AKOwner.objects.get(event=event, slug=slug)
class AKCategory(models.Model):
""" An AKCategory describes the characteristics of an AK, e.g. content vs. recreational.
"""
name = models.CharField(max_length=64, unique=True, verbose_name=_('Name'), help_text=_('Name of the AK Category'))
name = models.CharField(max_length=64, verbose_name=_('Name'), help_text=_('Name of the AK Category'))
color = models.CharField(max_length=7, blank=True, verbose_name=_('Color'), help_text=_('Color for displaying'))
description = models.TextField(blank=True, verbose_name=_("Description"),
help_text=_("Short description of this AK Category"))
......@@ -114,6 +113,7 @@ class AKCategory(models.Model):
verbose_name = _('AK Category')
verbose_name_plural = _('AK Categories')
ordering = ['name']
unique_together = ['event', 'name']
def __str__(self):
return self.name
......@@ -122,7 +122,7 @@ class AKCategory(models.Model):
class AKTrack(models.Model):
""" An AKTrack describes a set of semantically related AKs.
"""
name = models.CharField(max_length=64, unique=True, verbose_name=_('Name'), help_text=_('Name of the AK Track'))
name = models.CharField(max_length=64, verbose_name=_('Name'), help_text=_('Name of the AK Track'))
color = models.CharField(max_length=7, blank=True, verbose_name=_('Color'), help_text=_('Color for displaying'))
event = models.ForeignKey(to=Event, on_delete=models.CASCADE, verbose_name=_('Event'),
......@@ -132,6 +132,7 @@ class AKTrack(models.Model):
verbose_name = _('AK Track')
verbose_name_plural = _('AK Tracks')
ordering = ['name']
unique_together = ['event', 'name']
def __str__(self):
return self.name
......@@ -154,7 +155,7 @@ class AKTag(models.Model):
class AKRequirement(models.Model):
""" An AKRequirement describes something needed to hold an AK, e.g. infrastructure.
"""
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'), help_text=_('Name of the Requirement'))
name = models.CharField(max_length=128, verbose_name=_('Name'), help_text=_('Name of the Requirement'))
event = models.ForeignKey(to=Event, on_delete=models.CASCADE, verbose_name=_('Event'),
help_text=_('Associated event'))
......@@ -163,6 +164,7 @@ class AKRequirement(models.Model):
verbose_name = _('AK Requirement')
verbose_name_plural = _('AK Requirements')
ordering = ['name']
unique_together = ['event', 'name']
def __str__(self):
return self.name
......@@ -211,7 +213,7 @@ class AK(models.Model):
class Meta:
verbose_name = _('AK')
verbose_name_plural = _('AKs')
unique_together = [('name', 'event'), ('short_name', 'event')]
unique_together = [['event', 'name'], ['event', 'short_name']]
def __str__(self):
if self.short_name:
......@@ -248,7 +250,7 @@ class Room(models.Model):
verbose_name = _('Room')
verbose_name_plural = _('Rooms')
ordering = ['building', 'name']
unique_together = [['name', 'building']]
unique_together = ['event', 'name', 'building']
@property
def title(self):
......
......@@ -134,7 +134,10 @@ class AKOwnerForm(forms.ModelForm):
class Meta:
model = AKOwner
fields = ['name', 'institution', 'link']
fields = ['name', 'institution', 'link', 'event']
widgets = {
'event': forms.HiddenInput
}
class AKDurationForm(forms.ModelForm):
......
......@@ -8,7 +8,6 @@ from django.views import View
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from AKModel.models import AK, AKCategory, AKTag, AKOwner, AKSlot
from AKModel.models import Event
from AKModel.views import EventSlugMixin
from AKModel.views import FilterByEventSlugMixin
from AKSubmission.forms import AKWishForm, AKOwnerForm, AKEditForm, AKSubmissionForm, AKDurationForm
......@@ -128,13 +127,13 @@ class AKAndAKWishSubmissionView(EventSlugMixin, CreateView):
class AKSubmissionView(AKAndAKWishSubmissionView):
def get_initial(self):
initials = super(AKAndAKWishSubmissionView, self).get_initial()
initials['owners'] = [AKOwner.get_by_slug(self.kwargs['owner_slug'])]
initials['owners'] = [AKOwner.get_by_slug(self.event, self.kwargs['owner_slug'])]
initials['event'] = self.event
return initials
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(object_list=object_list, **kwargs)
context['owner'] = get_object_or_404(AKOwner, slug=self.kwargs['owner_slug'])
context['owner'] = get_object_or_404(AKOwner, event=self.event, slug=self.kwargs['owner_slug'])
return context
......@@ -180,13 +179,10 @@ class AKOwnerCreateView(EventSlugMixin, CreateView):
return reverse_lazy('submit:submit_ak',
kwargs={'event_slug': self.kwargs['event_slug'], 'owner_slug': self.object.slug})
def form_valid(self, form):
instance = form.save(commit=False)
# Set event
instance.event = Event.get_by_slug(self.kwargs["event_slug"])
return super().form_valid(form)
def get_initial(self):
initials = super(AKOwnerCreateView, self).get_initial()
initials['event'] = self.event
return initials
class AKOwnerSelectDispatchView(EventSlugMixin, View):
......@@ -206,7 +202,7 @@ class AKOwnerSelectDispatchView(EventSlugMixin, View):
reverse_lazy('submit:submit_ak', kwargs={'event_slug': kwargs['event_slug'], 'owner_slug': owner.slug}))
class AKOwnerEditView(EventSlugMixin, UpdateView):
class AKOwnerEditView(FilterByEventSlugMixin, UpdateView):
model = AKOwner
template_name = "AKSubmission/akowner_create_update.html"
form_class = AKOwnerForm
......@@ -252,7 +248,8 @@ class AKSlotAddView(EventSlugMixin, CreateView):
def get_success_url(self):
messages.add_message(self.request, messages.SUCCESS, _("AK Slot successfully added"))
return reverse_lazy('submit:ak_detail', kwargs={'event_slug': self.kwargs['event_slug'], 'pk': self.object.ak.pk})
return reverse_lazy('submit:ak_detail',
kwargs={'event_slug': self.kwargs['event_slug'], 'pk': self.object.ak.pk})
class AKSlotEditView(EventSlugMixin, UpdateView):
......@@ -263,7 +260,8 @@ class AKSlotEditView(EventSlugMixin, UpdateView):
def get(self, request, *args, **kwargs):
akslot = get_object_or_404(AKSlot, pk=kwargs["pk"])
if akslot.start is not None:
messages.add_message(self.request, messages.WARNING, _("You cannot edit a slot that has already been scheduled"))
messages.add_message(self.request, messages.WARNING,
_("You cannot edit a slot that has already been scheduled"))
return redirect('submit:ak_detail', event_slug=self.kwargs['event_slug'], pk=akslot.ak.pk)
return super().get(request, *args, **kwargs)
......@@ -274,7 +272,8 @@ class AKSlotEditView(EventSlugMixin, UpdateView):
def get_success_url(self):
messages.add_message(self.request, messages.SUCCESS, _("AK Slot successfully updated"))
return reverse_lazy('submit:ak_detail', kwargs={'event_slug': self.kwargs['event_slug'], 'pk': self.object.ak.pk})
return reverse_lazy('submit:ak_detail',
kwargs={'event_slug': self.kwargs['event_slug'], 'pk': self.object.ak.pk})
class AKSlotDeleteView(EventSlugMixin, DeleteView):
......@@ -284,7 +283,8 @@ class AKSlotDeleteView(EventSlugMixin, DeleteView):
def get(self, request, *args, **kwargs):
akslot = get_object_or_404(AKSlot, pk=kwargs["pk"])
if akslot.start is not None:
messages.add_message(self.request, messages.WARNING, _("You cannot delete a slot that has already been scheduled"))
messages.add_message(self.request, messages.WARNING,
_("You cannot delete a slot that has already been scheduled"))
return redirect('submit:ak_detail', event_slug=self.kwargs['event_slug'], pk=akslot.ak.pk)
return super().get(request, *args, **kwargs)
......@@ -295,4 +295,5 @@ class AKSlotDeleteView(EventSlugMixin, DeleteView):
def get_success_url(self):
messages.add_message(self.request, messages.SUCCESS, _("AK Slot successfully deleted"))
return reverse_lazy('submit:ak_detail', kwargs={'event_slug': self.kwargs['event_slug'], 'pk': self.object.ak.pk})
return reverse_lazy('submit:ak_detail',
kwargs={'event_slug': self.kwargs['event_slug'], 'pk': self.object.ak.pk})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment