Refactor group and music game models to use UniqueConstraint; update form error handling in templates

This commit is contained in:
Edgar P. Burkhart 2025-06-14 10:35:42 +02:00
parent 43ec6aafc4
commit 245a2503e2
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227
5 changed files with 84 additions and 14 deletions

View file

@ -64,3 +64,9 @@ article.message {
color: var(--pico-color-red-500);
}
}
.form-error::before {
margin-right: .5em;
font-family: remixicon;
content: "\eca0";
}

View file

@ -1,8 +1,4 @@
{% if form.non_field_errors %}
<ul class="form-errors">
{% for error in form.non_field_errors %}<li>{{ error }}</li>{% endfor %}
</ul>
{% endif %}
{% for error in form.non_field_errors %}<article class="message error">{{ error }}</article>{% endfor %}
<form method="post" {% if action %}action="{% url action %}"{% endif %}>
{% csrf_token %}
<fieldset>
@ -10,12 +6,10 @@
<label>
{{ field.label }}
{{ field }}
{% if field.errors %}
<small id="{{ field.errors.field_id }}_error" class="form-error">{{ field.errors|join:", " }}</small>
{% endif %}
</label>
{% if field.errors %}
<ul class="form-errors">
{% for error in field.errors %}<li>{{ error }}</li>{% endfor %}
</ul>
{% endif %}
{% endfor %}
</fieldset>
<input type="submit" {% if submit %}value="{{ submit }}"{% endif %}>

View file

@ -0,0 +1,53 @@
# Generated by Django 5.2.3 on 2025-06-14 08:13
import django.db.models.functions.text
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("game", "0012_alter_musikgame_playlist"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterUniqueTogether(
name="group",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="musicgameorder",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="musicvideo",
unique_together=set(),
),
migrations.AddConstraint(
model_name="group",
constraint=models.UniqueConstraint(
django.db.models.functions.text.Lower("name"),
models.F("owner"),
name="unique_group_name",
),
),
migrations.AddConstraint(
model_name="musicgameorder",
constraint=models.UniqueConstraint(
fields=("game", "player", "music_video"), name="unique_music_in_game"
),
),
migrations.AddConstraint(
model_name="musicgameorder",
constraint=models.UniqueConstraint(
fields=("game", "order"), name="unique_order"
),
),
migrations.AddConstraint(
model_name="musicvideo",
constraint=models.UniqueConstraint(
fields=("yt_id", "owner", "group"), name="unique_music_in_group"
),
),
]

View file

@ -1,5 +1,6 @@
from django.contrib.auth.models import User
from django.db import models
from django.db.models.functions import Lower
from django.urls import reverse
@ -19,7 +20,9 @@ class Group(models.Model):
return reverse("group_detail", kwargs={"pk": self.pk})
class Meta:
unique_together = ["name", "owner"]
constraints = [
models.UniqueConstraint(Lower("name"), "owner", name="unique_group_name")
]
class MusicVideo(models.Model):
@ -31,7 +34,11 @@ class MusicVideo(models.Model):
blacklisted = models.BooleanField(default=False)
class Meta:
unique_together = ["yt_id", "owner", "group"]
constraints = [
models.UniqueConstraint(
fields=("yt_id", "owner", "group"), name="unique_music_in_group"
)
]
class MusikGame(models.Model):
@ -52,5 +59,10 @@ class MusicGameOrder(models.Model):
order = models.PositiveIntegerField()
class Meta:
unique_together = [["game", "player", "music_video"], ["game", "order"]]
constraints = [
models.UniqueConstraint(
fields=("game", "player", "music_video"), name="unique_music_in_game"
),
models.UniqueConstraint(fields=("game", "order"), name="unique_order"),
]
ordering = ["order"]

View file

@ -7,6 +7,7 @@ from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin
from django.db import IntegrityError
from django.db.models import Count, Q
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect
@ -40,7 +41,11 @@ class GroupMixin:
class GroupCreateView(LoginRequiredMixin, GroupMixin, CreateView):
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
try:
return super().form_valid(form)
except IntegrityError:
form.add_error("name", "Ce nom de groupe existe déjà.")
return super().form_invalid(form)
class GroupUpdateView(OwnerFilterMixin, GroupMixin, UpdateView):