diff --git a/django/contrib/admin/validation.py b/django/contrib/admin/validation.py
index 027db63..f6de85c 100644
a
|
b
|
from django.forms.models import (BaseModelForm, BaseModelFormSet, fields_for_mod
|
6 | 6 | from django.contrib.admin.util import get_fields_from_path, NotRelationField |
7 | 7 | from django.contrib.admin.options import flatten_fieldsets, BaseModelAdmin |
8 | 8 | from django.contrib.admin.options import HORIZONTAL, VERTICAL |
| 9 | from django.template.base import TemplateDoesNotExist |
| 10 | from django.template.loader import find_template |
9 | 11 | |
10 | 12 | |
11 | 13 | __all__ = ['validate'] |
… |
… |
def validate_inline(cls, parent, parent_model):
|
199 | 201 | raise ImproperlyConfigured("%s cannot exclude the field " |
200 | 202 | "'%s' - this is the foreign key to the parent model " |
201 | 203 | "%s." % (cls.__name__, fk.name, parent_model.__name__)) |
| 204 | |
| 205 | # template |
| 206 | template = getattr(cls, 'template', None) |
| 207 | if template is None: |
| 208 | raise ImproperlyConfigured("%s.template cannot be None" % cls.__name__) |
| 209 | try: |
| 210 | find_template(template) |
| 211 | except TemplateDoesNotExist: |
| 212 | raise ImproperlyConfigured("%s.template cannot be loaded, template " |
| 213 | "'%s' could not be found" % (cls.__name__, template)) |
202 | 214 | |
203 | 215 | def validate_base(cls, model): |
204 | 216 | opts = model._meta |
diff --git a/tests/regressiontests/admin_inlines/models.py b/tests/regressiontests/admin_inlines/models.py
index 4e5c4e3..a5da886 100644
a
|
b
|
from django.db import models
|
6 | 6 | from django.contrib import admin |
7 | 7 | from django.contrib.contenttypes.models import ContentType |
8 | 8 | from django.contrib.contenttypes import generic |
| 9 | from django.contrib.admin.options import InlineModelAdmin |
9 | 10 | |
10 | 11 | class Parent(models.Model): |
11 | 12 | name = models.CharField(max_length=50) |
… |
… |
class InlineWeakness(admin.TabularInline):
|
123 | 124 | extra = 1 |
124 | 125 | |
125 | 126 | admin.site.register(Fashionista, inlines=[InlineWeakness]) |
| 127 | |
| 128 | # Don't register this because we only need it to test validation |
| 129 | class InnerInlineNoTemplate(InlineModelAdmin): |
| 130 | model = Inner |
| 131 | |
| 132 | # Don't register this because we only need it to test validation |
| 133 | class InnerInlineNonExistingTemplate(admin.TabularInline): |
| 134 | model = Inner |
| 135 | template = "does/not/exist.html" |
| 136 | No newline at end of file |
diff --git a/tests/regressiontests/admin_inlines/tests.py b/tests/regressiontests/admin_inlines/tests.py
index b10474d..c5ffbb7 100644
a
|
b
|
|
1 | 1 | from django.contrib.admin.helpers import InlineAdminForm |
2 | 2 | from django.contrib.contenttypes.models import ContentType |
| 3 | from django.contrib.admin.validation import validate_inline |
| 4 | from django.core.exceptions import ImproperlyConfigured |
3 | 5 | from django.test import TestCase |
4 | 6 | |
5 | 7 | # local test models |
6 | 8 | from models import (Holder, Inner, InnerInline, Holder2, Inner2, Holder3, |
7 | | Inner3, Person, OutfitItem, Fashionista, Teacher, Parent, Child) |
| 9 | Inner3, Person, OutfitItem, Fashionista, Teacher, Parent, Child, |
| 10 | InnerInlineNonExistingTemplate, InnerInlineNoTemplate, HolderAdmin) |
| 11 | |
| 12 | # local test models |
8 | 13 | |
9 | 14 | |
10 | 15 | class TestInline(TestCase): |
… |
… |
class TestInline(TestCase):
|
66 | 71 | response = self.client.post('/test_admin/admin/admin_inlines/fashionista/add/', data) |
67 | 72 | self.assertEqual(response.status_code, 302) |
68 | 73 | self.assertEqual(len(Fashionista.objects.filter(person__firstname='Imelda')), 1) |
| 74 | |
| 75 | def test_inline_template_validation(self): |
| 76 | self.assertRaises(ImproperlyConfigured, validate_inline, |
| 77 | InnerInlineNoTemplate, HolderAdmin, Holder) |
| 78 | self.assertRaises(ImproperlyConfigured, validate_inline, |
| 79 | InnerInlineNonExistingTemplate, HolderAdmin, Holder) |
| 80 | # check that regular inlines don't raise an exception: |
| 81 | validate_inline(InnerInline, HolderAdmin, Holder) |
| 82 | |
69 | 83 | |
70 | 84 | class TestInlineMedia(TestCase): |
71 | 85 | fixtures = ['admin-views-users.xml'] |
… |
… |
class TestInlineAdminForm(TestCase):
|
118 | 132 | |
119 | 133 | iaf = InlineAdminForm(None, None, {}, {}, joe) |
120 | 134 | parent_ct = ContentType.objects.get_for_model(Parent) |
121 | | self.assertEqual(iaf.original.content_type, parent_ct) |
| 135 | self.assertEqual(iaf.original.content_type, parent_ct) |
| 136 | No newline at end of file |