diff --git a/bootstrap_modal_forms/mixins.py b/bootstrap_modal_forms/mixins.py
index 9874264..8f8be3f 100644
--- a/bootstrap_modal_forms/mixins.py
+++ b/bootstrap_modal_forms/mixins.py
@@ -1,7 +1,7 @@
from django.contrib import messages
from django.contrib.auth import login as auth_login
from django.http import HttpResponseRedirect
-
+from django.db.models import ProtectedError
class PassRequestMixin(object):
"""
@@ -48,11 +48,18 @@ def save(self, commit=True):
class DeleteMessageMixin(object):
"""
Mixin which adds message to BSModalDeleteView.
+ Catch exceptions fired up by "on_delete=models.PROTECT" in the model fields.
"""
def post(self, request, *args, **kwargs):
- messages.success(request, self.success_message)
- return super(DeleteMessageMixin, self).delete(request, *args, **kwargs)
+ try:
+ httpResponse = super(DeleteMessageMixin, self).delete(request, *args, **kwargs)
+ messages.success(request, self.success_message)
+ return httpResponse
+ except ProtectedError:
+ messages.error(request, "Can not remove this item, has a relation in the database.")
+ return HttpResponseRedirect(self.success_url)
+
class LoginAjaxMixin(object):
diff --git a/examples/migrations/0001_initial.py b/examples/migrations/0001_initial.py
index eed1f88..da8d8fa 100644
--- a/examples/migrations/0001_initial.py
+++ b/examples/migrations/0001_initial.py
@@ -1,6 +1,7 @@
-# Generated by Django 2.1 on 2019-03-30 16:15
+# Generated by Django 2.1 on 2020-04-10 21:15
from django.db import migrations, models
+import django.db.models.deletion
class Migration(migrations.Migration):
@@ -11,6 +12,13 @@ class Migration(migrations.Migration):
]
operations = [
+ migrations.CreateModel(
+ name='Vat',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('vat_percentage', models.IntegerField()),
+ ],
+ ),
migrations.CreateModel(
name='Book',
fields=[
@@ -22,6 +30,7 @@ class Migration(migrations.Migration):
('pages', models.IntegerField(blank=True, null=True)),
('book_type', models.PositiveSmallIntegerField(choices=[(1, 'Hardcover'), (2, 'Paperback'), (3, 'E-book')])),
('timestamp', models.DateField(auto_now_add=True)),
+ ('vat', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='examples.Vat')),
],
),
]
diff --git a/examples/models.py b/examples/models.py
index fecc6d7..d92db29 100644
--- a/examples/models.py
+++ b/examples/models.py
@@ -1,6 +1,9 @@
from django.db import models
+class Vat(models.Model):
+ vat_percentage = models.IntegerField()
+
class Book(models.Model):
HARDCOVER = 1
PAPERBACK = 2
@@ -16,5 +19,5 @@ class Book(models.Model):
price = models.DecimalField(max_digits=5, decimal_places=2)
pages = models.IntegerField(blank=True, null=True)
book_type = models.PositiveSmallIntegerField(choices=BOOK_TYPES)
-
+ vat = models.ForeignKey(Vat, on_delete=models.PROTECT, blank=True, null=True)
timestamp = models.DateField(auto_now_add=True, auto_now=False)
diff --git a/examples/templates/examples/delete_vat.html b/examples/templates/examples/delete_vat.html
new file mode 100644
index 0000000..ae371fd
--- /dev/null
+++ b/examples/templates/examples/delete_vat.html
@@ -0,0 +1,22 @@
+{% load widget_tweaks %}
+
+
diff --git a/examples/urls.py b/examples/urls.py
index 149f1ff..15cf3d8 100644
--- a/examples/urls.py
+++ b/examples/urls.py
@@ -9,6 +9,7 @@
path('update/', views.BookUpdateView.as_view(), name='update_book'),
path('read/', views.BookReadView.as_view(), name='read_book'),
path('delete/', views.BookDeleteView.as_view(), name='delete_book'),
+ path('delete_vat/', views.VatDeleteView.as_view(), name='delete_vat'),
path('signup/', views.SignUpView.as_view(), name='signup'),
path('login/', views.CustomLoginView.as_view(), name='login'),
]
diff --git a/examples/views.py b/examples/views.py
index 1c68fc4..e81cdba 100644
--- a/examples/views.py
+++ b/examples/views.py
@@ -8,7 +8,7 @@
BSModalDeleteView)
from .forms import BookForm, CustomUserCreationForm, CustomAuthenticationForm
-from .models import Book
+from .models import Book, Vat
class Index(generic.ListView):
@@ -43,7 +43,12 @@ class BookDeleteView(BSModalDeleteView):
success_message = 'Success: Book was deleted.'
success_url = reverse_lazy('index')
-
+class VatDeleteView(BSModalDeleteView):
+ model = Vat
+ template_name = 'examples/delete_vat.html'
+ success_message = 'Success: Vat was deleted.'
+ success_url = reverse_lazy('index')
+
class SignUpView(BSModalCreateView):
form_class = CustomUserCreationForm
template_name = 'examples/signup.html'
diff --git a/tests/tests_unit.py b/tests/tests_unit.py
index 9dd8555..5625d51 100644
--- a/tests/tests_unit.py
+++ b/tests/tests_unit.py
@@ -2,19 +2,27 @@
from django.contrib.messages import get_messages
from django.test import TestCase
+from examples.models import Vat
from examples.models import Book
class MixinsTest(TestCase):
def setUp(self):
+ self.vat_1 = Vat.objects.create(
+ vat_percentage=28
+ )
+ self.vat_2 = Vat.objects.create(
+ vat_percentage=13
+ )
self.book = Book.objects.create(
title='Life of Jane Doe',
publication_date='2019-01-01',
author='Jane Doe',
price=29.99,
pages=477,
- book_type=2
+ book_type=2,
+ vat=self.vat_1
)
self.user = User.objects.create_user(
username='user',
@@ -56,7 +64,8 @@ def test_CreateUpdateAjaxMixin(self):
'price': 19.99,
'pages': 449,
# Wrong value
- 'book_type': 'wrong_value'
+ 'book_type': 'wrong_value',
+ 'vat': 1
},
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
)
@@ -78,7 +87,8 @@ def test_CreateUpdateAjaxMixin(self):
'author': 'John Doe',
'price': 19.99,
'pages': 449,
- 'book_type': 1
+ 'book_type': 1,
+ 'vat': 1
}
)
@@ -103,7 +113,8 @@ def test_CreateUpdateAjaxMixin(self):
'price': 29.99,
'pages': 477,
# Wrong value
- 'book_type': 'wrong_value'
+ 'book_type': 'wrong_value',
+ 'vat': 1
},
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
)
@@ -125,7 +136,8 @@ def test_CreateUpdateAjaxMixin(self):
'author': 'Jane Doe',
'price': 29.99,
'pages': 477,
- 'book_type': 2
+ 'book_type': 2,
+ 'vat': 1
},
)
@@ -140,11 +152,22 @@ def test_DeleteMessageMixin(self):
"""
Delete object through BSModalDeleteView.
"""
+
+ response = self.client.post('/delete_vat/1')
+ messages = get_messages(response.wsgi_request)
+ self.assertEqual(len(messages), 1)
+ self.assertEqual(str(list(iter(messages))[0]), 'Can not remove this item, has a relation in the database.')
+
+ response = self.client.post('/delete_vat/2')
+ messages = get_messages(response.wsgi_request)
+ self.assertEqual(str(list(iter(messages))[1]), 'Success: Vat was deleted.')
# Request to delete view passes message to the response
response = self.client.post('/delete/1')
messages = get_messages(response.wsgi_request)
- self.assertEqual(len(messages), 1)
+ self.assertEqual(len(messages), 3)
+ self.assertEqual(str(list(iter(messages))[2]), 'Success: Book was deleted.')
+
def test_LoginAjaxMixin(self):
"""