From 6ef880339f28360e4a2fef04050f75a8986f2558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 5 Jan 2020 15:30:50 +0100 Subject: [PATCH] Refactor the Reponses model --- .../0003_reponse_renaming_and_cleaning.py | 75 +++++++++++++++++++ propositions/models.py | 27 +++++-- .../templates/propositions/liste.html | 7 +- propositions/templatetags/getresponse.py | 8 +- propositions/urls.py | 7 +- propositions/views.py | 14 ++-- 6 files changed, 114 insertions(+), 24 deletions(-) create mode 100644 propositions/migrations/0003_reponse_renaming_and_cleaning.py diff --git a/propositions/migrations/0003_reponse_renaming_and_cleaning.py b/propositions/migrations/0003_reponse_renaming_and_cleaning.py new file mode 100644 index 0000000..6489374 --- /dev/null +++ b/propositions/migrations/0003_reponse_renaming_and_cleaning.py @@ -0,0 +1,75 @@ +# Generated by Django 2.2.9 on 2020-01-05 13:32 + +from django.conf import settings +from django.db import migrations, models + + +def move_profile_to_user(apps, schema_editor): + Reponses = apps.get_model("propositions", "reponses") + for answer in Reponses.objects.all(): + answer.user = answer.part.user + answer.save() + + +def move_user_to_profile(apps, schema_editor): + # One should do something similar to ``move_profile_to_user`` AND make the + # ``part`` field temporarily nullable in the operations below. + # => Grosse flemme + raise NotImplementedError("Who uses migrations backwards anyway?") + + +class Migration(migrations.Migration): + + dependencies = [ + ("gestion", "0001_initial"), + ("propositions", "0002_nom_verbose_name"), + ] + + operations = [ + migrations.AlterModelOptions( + name="reponses", + options={ + "verbose_name": "Réponse à une proposition", + "verbose_name_plural": "Réponses à une proposition", + }, + ), + migrations.RenameField( + model_name="reponses", old_name="prop", new_name="proposition", + ), + migrations.AddField( + model_name="reponses", + name="user", + field=models.ForeignKey( + on_delete=models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + null=True, + ), + ), + migrations.RunPython(move_profile_to_user, move_user_to_profile), + migrations.AlterField( + model_name="reponses", + name="user", + field=models.ForeignKey( + on_delete=models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + null=False, + ), + ), + migrations.RemoveField(model_name="reponses", name="part"), + migrations.AddField( + model_name="reponses", + name="answer", + field=models.CharField( + choices=[("oui", "Oui"), ("non", "Non")], + default="non", + max_length=3, + verbose_name="Réponse", + ), + preserve_default=False, + ), + migrations.AlterUniqueTogether( + name="reponses", unique_together={("proposition", "user")}, + ), + migrations.RemoveField(model_name="reponses", name="reponse",), + migrations.RenameModel(old_name="reponses", new_name="answer"), + ] diff --git a/propositions/models.py b/propositions/models.py index 8e61373..4453cab 100644 --- a/propositions/models.py +++ b/propositions/models.py @@ -1,10 +1,8 @@ +from django.contrib.auth import get_user_model from django.db import models from gestion.models import ErnestoUser -REP = ( - ('oui', 'Oui'), - ('non', 'Non'), - ) +User = get_user_model() class Prop(models.Model): @@ -22,7 +20,20 @@ class Prop(models.Model): verbose_name = "Proposition" -class Reponses(models.Model): - prop = models.ForeignKey(Prop, on_delete=models.CASCADE) - part = models.ForeignKey(ErnestoUser, on_delete=models.CASCADE) - reponse = models.CharField("Réponse", max_length=20, blank=True, choices=REP) +class Answer(models.Model): + YES = "oui" + NO = "non" + + REP_CHOICES = [ + (YES, "Oui"), + (NO, "Non") + ] + + proposition = models.ForeignKey(Prop, on_delete=models.CASCADE) + user = models.ForeignKey(User, on_delete=models.CASCADE) + answer = models.CharField("Réponse", max_length=3, choices=REP_CHOICES) + + class Meta: + unique_together = ("proposition", "user") + verbose_name = "Réponse à une proposition" + verbose_name_plural = "Réponses à une proposition" diff --git a/propositions/templates/propositions/liste.html b/propositions/templates/propositions/liste.html index 4bf8d8f..4209350 100644 --- a/propositions/templates/propositions/liste.html +++ b/propositions/templates/propositions/liste.html @@ -21,12 +21,15 @@ {% for p in propositions %} - {% if p.lien %}{% endif %}{{ p.nom }}{% if p.artiste %} - {{ p.artiste }}{% endif %}{% if p.lien %}{% endif %} + {% if p.lien %}{% endif %} + {{ p.nom }}{% if p.artiste %} - {{ p.artiste }}{% endif %} + {% if p.lien %}{% endif %} + {{ p.nboui }} {{ p.nbnon }} Oui Non - {% getresponse request.user.profile p %} + {% getresponse request.user p %} {% if p.user == request.user.profile or request.user.profile.is_chef %}Supprimer{% endif %} {% endfor %} diff --git a/propositions/templatetags/getresponse.py b/propositions/templatetags/getresponse.py index 941e016..612e2d4 100644 --- a/propositions/templatetags/getresponse.py +++ b/propositions/templatetags/getresponse.py @@ -1,5 +1,5 @@ from django import template -from propositions.models import Reponses +from propositions.models import Answer register = template.Library() @@ -7,7 +7,7 @@ register = template.Library() @register.inclusion_tag("propositions/reponse.html") def getresponse(user, prop): try: - rep = Reponses.objects.get(prop=prop, part=user) - return {"reponse": rep.reponse} - except Reponses.DoesNotExist: + answer = Answer.objects.values_list("answer").get(proposition=prop, user=user) + return {"reponse": answer[0]} + except Answer.DoesNotExist: return {} diff --git a/propositions/urls.py b/propositions/urls.py index b2191d1..f08c0c3 100644 --- a/propositions/urls.py +++ b/propositions/urls.py @@ -1,13 +1,14 @@ from django.urls import path -from propositions.views import PropDelete from propositions import views +from propositions.models import Answer +from propositions.views import PropDelete app_name = "propositions" urlpatterns = [ path("", views.PropositionList.as_view(), name="list"), path("new", views.PropositionCreate.as_view(), name="create"), - path("/oui", views.reponse, {"rep": "oui"}, name="oui"), - path("/non", views.reponse, {"rep": "non"}, name="non"), + path("/oui", views.answer, {"rep": "oui"}, name=Answer.YES), + path("/non", views.answer, {"rep": "non"}, name=Answer.NO), path("/supprimer", PropDelete.as_view(), name="delete"), ] diff --git a/propositions/views.py b/propositions/views.py index a089951..021903f 100644 --- a/propositions/views.py +++ b/propositions/views.py @@ -7,7 +7,7 @@ from django.utils.decorators import method_decorator from django.http import HttpResponseRedirect from propositions.models import Prop -from propositions.models import Reponses +from propositions.models import Answer class PropositionCreate(LoginRequiredMixin, CreateView): @@ -51,21 +51,21 @@ class PropDelete(DeleteView): @login_required -def reponse(request, id, rep): +def answer(request, id, rep): proposition = get_object_or_404(Prop, id=id) - participant = request.user.profile + user = request.user - old_answer = Reponses.objects.filter(prop=proposition, part=participant) + old_answer = Answer.objects.filter(proposition=proposition, user=user) if old_answer.exists(): old_answer = old_answer.get() - if old_answer.reponse == "oui": + if old_answer.answer == Answer.YES: proposition.nboui -= 1 else: proposition.nbnon -= 1 old_answer.delete() - Reponses.objects.create(prop=proposition, part=participant, reponse=rep) - if rep == "oui": + Answer.objects.create(proposition=proposition, user=user, answer=rep) + if rep == Answer.YES: proposition.nboui += 1 else: proposition.nbnon += 1