summaryrefslogtreecommitdiff
path: root/tests/modeladmin
diff options
context:
space:
mode:
authorJohannes Hoppe <info@johanneshoppe.com>2017-05-10 14:48:57 +0200
committerTim Graham <timograham@gmail.com>2017-09-18 13:48:02 -0400
commit94cd8efc50c717cd00244f4b2233f971a53b205e (patch)
treeab1f13a12121907a561962181eaceeab793cb838 /tests/modeladmin
parent01a294f8f014a32e288958701540ea47dcb9fc14 (diff)
Fixed #14370 -- Allowed using a Select2 widget for ForeignKey and ManyToManyField in the admin.
Thanks Florian Apolloner and Tim Graham for review and contributing to the patch.
Diffstat (limited to 'tests/modeladmin')
-rw-r--r--tests/modeladmin/models.py9
-rw-r--r--tests/modeladmin/test_checks.py100
-rw-r--r--tests/modeladmin/tests.py32
3 files changed, 134 insertions, 7 deletions
diff --git a/tests/modeladmin/models.py b/tests/modeladmin/models.py
index 861a2dbb9d..c0d3c772c9 100644
--- a/tests/modeladmin/models.py
+++ b/tests/modeladmin/models.py
@@ -14,6 +14,15 @@ class Band(models.Model):
return self.name
+class Song(models.Model):
+ name = models.CharField(max_length=100)
+ band = models.ForeignKey(Band, models.CASCADE)
+ featuring = models.ManyToManyField(Band, related_name='featured')
+
+ def __str__(self):
+ return self.name
+
+
class Concert(models.Model):
main_band = models.ForeignKey(Band, models.CASCADE, related_name='main_concerts')
opening_band = models.ForeignKey(Band, models.CASCADE, related_name='opening_concerts', blank=True)
diff --git a/tests/modeladmin/test_checks.py b/tests/modeladmin/test_checks.py
index acca6b18a2..eaca153bd8 100644
--- a/tests/modeladmin/test_checks.py
+++ b/tests/modeladmin/test_checks.py
@@ -6,14 +6,16 @@ from django.core.checks import Error
from django.forms.models import BaseModelFormSet
from django.test import SimpleTestCase
-from .models import Band, ValidationTestInlineModel, ValidationTestModel
+from .models import Band, Song, ValidationTestInlineModel, ValidationTestModel
class CheckTestCase(SimpleTestCase):
- def assertIsInvalid(self, model_admin, model, msg, id=None, hint=None, invalid_obj=None):
+ def assertIsInvalid(self, model_admin, model, msg, id=None, hint=None, invalid_obj=None, admin_site=None):
+ if admin_site is None:
+ admin_site = AdminSite()
invalid_obj = invalid_obj or model_admin
- admin_obj = model_admin(model, AdminSite())
+ admin_obj = model_admin(model, admin_site)
self.assertEqual(admin_obj.check(), [Error(msg, hint=hint, obj=invalid_obj, id=id)])
def assertIsInvalidRegexp(self, model_admin, model, msg, id=None, hint=None, invalid_obj=None):
@@ -30,8 +32,10 @@ class CheckTestCase(SimpleTestCase):
self.assertEqual(error.id, id)
self.assertRegex(error.msg, msg)
- def assertIsValid(self, model_admin, model):
- admin_obj = model_admin(model, AdminSite())
+ def assertIsValid(self, model_admin, model, admin_site=None):
+ if admin_site is None:
+ admin_site = AdminSite()
+ admin_obj = model_admin(model, admin_site)
self.assertEqual(admin_obj.check(), [])
@@ -1153,3 +1157,89 @@ class ListDisplayEditableTests(CheckTestCase):
"'list_display_links'.",
id='admin.E123',
)
+
+
+class AutocompleteFieldsTests(CheckTestCase):
+ def test_autocomplete_e036(self):
+ class Admin(ModelAdmin):
+ autocomplete_fields = 'name'
+
+ self.assertIsInvalid(
+ Admin, Band,
+ msg="The value of 'autocomplete_fields' must be a list or tuple.",
+ id='admin.E036',
+ invalid_obj=Admin,
+ )
+
+ def test_autocomplete_e037(self):
+ class Admin(ModelAdmin):
+ autocomplete_fields = ('nonexistent',)
+
+ self.assertIsInvalid(
+ Admin, ValidationTestModel,
+ msg=(
+ "The value of 'autocomplete_fields[0]' refers to 'nonexistent', "
+ "which is not an attribute of 'modeladmin.ValidationTestModel'."
+ ),
+ id='admin.E037',
+ invalid_obj=Admin,
+ )
+
+ def test_autocomplete_e38(self):
+ class Admin(ModelAdmin):
+ autocomplete_fields = ('name',)
+
+ self.assertIsInvalid(
+ Admin, ValidationTestModel,
+ msg=(
+ "The value of 'autocomplete_fields[0]' must be a foreign "
+ "key or a many-to-many field."
+ ),
+ id='admin.E038',
+ invalid_obj=Admin,
+ )
+
+ def test_autocomplete_e039(self):
+ class Admin(ModelAdmin):
+ autocomplete_fields = ('band',)
+
+ self.assertIsInvalid(
+ Admin, Song,
+ msg=(
+ 'An admin for model "Band" has to be registered '
+ 'to be referenced by Admin.autocomplete_fields.'
+ ),
+ id='admin.E039',
+ invalid_obj=Admin,
+ )
+
+ def test_autocomplete_e040(self):
+ class NoSearchFieldsAdmin(ModelAdmin):
+ pass
+
+ class AutocompleteAdmin(ModelAdmin):
+ autocomplete_fields = ('featuring',)
+
+ site = AdminSite()
+ site.register(Band, NoSearchFieldsAdmin)
+ self.assertIsInvalid(
+ AutocompleteAdmin, Song,
+ msg=(
+ 'NoSearchFieldsAdmin must define "search_fields", because '
+ 'it\'s referenced by AutocompleteAdmin.autocomplete_fields.'
+ ),
+ id='admin.E040',
+ invalid_obj=AutocompleteAdmin,
+ admin_site=site,
+ )
+
+ def test_autocomplete_is_valid(self):
+ class SearchFieldsAdmin(ModelAdmin):
+ search_fields = 'name'
+
+ class AutocompleteAdmin(ModelAdmin):
+ autocomplete_fields = ('featuring',)
+
+ site = AdminSite()
+ site.register(Band, SearchFieldsAdmin)
+ self.assertIsValid(AutocompleteAdmin, Song, admin_site=site)
diff --git a/tests/modeladmin/tests.py b/tests/modeladmin/tests.py
index 25b9dfed69..67bed3d697 100644
--- a/tests/modeladmin/tests.py
+++ b/tests/modeladmin/tests.py
@@ -7,14 +7,17 @@ from django.contrib.admin.options import (
get_content_type_for_model,
)
from django.contrib.admin.sites import AdminSite
-from django.contrib.admin.widgets import AdminDateWidget, AdminRadioSelect
+from django.contrib.admin.widgets import (
+ AdminDateWidget, AdminRadioSelect, AutocompleteSelect,
+ AutocompleteSelectMultiple,
+)
from django.contrib.auth.models import User
from django.db import models
from django.forms.widgets import Select
from django.test import SimpleTestCase, TestCase
from django.test.utils import isolate_apps
-from .models import Band, Concert
+from .models import Band, Concert, Song
class MockRequest:
@@ -638,6 +641,31 @@ class ModelAdminTests(TestCase):
self.assertEqual(fetched.change_message, str(message))
self.assertEqual(fetched.object_repr, str(self.band))
+ def test_get_autocomplete_fields(self):
+ class NameAdmin(ModelAdmin):
+ search_fields = ['name']
+
+ class SongAdmin(ModelAdmin):
+ autocomplete_fields = ['featuring']
+ fields = ['featuring', 'band']
+
+ class OtherSongAdmin(SongAdmin):
+ def get_autocomplete_fields(self, request):
+ return ['band']
+
+ self.site.register(Band, NameAdmin)
+ try:
+ # Uses autocomplete_fields if not overridden.
+ model_admin = SongAdmin(Song, self.site)
+ form = model_admin.get_form(request)()
+ self.assertIsInstance(form.fields['featuring'].widget.widget, AutocompleteSelectMultiple)
+ # Uses overridden get_autocomplete_fields
+ model_admin = OtherSongAdmin(Song, self.site)
+ form = model_admin.get_form(request)()
+ self.assertIsInstance(form.fields['band'].widget.widget, AutocompleteSelect)
+ finally:
+ self.site.unregister(Band)
+
class ModelAdminPermissionTests(SimpleTestCase):