From 86134eecb448447f298f3a877e56a2fbb77bbd42 Mon Sep 17 00:00:00 2001 From: Tobias Lindenberg Date: Sat, 9 Jan 2021 22:17:56 +0100 Subject: [PATCH] added unique constraint on RecipeBookEntry table Signed-off-by: Tobias Lindenberg --- .../migrations/0096_auto_20210109_2044.py | 31 +++++++++++++++++++ cookbook/models.py | 3 ++ cookbook/views/views.py | 11 +++++-- 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 cookbook/migrations/0096_auto_20210109_2044.py diff --git a/cookbook/migrations/0096_auto_20210109_2044.py b/cookbook/migrations/0096_auto_20210109_2044.py new file mode 100644 index 000000000..4206def66 --- /dev/null +++ b/cookbook/migrations/0096_auto_20210109_2044.py @@ -0,0 +1,31 @@ +# Generated by Django 3.1.5 on 2021-01-09 19:44 + +from django.db import migrations + + +def delete_duplicate_bookmarks(apps, schema_editor): + """ + In this migration, a unique constraint is set on the fields `recipe` and `book`. + If there are already duplicate entries, the migration will fail. + Therefore all duplicate entries are deleted beforehand. + """ + RecipeBookEntry = apps.get_model('cookbook', 'RecipeBookEntry') + + for row in RecipeBookEntry.objects.all(): + if RecipeBookEntry.objects.filter(recipe=row.recipe, book=row.book).count() > 1: + row.delete() + + +class Migration(migrations.Migration): + dependencies = [ + ('cookbook', '0095_auto_20210107_1804'), + ] + + operations = [ + # run function to delete duplicated bookmarks + migrations.RunPython(delete_duplicate_bookmarks), + migrations.AlterUniqueTogether( + name='recipebookentry', + unique_together={('recipe', 'book')}, + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index 64c4e3d37..6f88069c0 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -265,6 +265,9 @@ class RecipeBookEntry(models.Model): def __str__(self): return self.recipe.name + class Meta: + unique_together = (('recipe', 'book'),) + class MealType(models.Model): name = models.CharField(max_length=128) diff --git a/cookbook/views/views.py b/cookbook/views/views.py index e42486899..7b2ae0828 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -7,6 +7,7 @@ from django.contrib.auth import update_session_auth_hash, authenticate from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.password_validation import validate_password from django.core.exceptions import ValidationError +from django.db import IntegrityError from django.db.models import Q, Avg from django.http import HttpResponseRedirect from django.shortcuts import render, get_object_or_404 @@ -105,9 +106,13 @@ def recipe_view(request, pk, share=None): bookmark.recipe = recipe bookmark.book = bookmark_form.cleaned_data['book'] - bookmark.save() - - messages.add_message(request, messages.SUCCESS, _('Bookmark saved!')) + try: + bookmark.save() + except IntegrityError as e: + if 'UNIQUE constraint' in str(e.args): + messages.add_message(request, messages.ERROR, _('This recipe is already linked to the book!')) + else: + messages.add_message(request, messages.SUCCESS, _('Bookmark saved!')) comment_form = CommentForm() bookmark_form = RecipeBookEntryForm()