kopia lustrzana https://github.com/wagtail/wagtail
Prevent exception when attempting to delete a model with a protected 1-to-1 relation
Modeladmin handles notification to the user if a model instance has protected ForeignKey relationships. However, if the protected relation is a OneToOneField it raises an exception: File ".../wagtail/wagtail/contrib/modeladmin/views.py", line 742, in post for obj in qs.all(): AttributeError: 'MyRelatedModel' object has no attribute 'all' because qs in this case is the related instance rather than a queryset of related instances (as is the case for a ForeignKey). This commit handles the OneToOneField case as well.pull/5506/head
rodzic
cdb13b6490
commit
4a93424654
|
@ -10,6 +10,7 @@ Changelog
|
||||||
* Fix: Added https support for Scribd oEmbed provider (Rodrigo)
|
* Fix: Added https support for Scribd oEmbed provider (Rodrigo)
|
||||||
* Fix: Changed StreamField group labels color so labels are visible (Catherine Farman)
|
* Fix: Changed StreamField group labels color so labels are visible (Catherine Farman)
|
||||||
* Fix: Prevented images with a very wide aspect ratio from being displayed distorted in the rich text editor (Iman Syed)
|
* Fix: Prevented images with a very wide aspect ratio from being displayed distorted in the rich text editor (Iman Syed)
|
||||||
|
* Fix: Prevent exception when deleting a model with a protected One-to-one relationship (Neal Todd)
|
||||||
|
|
||||||
|
|
||||||
2.6.1 (xx.xx.xxxx) - IN DEVELOPMENT
|
2.6.1 (xx.xx.xxxx) - IN DEVELOPMENT
|
||||||
|
|
|
@ -28,6 +28,7 @@ Bug fixes
|
||||||
* Added https support for Scribd oEmbed provider (Rodrigo)
|
* Added https support for Scribd oEmbed provider (Rodrigo)
|
||||||
* Changed StreamField group label color so labels are visible (Catherine Farman)
|
* Changed StreamField group label color so labels are visible (Catherine Farman)
|
||||||
* Prevented images with a very wide aspect ratio from being displayed distorted in the rich text editor (Iman Syed)
|
* Prevented images with a very wide aspect ratio from being displayed distorted in the rich text editor (Iman Syed)
|
||||||
|
* Prevent exception when deleting a model with a protected One-to-one relationship (Neal Todd)
|
||||||
|
|
||||||
|
|
||||||
Upgrade considerations
|
Upgrade considerations
|
||||||
|
|
|
@ -439,6 +439,23 @@ class TestDeleteViewWithProtectedRelation(TestCase, WagtailTestUtils):
|
||||||
self.assertFalse(Author.objects.filter(id=4).exists())
|
self.assertFalse(Author.objects.filter(id=4).exists())
|
||||||
|
|
||||||
|
|
||||||
|
def test_post_with_1to1_dependent_object(self):
|
||||||
|
response = self.post(5)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(
|
||||||
|
response,
|
||||||
|
"'Harper Lee' is currently referenced by other objects"
|
||||||
|
)
|
||||||
|
self.assertContains(
|
||||||
|
response,
|
||||||
|
"<li><b>Solo Book:</b> To Kill a Mockingbird</li>"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Author not deleted
|
||||||
|
self.assertTrue(Author.objects.filter(id=5).exists())
|
||||||
|
|
||||||
|
|
||||||
class TestDeleteViewModelReprPrimary(TestCase, WagtailTestUtils):
|
class TestDeleteViewModelReprPrimary(TestCase, WagtailTestUtils):
|
||||||
fixtures = ['modeladmintest_test.json']
|
fixtures = ['modeladmintest_test.json']
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,12 @@ from django.contrib.admin.options import IncorrectLookupParameters
|
||||||
from django.contrib.admin.utils import (
|
from django.contrib.admin.utils import (
|
||||||
get_fields_from_path, label_for_field, lookup_needs_distinct, prepare_lookup_value, quote, unquote)
|
get_fields_from_path, label_for_field, lookup_needs_distinct, prepare_lookup_value, quote, unquote)
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.exceptions import ImproperlyConfigured, PermissionDenied, SuspiciousOperation
|
from django.core.exceptions import (
|
||||||
|
ImproperlyConfigured, ObjectDoesNotExist, PermissionDenied, SuspiciousOperation)
|
||||||
from django.core.paginator import InvalidPage, Paginator
|
from django.core.paginator import InvalidPage, Paginator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.fields import FieldDoesNotExist
|
from django.db.models.fields import FieldDoesNotExist
|
||||||
from django.db.models.fields.related import ManyToManyField
|
from django.db.models.fields.related import ManyToManyField, OneToOneRel
|
||||||
from django.shortcuts import get_object_or_404, redirect
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
from django.template.defaultfilters import filesizeformat
|
from django.template.defaultfilters import filesizeformat
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
|
@ -738,9 +739,17 @@ class DeleteView(InstanceSpecificView):
|
||||||
obj.field, ManyToManyField))
|
obj.field, ManyToManyField))
|
||||||
for rel in fields:
|
for rel in fields:
|
||||||
if rel.on_delete == models.PROTECT:
|
if rel.on_delete == models.PROTECT:
|
||||||
qs = getattr(self.instance, rel.get_accessor_name())
|
if isinstance(rel, OneToOneRel):
|
||||||
for obj in qs.all():
|
try:
|
||||||
linked_objects.append(obj)
|
obj = getattr(self.instance, rel.get_accessor_name())
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
linked_objects.append(obj)
|
||||||
|
else:
|
||||||
|
qs = getattr(self.instance, rel.get_accessor_name())
|
||||||
|
for obj in qs.all():
|
||||||
|
linked_objects.append(obj)
|
||||||
context = self.get_context_data(
|
context = self.get_context_data(
|
||||||
protected_error=True,
|
protected_error=True,
|
||||||
linked_objects=linked_objects
|
linked_objects=linked_objects
|
||||||
|
|
|
@ -31,6 +31,14 @@
|
||||||
"date_of_birth": "1898-11-29"
|
"date_of_birth": "1898-11-29"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pk": 5,
|
||||||
|
"model": "modeladmintest.author",
|
||||||
|
"fields": {
|
||||||
|
"name": "Harper Lee",
|
||||||
|
"date_of_birth": "1926-04-28"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
"model": "modeladmintest.book",
|
"model": "modeladmintest.book",
|
||||||
|
@ -63,6 +71,14 @@
|
||||||
"author_id": 3
|
"author_id": 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pk": 4,
|
||||||
|
"model": "modeladmintest.solobook",
|
||||||
|
"fields": {
|
||||||
|
"title": "To Kill a Mockingbird",
|
||||||
|
"author_id": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pk": "boom",
|
"pk": "boom",
|
||||||
"model": "modeladmintest.token",
|
"model": "modeladmintest.token",
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 2.1.10 on 2019-07-17 17:46
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('modeladmintest', '0007_friend'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SoloBook',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('title', models.CharField(max_length=255)),
|
||||||
|
('author', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='modeladmintest.Author')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -40,6 +40,14 @@ class Book(models.Model, index.Indexed):
|
||||||
return self.title
|
return self.title
|
||||||
|
|
||||||
|
|
||||||
|
class SoloBook(models.Model):
|
||||||
|
author = models.OneToOneField(Author, on_delete=models.PROTECT)
|
||||||
|
title = models.CharField(max_length=255)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.title
|
||||||
|
|
||||||
|
|
||||||
class Token(models.Model):
|
class Token(models.Model):
|
||||||
key = models.CharField(max_length=40, primary_key=True)
|
key = models.CharField(max_length=40, primary_key=True)
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue