summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2013-06-19 12:03:20 +0100
committerAndrew Godwin <andrew@aeracode.org>2013-06-19 12:05:23 +0100
commit9daf81b94e7945d7adfdf62206cf9cb436166f0d (patch)
tree0ca2a77977432d0c139886297afb433569b588ca /tests
parent315ab41e416c777d4f42932d42df07872e8f8895 (diff)
parentd9a43545be1af95a13c181c8b178f5631d3a4148 (diff)
Merge remote-tracking branch 'core/master' into schema-alteration
Conflicts: django/db/models/loading.py
Diffstat (limited to 'tests')
-rw-r--r--tests/admin_inlines/tests.py4
-rw-r--r--tests/admin_scripts/tests.py22
-rw-r--r--tests/admin_util/tests.py4
-rw-r--r--tests/admin_views/tests.py167
-rw-r--r--tests/admin_widgets/tests.py8
-rw-r--r--tests/backends/tests.py7
-rw-r--r--tests/basic/tests.py3
-rw-r--r--tests/cache/tests.py2
-rw-r--r--tests/compat_checks/__init__.py (renamed from tests/shared_models/__init__.py)0
-rw-r--r--tests/compat_checks/models.py1
-rw-r--r--tests/compat_checks/tests.py107
-rw-r--r--tests/delete_regress/tests.py6
-rw-r--r--tests/file_storage/tests.py20
-rw-r--r--tests/file_storage/urls.py7
-rw-r--r--tests/fixtures/tests.py7
-rw-r--r--tests/fixtures_model_package/tests.py3
-rw-r--r--tests/fixtures_regress/tests.py6
-rw-r--r--tests/forms_tests/tests/test_forms.py43
-rw-r--r--tests/forms_tests/tests/test_formsets.py154
-rw-r--r--tests/forms_tests/tests/test_regressions.py4
-rw-r--r--tests/forms_tests/tests/test_widgets.py2
-rw-r--r--tests/forms_tests/tests/tests.py6
-rw-r--r--tests/generic_views/test_base.py20
-rw-r--r--tests/get_or_create/tests.py2
-rw-r--r--tests/handlers/tests.py2
-rw-r--r--tests/lookup/models.py21
-rw-r--r--tests/lookup/tests.py793
-rw-r--r--tests/m2m_through_regress/tests.py1
-rw-r--r--tests/middleware/tests.py3
-rw-r--r--tests/model_forms/models.py37
-rw-r--r--tests/model_forms/tests.py179
-rw-r--r--tests/model_forms_regress/tests.py4
-rw-r--r--tests/model_formsets/tests.py52
-rw-r--r--tests/multiple_database/tests.py6
-rw-r--r--tests/proxy_model_inheritance/tests.py8
-rw-r--r--tests/queries/tests.py106
-rw-r--r--tests/queryset_pickle/models.py10
-rw-r--r--tests/queryset_pickle/tests.py43
-rw-r--r--tests/requests/tests.py2
-rwxr-xr-xtests/runtests.py15
-rw-r--r--tests/select_for_update/tests.py2
-rw-r--r--tests/serializers/tests.py3
-rw-r--r--tests/servers/tests.py9
-rw-r--r--tests/settings_tests/tests.py2
-rw-r--r--tests/shared_models/models.py37
-rw-r--r--tests/signals_regress/models.py18
-rw-r--r--tests/signals_regress/tests.py6
-rw-r--r--tests/swappable_models/tests.py7
-rw-r--r--tests/syncdb_signals/tests.py7
-rw-r--r--tests/test_runner/tests.py22
-rw-r--r--tests/test_suite_override/tests.py5
-rw-r--r--tests/test_utils/tests.py6
-rw-r--r--tests/transactions/tests.py16
-rw-r--r--tests/transactions_regress/tests.py21
-rw-r--r--tests/urlpatterns_reverse/tests.py14
-rw-r--r--tests/validation/models.py1
-rw-r--r--tests/validation/tests.py6
-rw-r--r--tests/validators/tests.py6
-rw-r--r--tests/view_tests/tests/test_i18n.py2
59 files changed, 1411 insertions, 666 deletions
diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py
index 78ccf074d5..41dc0e32de 100644
--- a/tests/admin_inlines/tests.py
+++ b/tests/admin_inlines/tests.py
@@ -505,9 +505,11 @@ class TestInlinePermissions(TestCase):
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class SeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
- webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
+
+ available_apps = ['admin_inlines'] + AdminSeleniumWebDriverTestCase.available_apps
fixtures = ['admin-views-users.xml']
urls = "admin_inlines.urls"
+ webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
def test_add_stackeds(self):
"""
diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py
index 9e6b1f557b..2f399acb23 100644
--- a/tests/admin_scripts/tests.py
+++ b/tests/admin_scripts/tests.py
@@ -1192,6 +1192,21 @@ class ManageRunserver(AdminScriptTestCase):
self.cmd.handle(addrport="deadbeef:7654")
self.assertServerSettings('deadbeef', '7654')
+class ManageRunserverEmptyAllowedHosts(AdminScriptTestCase):
+ def setUp(self):
+ self.write_settings('settings.py', sdict={
+ 'ALLOWED_HOSTS': [],
+ 'DEBUG': False,
+ })
+
+ def tearDown(self):
+ self.remove_settings('settings.py')
+
+ def test_empty_allowed_hosts_error(self):
+ out, err = self.run_manage(['runserver'])
+ self.assertNoOutput(out)
+ self.assertOutput(err, 'CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False.')
+
##########################################################################
# COMMAND PROCESSING TESTS
@@ -1459,6 +1474,13 @@ class ArgumentOrder(AdminScriptTestCase):
class StartProject(LiveServerTestCase, AdminScriptTestCase):
+ available_apps = [
+ 'admin_scripts',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ ]
+
def test_wrong_args(self):
"Make sure passing the wrong kinds of arguments raises a CommandError"
out, err = self.run_django_admin(['startproject'])
diff --git a/tests/admin_util/tests.py b/tests/admin_util/tests.py
index 4a9a203f50..637f643261 100644
--- a/tests/admin_util/tests.py
+++ b/tests/admin_util/tests.py
@@ -301,7 +301,7 @@ class UtilTests(SimpleTestCase):
self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(),
'<label for="id_text" class="required inline"><i>text</i>:</label>')
self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(),
- '<label for="id_cb" class="vCheckboxLabel required inline"><i>cb</i></label>')
+ '<label for="id_cb" class="vCheckboxLabel required inline"><i>cb</i>:</label>')
# normal strings needs to be escaped
class MyForm(forms.Form):
@@ -312,7 +312,7 @@ class UtilTests(SimpleTestCase):
self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(),
'<label for="id_text" class="required inline">&amp;text:</label>')
self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(),
- '<label for="id_cb" class="vCheckboxLabel required inline">&amp;cb</label>')
+ '<label for="id_cb" class="vCheckboxLabel required inline">&amp;cb:</label>')
def test_flatten_fieldsets(self):
"""
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index 8c8a65318c..528c728069 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -22,7 +22,7 @@ from django.contrib.admin.util import quote
from django.contrib.admin.views.main import IS_POPUP_VAR
from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
from django.contrib.auth import REDIRECT_FIELD_NAME
-from django.contrib.auth.models import Group, User, Permission, UNUSABLE_PASSWORD
+from django.contrib.auth.models import Group, User, Permission
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.db import connection
@@ -3308,9 +3308,11 @@ class PrePopulatedTest(TestCase):
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class SeleniumAdminViewsFirefoxTests(AdminSeleniumWebDriverTestCase):
- webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
- urls = "admin_views.urls"
+
+ available_apps = ['admin_views'] + AdminSeleniumWebDriverTestCase.available_apps
fixtures = ['admin-views-users.xml']
+ urls = "admin_views.urls"
+ webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
def test_prepopulated_fields(self):
"""
@@ -3630,7 +3632,7 @@ class UserAdminTest(TestCase):
new_user = User.objects.order_by('-id')[0]
self.assertRedirects(response, '/test_admin/admin/auth/user/%s/' % new_user.pk)
self.assertEqual(User.objects.count(), user_count + 1)
- self.assertNotEqual(new_user.password, UNUSABLE_PASSWORD)
+ self.assertTrue(new_user.has_usable_password())
def test_save_continue_editing_button(self):
user_count = User.objects.count()
@@ -3643,7 +3645,7 @@ class UserAdminTest(TestCase):
new_user = User.objects.order_by('-id')[0]
self.assertRedirects(response, '/test_admin/admin/auth/user/%s/' % new_user.pk)
self.assertEqual(User.objects.count(), user_count + 1)
- self.assertNotEqual(new_user.password, UNUSABLE_PASSWORD)
+ self.assertTrue(new_user.has_usable_password())
def test_password_mismatch(self):
response = self.client.post('/test_admin/admin/auth/user/add/', {
@@ -3689,7 +3691,7 @@ class UserAdminTest(TestCase):
new_user = User.objects.order_by('-id')[0]
self.assertRedirects(response, '/test_admin/admin/auth/user/add/')
self.assertEqual(User.objects.count(), user_count + 1)
- self.assertNotEqual(new_user.password, UNUSABLE_PASSWORD)
+ self.assertTrue(new_user.has_usable_password())
def test_user_permission_performance(self):
u = User.objects.all()[0]
@@ -4155,3 +4157,156 @@ class AdminUserMessageTest(TestCase):
self.assertContains(response,
'<li class="extra_tag info">Test tags</li>',
html=True)
+
+
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
+class AdminKeepChangeListFiltersTests(TestCase):
+ urls = "admin_views.urls"
+ fixtures = ['admin-views-users.xml']
+
+ def setUp(self):
+ self.client.login(username='super', password='secret')
+
+ def tearDown(self):
+ self.client.logout()
+
+ def get_changelist_filters_querystring(self):
+ return urlencode({
+ 'is_superuser__exact': 0,
+ 'is_staff__exact': 0,
+ })
+
+ def get_preserved_filters_querystring(self):
+ return urlencode({
+ '_changelist_filters': self.get_changelist_filters_querystring()
+ })
+
+ def get_sample_user_id(self):
+ return 104
+
+ def get_changelist_url(self):
+ return '%s?%s' % (
+ reverse('admin:auth_user_changelist'),
+ self.get_changelist_filters_querystring(),
+ )
+
+ def get_add_url(self):
+ return '%s?%s' % (
+ reverse('admin:auth_user_add'),
+ self.get_preserved_filters_querystring(),
+ )
+
+ def get_change_url(self, user_id=None):
+ if user_id is None:
+ user_id = self.get_sample_user_id()
+ return "%s?%s" % (
+ reverse('admin:auth_user_change', args=(user_id,)),
+ self.get_preserved_filters_querystring(),
+ )
+
+ def get_history_url(self, user_id=None):
+ if user_id is None:
+ user_id = self.get_sample_user_id()
+ return "%s?%s" % (
+ reverse('admin:auth_user_history', args=(user_id,)),
+ self.get_preserved_filters_querystring(),
+ )
+
+ def get_delete_url(self, user_id=None):
+ if user_id is None:
+ user_id = self.get_sample_user_id()
+ return "%s?%s" % (
+ reverse('admin:auth_user_delete', args=(user_id,)),
+ self.get_preserved_filters_querystring(),
+ )
+
+ def test_changelist_view(self):
+ response = self.client.get(self.get_changelist_url())
+ self.assertEqual(response.status_code, 200)
+
+ # Check the `change_view` link has the correct querystring.
+ detail_link = """<a href="%s">joepublic</a>""" % self.get_change_url()
+ self.assertContains(response, detail_link, count=1)
+
+ def test_change_view(self):
+ # Get the `change_view`.
+ response = self.client.get(self.get_change_url())
+ self.assertEqual(response.status_code, 200)
+
+ # Check the form action.
+ form_action = """<form enctype="multipart/form-data" action="?%s" method="post" id="user_form">""" % self.get_preserved_filters_querystring()
+ self.assertContains(response, form_action, count=1)
+
+ # Check the history link.
+ history_link = """<a href="%s" class="historylink">History</a>""" % self.get_history_url()
+ self.assertContains(response, history_link, count=1)
+
+ # Check the delete link.
+ delete_link = """<a href="%s" class="deletelink">Delete</a>""" % (self.get_delete_url())
+ self.assertContains(response, delete_link, count=1)
+
+ # Test redirect on "Save".
+ post_data = {
+ 'username': 'joepublic',
+ 'last_login_0': '2007-05-30',
+ 'last_login_1': '13:20:10',
+ 'date_joined_0': '2007-05-30',
+ 'date_joined_1': '13:20:10',
+ }
+
+ post_data['_save'] = 1
+ response = self.client.post(self.get_change_url(), data=post_data)
+ self.assertRedirects(response, self.get_changelist_url())
+ post_data.pop('_save')
+
+ # Test redirect on "Save and continue".
+ post_data['_continue'] = 1
+ response = self.client.post(self.get_change_url(), data=post_data)
+ self.assertRedirects(response, self.get_change_url())
+ post_data.pop('_continue')
+
+ # Test redirect on "Save and add new".
+ post_data['_addanother'] = 1
+ response = self.client.post(self.get_change_url(), data=post_data)
+ self.assertRedirects(response, self.get_add_url())
+ post_data.pop('_addanother')
+
+ def test_add_view(self):
+ # Get the `add_view`.
+ response = self.client.get(self.get_add_url())
+ self.assertEqual(response.status_code, 200)
+
+ # Check the form action.
+ form_action = """<form enctype="multipart/form-data" action="?%s" method="post" id="user_form">""" % self.get_preserved_filters_querystring()
+ self.assertContains(response, form_action, count=1)
+
+ # Test redirect on "Save".
+ post_data = {
+ 'username': 'dummy',
+ 'password1': 'test',
+ 'password2': 'test',
+ }
+
+ post_data['_save'] = 1
+ response = self.client.post(self.get_add_url(), data=post_data)
+ self.assertRedirects(response, self.get_change_url(User.objects.latest('pk').pk))
+ post_data.pop('_save')
+
+ # Test redirect on "Save and continue".
+ post_data['username'] = 'dummy2'
+ post_data['_continue'] = 1
+ response = self.client.post(self.get_add_url(), data=post_data)
+ self.assertRedirects(response, self.get_change_url(User.objects.latest('pk').pk))
+ post_data.pop('_continue')
+
+ # Test redirect on "Save and add new".
+ post_data['username'] = 'dummy3'
+ post_data['_addanother'] = 1
+ response = self.client.post(self.get_add_url(), data=post_data)
+ self.assertRedirects(response, self.get_add_url())
+ post_data.pop('_addanother')
+
+ def test_delete_view(self):
+ # Test redirect on "Delete".
+ response = self.client.post(self.get_delete_url(), {'post': 'yes'})
+ self.assertRedirects(response, self.get_changelist_url())
diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py
index 98f41c1490..4823883f42 100644
--- a/tests/admin_widgets/tests.py
+++ b/tests/admin_widgets/tests.py
@@ -470,9 +470,11 @@ class RelatedFieldWidgetWrapperTests(DjangoTestCase):
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class DateTimePickerSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
- webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
+
+ available_apps = ['admin_widgets'] + AdminSeleniumWebDriverTestCase.available_apps
fixtures = ['admin-widgets-users.xml']
urls = "admin_widgets.urls"
+ webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
def test_show_hide_date_time_picker_widgets(self):
"""
@@ -526,9 +528,11 @@ class DateTimePickerSeleniumIETests(DateTimePickerSeleniumFirefoxTests):
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class HorizontalVerticalFilterSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
- webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
+
+ available_apps = ['admin_widgets'] + AdminSeleniumWebDriverTestCase.available_apps
fixtures = ['admin-widgets-users.xml']
urls = "admin_widgets.urls"
+ webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
def setUp(self):
self.lisa = models.Student.objects.create(name='Lisa')
diff --git a/tests/backends/tests.py b/tests/backends/tests.py
index 08cae0f7c3..b6e3e9e36f 100644
--- a/tests/backends/tests.py
+++ b/tests/backends/tests.py
@@ -345,6 +345,8 @@ class PostgresNewConnectionTest(TestCase):
# connection would implicitly rollback and cause problems during teardown.
class ConnectionCreatedSignalTest(TransactionTestCase):
+ available_apps = []
+
# Unfortunately with sqlite3 the in-memory test database cannot be closed,
# and so it cannot be re-opened during testing.
@skipUnlessDBFeature('test_db_allows_multiple_connections')
@@ -514,6 +516,8 @@ class BackendTestCase(TestCase):
# verify if its type is django.database.db.IntegrityError.
class FkConstraintsTests(TransactionTestCase):
+ available_apps = ['backends']
+
def setUp(self):
# Create a Reporter.
self.r = models.Reporter.objects.create(first_name='John', last_name='Smith')
@@ -777,6 +781,9 @@ class MySQLPKZeroTests(TestCase):
class DBConstraintTestCase(TransactionTestCase):
+
+ available_apps = ['backends']
+
def test_can_reference_existant(self):
obj = models.Object.objects.create()
ref = models.ObjectReference.objects.create(obj=obj)
diff --git a/tests/basic/tests.py b/tests/basic/tests.py
index 6bf46cce9b..4b79c47be5 100644
--- a/tests/basic/tests.py
+++ b/tests/basic/tests.py
@@ -686,6 +686,9 @@ class ModelTest(TestCase):
class ConcurrentSaveTests(TransactionTestCase):
+
+ available_apps = ['basic']
+
@skipUnlessDBFeature('test_db_allows_multiple_connections')
def test_concurrent_delete_with_save(self):
"""
diff --git a/tests/cache/tests.py b/tests/cache/tests.py
index da80c48058..7413a4aae6 100644
--- a/tests/cache/tests.py
+++ b/tests/cache/tests.py
@@ -827,6 +827,8 @@ def custom_key_func(key, key_prefix, version):
class DBCacheTests(BaseCacheTests, TransactionTestCase):
+
+ available_apps = ['cache']
backend_name = 'django.core.cache.backends.db.DatabaseCache'
def setUp(self):
diff --git a/tests/shared_models/__init__.py b/tests/compat_checks/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/tests/shared_models/__init__.py
+++ b/tests/compat_checks/__init__.py
diff --git a/tests/compat_checks/models.py b/tests/compat_checks/models.py
new file mode 100644
index 0000000000..78a10abba6
--- /dev/null
+++ b/tests/compat_checks/models.py
@@ -0,0 +1 @@
+# Stubby.
diff --git a/tests/compat_checks/tests.py b/tests/compat_checks/tests.py
new file mode 100644
index 0000000000..879988c905
--- /dev/null
+++ b/tests/compat_checks/tests.py
@@ -0,0 +1,107 @@
+from django.core.compat_checks import base
+from django.core.compat_checks import django_1_6_0
+from django.core.management.commands import checksetup
+from django.core.management import call_command
+from django.test import TestCase
+
+
+class StubCheckModule(object):
+ # Has no ``run_checks`` attribute & will trigger a warning.
+ __name__ = 'StubCheckModule'
+
+
+class FakeWarnings(object):
+ def __init__(self):
+ self._warnings = []
+
+ def warn(self, message):
+ self._warnings.append(message)
+
+
+class CompatChecksTestCase(TestCase):
+ def setUp(self):
+ super(CompatChecksTestCase, self).setUp()
+
+ # We're going to override the list of checks to perform for test
+ # consistency in the future.
+ self.old_compat_checks = base.COMPAT_CHECKS
+ base.COMPAT_CHECKS = [
+ django_1_6_0,
+ ]
+
+ def tearDown(self):
+ # Restore what's supposed to be in ``COMPAT_CHECKS``.
+ base.COMPAT_CHECKS = self.old_compat_checks
+ super(CompatChecksTestCase, self).tearDown()
+
+ def test_check_test_runner_new_default(self):
+ with self.settings(TEST_RUNNER='django.test.runner.DiscoverRunner'):
+ result = django_1_6_0.check_test_runner()
+ self.assertTrue("You have not explicitly set 'TEST_RUNNER'" in result)
+
+ def test_check_test_runner_overridden(self):
+ with self.settings(TEST_RUNNER='myapp.test.CustomRunnner'):
+ self.assertEqual(django_1_6_0.check_test_runner(), None)
+
+ def test_run_checks_new_default(self):
+ with self.settings(TEST_RUNNER='django.test.runner.DiscoverRunner'):
+ result = django_1_6_0.run_checks()
+ self.assertEqual(len(result), 1)
+ self.assertTrue("You have not explicitly set 'TEST_RUNNER'" in result[0])
+
+ def test_run_checks_overridden(self):
+ with self.settings(TEST_RUNNER='myapp.test.CustomRunnner'):
+ self.assertEqual(len(django_1_6_0.run_checks()), 0)
+
+ def test_check_compatibility(self):
+ with self.settings(TEST_RUNNER='django.test.runner.DiscoverRunner'):
+ result = base.check_compatibility()
+ self.assertEqual(len(result), 1)
+ self.assertTrue("You have not explicitly set 'TEST_RUNNER'" in result[0])
+
+ with self.settings(TEST_RUNNER='myapp.test.CustomRunnner'):
+ self.assertEqual(len(base.check_compatibility()), 0)
+
+ def test_check_compatibility_warning(self):
+ # First, we're patching over the ``COMPAT_CHECKS`` with a stub which
+ # will trigger the warning.
+ base.COMPAT_CHECKS = [
+ StubCheckModule(),
+ ]
+
+ # Next, we unfortunately have to patch out ``warnings``.
+ old_warnings = base.warnings
+ base.warnings = FakeWarnings()
+
+ self.assertEqual(len(base.warnings._warnings), 0)
+
+ with self.settings(TEST_RUNNER='myapp.test.CustomRunnner'):
+ self.assertEqual(len(base.check_compatibility()), 0)
+
+ self.assertEqual(len(base.warnings._warnings), 1)
+ self.assertTrue("The 'StubCheckModule' module lacks a 'run_checks'" in base.warnings._warnings[0])
+
+ # Restore the ``warnings``.
+ base.warnings = old_warnings
+
+ def test_management_command(self):
+ # Again, we unfortunately have to patch out ``warnings``. Different
+ old_warnings = checksetup.warnings
+ checksetup.warnings = FakeWarnings()
+
+ self.assertEqual(len(checksetup.warnings._warnings), 0)
+
+ # Should not produce any warnings.
+ with self.settings(TEST_RUNNER='myapp.test.CustomRunnner'):
+ call_command('checksetup')
+
+ self.assertEqual(len(checksetup.warnings._warnings), 0)
+
+ with self.settings(TEST_RUNNER='django.test.runner.DiscoverRunner'):
+ call_command('checksetup')
+
+ self.assertEqual(len(checksetup.warnings._warnings), 1)
+ self.assertTrue("You have not explicitly set 'TEST_RUNNER'" in checksetup.warnings._warnings[0])
+
+ # Restore the ``warnings``.
+ base.warnings = old_warnings
diff --git a/tests/delete_regress/tests.py b/tests/delete_regress/tests.py
index e88c95e229..a4908b2121 100644
--- a/tests/delete_regress/tests.py
+++ b/tests/delete_regress/tests.py
@@ -16,6 +16,9 @@ from .models import (Book, Award, AwardNote, Person, Child, Toy, PlayedWith,
# Can't run this test under SQLite, because you can't
# get two connections to an in-memory database.
class DeleteLockingTest(TransactionTestCase):
+
+ available_apps = ['delete_regress']
+
def setUp(self):
# Create a second connection to the default database
new_connections = ConnectionHandler(settings.DATABASES)
@@ -107,6 +110,9 @@ class DeleteCascadeTests(TestCase):
class DeleteCascadeTransactionTests(TransactionTestCase):
+
+ available_apps = ['delete_regress']
+
def test_inheritance(self):
"""
Auto-created many-to-many through tables referencing a parent model are
diff --git a/tests/file_storage/tests.py b/tests/file_storage/tests.py
index 406a4d79b6..6c3c559660 100644
--- a/tests/file_storage/tests.py
+++ b/tests/file_storage/tests.py
@@ -7,6 +7,10 @@ import shutil
import sys
import tempfile
import time
+try:
+ from urllib.request import urlopen
+except ImportError: # Python 2
+ from urllib2 import urlopen
import zlib
from datetime import datetime, timedelta
from io import BytesIO
@@ -22,12 +26,11 @@ from django.core.files.base import File, ContentFile
from django.core.files.images import get_image_dimensions
from django.core.files.storage import FileSystemStorage, get_storage_class
from django.core.files.uploadedfile import UploadedFile
-from django.test import SimpleTestCase
+from django.test import LiveServerTestCase, SimpleTestCase
from django.utils import six
from django.utils import unittest
from django.utils._os import upath
from django.test.utils import override_settings
-from servers.tests import LiveServerBase
try:
from django.utils.image import Image
@@ -613,10 +616,15 @@ class NoNameFileTestCase(unittest.TestCase):
def test_noname_file_get_size(self):
self.assertEqual(File(BytesIO(b'A file with no name')).size, 19)
-class FileLikeObjectTestCase(LiveServerBase):
+
+class FileLikeObjectTestCase(LiveServerTestCase):
"""
Test file-like objects (#15644).
"""
+
+ available_apps = []
+ urls = 'file_storage.urls'
+
def setUp(self):
self.temp_dir = tempfile.mkdtemp()
self.storage = FileSystemStorage(location=self.temp_dir)
@@ -628,12 +636,10 @@ class FileLikeObjectTestCase(LiveServerBase):
"""
Test the File storage API with a file like object coming from urllib2.urlopen()
"""
-
- file_like_object = self.urlopen('/example_view/')
+ file_like_object = urlopen(self.live_server_url + '/')
f = File(file_like_object)
stored_filename = self.storage.save("remote_file.html", f)
- remote_file = self.urlopen('/example_view/')
-
+ remote_file = urlopen(self.live_server_url + '/')
with self.storage.open(stored_filename) as stored_file:
self.assertEqual(stored_file.read(), remote_file.read())
diff --git a/tests/file_storage/urls.py b/tests/file_storage/urls.py
new file mode 100644
index 0000000000..aefd8549e1
--- /dev/null
+++ b/tests/file_storage/urls.py
@@ -0,0 +1,7 @@
+from django.conf.urls import patterns, url
+from django.http import HttpResponse
+
+
+urlpatterns = patterns('',
+ url(r'^$', lambda req: HttpResponse('example view')),
+)
diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py
index 1b4d6eeeef..d0942afdb7 100644
--- a/tests/fixtures/tests.py
+++ b/tests/fixtures/tests.py
@@ -354,6 +354,13 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase):
class FixtureTransactionTests(DumpDataAssertMixin, TransactionTestCase):
+ available_apps = [
+ 'fixtures',
+ 'django.contrib.contenttypes',
+ 'django.contrib.auth',
+ 'django.contrib.sites',
+ ]
+
@skipUnlessDBFeature('supports_forward_references')
def test_format_discovery(self):
# Load fixture 1 again, using format discovery
diff --git a/tests/fixtures_model_package/tests.py b/tests/fixtures_model_package/tests.py
index e0a35e300d..dbcc721d8f 100644
--- a/tests/fixtures_model_package/tests.py
+++ b/tests/fixtures_model_package/tests.py
@@ -26,6 +26,9 @@ class SampleTestCase(TestCase):
class TestNoInitialDataLoading(TransactionTestCase):
+
+ available_apps = ['fixtures_model_package']
+
def test_syncdb(self):
transaction.set_autocommit(False)
try:
diff --git a/tests/fixtures_regress/tests.py b/tests/fixtures_regress/tests.py
index 52526ec338..0f6ac65976 100644
--- a/tests/fixtures_regress/tests.py
+++ b/tests/fixtures_regress/tests.py
@@ -685,6 +685,12 @@ class NaturalKeyFixtureTests(TestCase):
class TestTicket11101(TransactionTestCase):
+ available_apps = [
+ 'fixtures_regress',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ ]
+
def ticket_11101(self):
management.call_command(
'loaddata',
diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py
index 1a3fb44a66..633fde5026 100644
--- a/tests/forms_tests/tests/test_forms.py
+++ b/tests/forms_tests/tests/test_forms.py
@@ -1589,9 +1589,9 @@ class FormsTestCase(TestCase):
# Recall from above that passing the "auto_id" argument to a Form gives each
# field an "id" attribute.
t = Template('''<form action="">
-<p>{{ form.username.label_tag }}: {{ form.username }}</p>
-<p>{{ form.password1.label_tag }}: {{ form.password1 }}</p>
-<p>{{ form.password2.label_tag }}: {{ form.password2 }}</p>
+<p>{{ form.username.label_tag }} {{ form.username }}</p>
+<p>{{ form.password1.label_tag }} {{ form.password1 }}</p>
+<p>{{ form.password2.label_tag }} {{ form.password2 }}</p>
<input type="submit" />
</form>''')
self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id=False)})), """<form action="">
@@ -1601,18 +1601,18 @@ class FormsTestCase(TestCase):
<input type="submit" />
</form>""")
self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id='id_%s')})), """<form action="">
-<p><label for="id_username">Username</label>: <input id="id_username" type="text" name="username" maxlength="10" /></p>
-<p><label for="id_password1">Password1</label>: <input type="password" name="password1" id="id_password1" /></p>
-<p><label for="id_password2">Password2</label>: <input type="password" name="password2" id="id_password2" /></p>
+<p><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></p>
+<p><label for="id_password1">Password1:</label> <input type="password" name="password1" id="id_password1" /></p>
+<p><label for="id_password2">Password2:</label> <input type="password" name="password2" id="id_password2" /></p>
<input type="submit" />
</form>""")
# User form.[field].help_text to output a field's help text. If the given field
# does not have help text, nothing will be output.
t = Template('''<form action="">
-<p>{{ form.username.label_tag }}: {{ form.username }}<br />{{ form.username.help_text }}</p>
-<p>{{ form.password1.label_tag }}: {{ form.password1 }}</p>
-<p>{{ form.password2.label_tag }}: {{ form.password2 }}</p>
+<p>{{ form.username.label_tag }} {{ form.username }}<br />{{ form.username.help_text }}</p>
+<p>{{ form.password1.label_tag }} {{ form.password1 }}</p>
+<p>{{ form.password2.label_tag }} {{ form.password2 }}</p>
<input type="submit" />
</form>''')
self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id=False)})), """<form action="">
@@ -1819,17 +1819,17 @@ class FormsTestCase(TestCase):
testcases = [ # (args, kwargs, expected)
# without anything: just print the <label>
- ((), {}, '<label for="id_field">Field</label>'),
+ ((), {}, '<label for="id_field">Field:</label>'),
# passing just one argument: overrides the field's label
- (('custom',), {}, '<label for="id_field">custom</label>'),
+ (('custom',), {}, '<label for="id_field">custom:</label>'),
# the overriden label is escaped
- (('custom&',), {}, '<label for="id_field">custom&amp;</label>'),
- ((mark_safe('custom&'),), {}, '<label for="id_field">custom&</label>'),
+ (('custom&',), {}, '<label for="id_field">custom&amp;:</label>'),
+ ((mark_safe('custom&'),), {}, '<label for="id_field">custom&:</label>'),
# Passing attrs to add extra attributes on the <label>
- ((), {'attrs': {'class': 'pretty'}}, '<label for="id_field" class="pretty">Field</label>')
+ ((), {'attrs': {'class': 'pretty'}}, '<label for="id_field" class="pretty">Field:</label>')
]
for args, kwargs, expected in testcases:
@@ -1844,8 +1844,8 @@ class FormsTestCase(TestCase):
field = CharField()
boundfield = SomeForm(auto_id='')['field']
- self.assertHTMLEqual(boundfield.label_tag(), 'Field')
- self.assertHTMLEqual(boundfield.label_tag('Custom&'), 'Custom&amp;')
+ self.assertHTMLEqual(boundfield.label_tag(), 'Field:')
+ self.assertHTMLEqual(boundfield.label_tag('Custom&'), 'Custom&amp;:')
def test_boundfield_label_tag_custom_widget_id_for_label(self):
class CustomIdForLabelTextInput(TextInput):
@@ -1861,5 +1861,12 @@ class FormsTestCase(TestCase):
empty = CharField(widget=EmptyIdForLabelTextInput)
form = SomeForm()
- self.assertHTMLEqual(form['custom'].label_tag(), '<label for="custom_id_custom">Custom</label>')
- self.assertHTMLEqual(form['empty'].label_tag(), '<label>Empty</label>')
+ self.assertHTMLEqual(form['custom'].label_tag(), '<label for="custom_id_custom">Custom:</label>')
+ self.assertHTMLEqual(form['empty'].label_tag(), '<label>Empty:</label>')
+
+ def test_boundfield_empty_label(self):
+ class SomeForm(Form):
+ field = CharField(label='')
+ boundfield = SomeForm()['field']
+
+ self.assertHTMLEqual(boundfield.label_tag(), '<label for="id_field"></label>')
diff --git a/tests/forms_tests/tests/test_formsets.py b/tests/forms_tests/tests/test_formsets.py
index 1e9e7db30c..b26017bc78 100644
--- a/tests/forms_tests/tests/test_formsets.py
+++ b/tests/forms_tests/tests/test_formsets.py
@@ -55,81 +55,82 @@ SplitDateTimeFormSet = formset_factory(SplitDateTimeForm)
class FormsFormsetTestCase(TestCase):
+
+ def make_choiceformset(self, formset_data=None, formset_class=ChoiceFormSet,
+ total_forms=None, initial_forms=0, max_num_forms=0, **kwargs):
+ """
+ Make a ChoiceFormset from the given formset_data.
+ The data should be given as a list of (choice, votes) tuples.
+ """
+ kwargs.setdefault('prefix', 'choices')
+ kwargs.setdefault('auto_id', False)
+
+ if formset_data is None:
+ return formset_class(**kwargs)
+
+ if total_forms is None:
+ total_forms = len(formset_data)
+
+ def prefixed(*args):
+ args = (kwargs['prefix'],) + args
+ return '-'.join(args)
+
+ data = {
+ prefixed('TOTAL_FORMS'): str(total_forms),
+ prefixed('INITIAL_FORMS'): str(initial_forms),
+ prefixed('MAX_NUM_FORMS'): str(max_num_forms),
+ }
+ for i, (choice, votes) in enumerate(formset_data):
+ data[prefixed(str(i), 'choice')] = choice
+ data[prefixed(str(i), 'votes')] = votes
+
+ return formset_class(data, **kwargs)
+
def test_basic_formset(self):
# A FormSet constructor takes the same arguments as Form. Let's create a FormSet
# for adding data. By default, it displays 1 blank form. It can display more,
# but we'll look at how to do so later.
- formset = ChoiceFormSet(auto_id=False, prefix='choices')
+ formset = self.make_choiceformset()
+
self.assertHTMLEqual(str(formset), """<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" value="1000" />
<tr><th>Choice:</th><td><input type="text" name="choices-0-choice" /></td></tr>
<tr><th>Votes:</th><td><input type="number" name="choices-0-votes" /></td></tr>""")
- # On thing to note is that there needs to be a special value in the data. This
- # value tells the FormSet how many forms were displayed so it can tell how
- # many forms it needs to clean and validate. You could use javascript to create
- # new forms on the client side, but they won't get validated unless you increment
- # the TOTAL_FORMS field appropriately.
-
- data = {
- 'choices-TOTAL_FORMS': '1', # the number of forms rendered
- 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
- 'choices-MAX_NUM_FORMS': '0', # max number of forms
- 'choices-0-choice': 'Calexico',
- 'choices-0-votes': '100',
- }
# We treat FormSet pretty much like we would treat a normal Form. FormSet has an
# is_valid method, and a cleaned_data or errors attribute depending on whether all
# the forms passed validation. However, unlike a Form instance, cleaned_data and
# errors will be a list of dicts rather than just a single dict.
- formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ formset = self.make_choiceformset([('Calexico', '100')])
self.assertTrue(formset.is_valid())
self.assertEqual([form.cleaned_data for form in formset.forms], [{'votes': 100, 'choice': 'Calexico'}])
# If a FormSet was not passed any data, its is_valid and has_changed
# methods should return False.
- formset = ChoiceFormSet()
+ formset = self.make_choiceformset()
self.assertFalse(formset.is_valid())
self.assertFalse(formset.has_changed())
def test_formset_validation(self):
# FormSet instances can also have an error attribute if validation failed for
# any of the forms.
-
- data = {
- 'choices-TOTAL_FORMS': '1', # the number of forms rendered
- 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
- 'choices-MAX_NUM_FORMS': '0', # max number of forms
- 'choices-0-choice': 'Calexico',
- 'choices-0-votes': '',
- }
-
- formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ formset = self.make_choiceformset([('Calexico', '')])
self.assertFalse(formset.is_valid())
self.assertEqual(formset.errors, [{'votes': ['This field is required.']}])
def test_formset_has_changed(self):
# FormSet instances has_changed method will be True if any data is
# passed to his forms, even if the formset didn't validate
- data = {
- 'choices-TOTAL_FORMS': '1', # the number of forms rendered
- 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
- 'choices-MAX_NUM_FORMS': '0', # max number of forms
- 'choices-0-choice': '',
- 'choices-0-votes': '',
- }
- blank_formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ blank_formset = self.make_choiceformset([('', '')])
self.assertFalse(blank_formset.has_changed())
# invalid formset test
- data['choices-0-choice'] = 'Calexico'
- invalid_formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ invalid_formset = self.make_choiceformset([('Calexico', '')])
self.assertFalse(invalid_formset.is_valid())
self.assertTrue(invalid_formset.has_changed())
# valid formset test
- data['choices-0-votes'] = '100'
- valid_formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ valid_formset = self.make_choiceformset([('Calexico', '100')])
self.assertTrue(valid_formset.is_valid())
self.assertTrue(valid_formset.has_changed())
@@ -139,7 +140,7 @@ class FormsFormsetTestCase(TestCase):
# an extra blank form is included.
initial = [{'choice': 'Calexico', 'votes': 100}]
- formset = ChoiceFormSet(initial=initial, auto_id=False, prefix='choices')
+ formset = self.make_choiceformset(initial=initial)
form_output = []
for form in formset.forms:
@@ -151,18 +152,7 @@ class FormsFormsetTestCase(TestCase):
<li>Votes: <input type="number" name="choices-1-votes" /></li>""")
# Let's simulate what would happen if we submitted this form.
-
- data = {
- 'choices-TOTAL_FORMS': '2', # the number of forms rendered
- 'choices-INITIAL_FORMS': '1', # the number of forms with initial data
- 'choices-MAX_NUM_FORMS': '0', # max number of forms
- 'choices-0-choice': 'Calexico',
- 'choices-0-votes': '100',
- 'choices-1-choice': '',
- 'choices-1-votes': '',
- }
-
- formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ formset = self.make_choiceformset([('Calexico', '100'), ('', '')], initial_forms=1)
self.assertTrue(formset.is_valid())
self.assertEqual([form.cleaned_data for form in formset.forms], [{'votes': 100, 'choice': 'Calexico'}, {}])
@@ -172,18 +162,7 @@ class FormsFormsetTestCase(TestCase):
# one of the fields of a blank form though, it will be validated. We may want to
# required that at least x number of forms are completed, but we'll show how to
# handle that later.
-
- data = {
- 'choices-TOTAL_FORMS': '2', # the number of forms rendered
- 'choices-INITIAL_FORMS': '1', # the number of forms with initial data
- 'choices-MAX_NUM_FORMS': '0', # max number of forms
- 'choices-0-choice': 'Calexico',
- 'choices-0-votes': '100',
- 'choices-1-choice': 'The Decemberists',
- 'choices-1-votes': '', # missing value
- }
-
- formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ formset = self.make_choiceformset([('Calexico', '100'), ('The Decemberists', '')], initial_forms=1)
self.assertFalse(formset.is_valid())
self.assertEqual(formset.errors, [{}, {'votes': ['This field is required.']}])
@@ -191,18 +170,7 @@ class FormsFormsetTestCase(TestCase):
# If we delete data that was pre-filled, we should get an error. Simply removing
# data from form fields isn't the proper way to delete it. We'll see how to
# handle that case later.
-
- data = {
- 'choices-TOTAL_FORMS': '2', # the number of forms rendered
- 'choices-INITIAL_FORMS': '1', # the number of forms with initial data
- 'choices-MAX_NUM_FORMS': '0', # max number of forms
- 'choices-0-choice': '', # deleted value
- 'choices-0-votes': '', # deleted value
- 'choices-1-choice': '',
- 'choices-1-votes': '',
- }
-
- formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ formset = self.make_choiceformset([('', ''), ('', '')], initial_forms=1)
self.assertFalse(formset.is_valid())
self.assertEqual(formset.errors, [{'votes': ['This field is required.'], 'choice': ['This field is required.']}, {}])
@@ -1027,6 +995,40 @@ class FormsFormsetTestCase(TestCase):
self.assertTrue(formset.is_valid())
+ def test_formset_total_error_count(self):
+ """A valid formset should have 0 total errors."""
+ data = [ # formset_data, expected error count
+ ([('Calexico', '100')], 0),
+ ([('Calexico', '')], 1),
+ ([('', 'invalid')], 2),
+ ([('Calexico', '100'), ('Calexico', '')], 1),
+ ([('Calexico', ''), ('Calexico', '')], 2),
+ ]
+
+ for formset_data, expected_error_count in data:
+ formset = self.make_choiceformset(formset_data)
+ self.assertEqual(formset.total_error_count(), expected_error_count)
+
+ def test_formset_total_error_count_with_non_form_errors(self):
+ data = {
+ 'choices-TOTAL_FORMS': '2', # the number of forms rendered
+ 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
+ 'choices-MAX_NUM_FORMS': '2', # max number of forms - should be ignored
+ 'choices-0-choice': 'Zero',
+ 'choices-0-votes': '0',
+ 'choices-1-choice': 'One',
+ 'choices-1-votes': '1',
+ }
+
+ ChoiceFormSet = formset_factory(Choice, extra=1, max_num=1, validate_max=True)
+ formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ self.assertEqual(formset.total_error_count(), 1)
+
+ data['choices-1-votes'] = ''
+ formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+ self.assertEqual(formset.total_error_count(), 2)
+
+
data = {
'choices-TOTAL_FORMS': '1', # the number of forms rendered
'choices-INITIAL_FORMS': '0', # the number of forms with initial data
@@ -1087,7 +1089,7 @@ class TestIsBoundBehavior(TestCase):
self.assertEqual([{}], formset.cleaned_data)
- def test_form_errors_are_cought_by_formset(self):
+ def test_form_errors_are_caught_by_formset(self):
data = {
'form-TOTAL_FORMS': '2',
'form-INITIAL_FORMS': '0',
diff --git a/tests/forms_tests/tests/test_regressions.py b/tests/forms_tests/tests/test_regressions.py
index ea138d32d5..d230d68f75 100644
--- a/tests/forms_tests/tests/test_regressions.py
+++ b/tests/forms_tests/tests/test_regressions.py
@@ -45,8 +45,8 @@ class FormsRegressionsTestCase(TransRealMixin, TestCase):
field_2 = CharField(max_length=10, label=ugettext_lazy('field_2'), widget=TextInput(attrs={'id': 'field_2_id'}))
f = SomeForm()
- self.assertHTMLEqual(f['field_1'].label_tag(), '<label for="id_field_1">field_1</label>')
- self.assertHTMLEqual(f['field_2'].label_tag(), '<label for="field_2_id">field_2</label>')
+ self.assertHTMLEqual(f['field_1'].label_tag(), '<label for="id_field_1">field_1:</label>')
+ self.assertHTMLEqual(f['field_2'].label_tag(), '<label for="field_2_id">field_2:</label>')
# Unicode decoding problems...
GENDERS = (('\xc5', 'En tied\xe4'), ('\xf8', 'Mies'), ('\xdf', 'Nainen'))
diff --git a/tests/forms_tests/tests/test_widgets.py b/tests/forms_tests/tests/test_widgets.py
index 4664553aa7..4c566dc8e4 100644
--- a/tests/forms_tests/tests/test_widgets.py
+++ b/tests/forms_tests/tests/test_widgets.py
@@ -1028,6 +1028,8 @@ class WidgetTests(TestCase):
class LiveWidgetTests(AdminSeleniumWebDriverTestCase):
+
+ available_apps = ['forms_tests'] + AdminSeleniumWebDriverTestCase.available_apps
urls = 'forms_tests.urls'
def test_textarea_trailing_newlines(self):
diff --git a/tests/forms_tests/tests/tests.py b/tests/forms_tests/tests/tests.py
index 2616ddaf7d..99a67c320c 100644
--- a/tests/forms_tests/tests/tests.py
+++ b/tests/forms_tests/tests/tests.py
@@ -208,7 +208,8 @@ class RelatedModelFormTests(TestCase):
ref = models.ForeignKey("B")
class Meta:
- model=A
+ model = A
+ fields = '__all__'
self.assertRaises(ValueError, ModelFormMetaclass, str('Form'), (ModelForm,), {'Meta': Meta})
@@ -226,7 +227,8 @@ class RelatedModelFormTests(TestCase):
pass
class Meta:
- model=A
+ model = A
+ fields = '__all__'
self.assertTrue(issubclass(ModelFormMetaclass(str('Form'), (ModelForm,), {'Meta': Meta}), ModelForm))
diff --git a/tests/generic_views/test_base.py b/tests/generic_views/test_base.py
index ffd9b1b480..f95732f8b5 100644
--- a/tests/generic_views/test_base.py
+++ b/tests/generic_views/test_base.py
@@ -317,7 +317,9 @@ class TemplateViewTest(TestCase):
self.assertEqual(response['Content-Type'], 'text/plain')
-class RedirectViewTest(unittest.TestCase):
+class RedirectViewTest(TestCase):
+ urls = 'generic_views.urls'
+
rf = RequestFactory()
def test_no_url(self):
@@ -360,6 +362,22 @@ class RedirectViewTest(unittest.TestCase):
self.assertEqual(response.status_code, 301)
self.assertEqual(response.url, '/bar/42/')
+ def test_named_url_pattern(self):
+ "Named pattern parameter should reverse to the matching pattern"
+ response = RedirectView.as_view(pattern_name='artist_detail')(self.rf.get('/foo/'), pk=1)
+ self.assertEqual(response.status_code, 301)
+ self.assertEqual(response['Location'], '/detail/artist/1/')
+
+ def test_named_url_pattern_using_args(self):
+ response = RedirectView.as_view(pattern_name='artist_detail')(self.rf.get('/foo/'), 1)
+ self.assertEqual(response.status_code, 301)
+ self.assertEqual(response['Location'], '/detail/artist/1/')
+
+ def test_wrong_named_url_pattern(self):
+ "A wrong pattern name returns 410 GONE"
+ response = RedirectView.as_view(pattern_name='wrong.pattern_name')(self.rf.get('/foo/'))
+ self.assertEqual(response.status_code, 410)
+
def test_redirect_POST(self):
"Default is a permanent redirect"
response = RedirectView.as_view(url='/bar/')(self.rf.post('/foo/'))
diff --git a/tests/get_or_create/tests.py b/tests/get_or_create/tests.py
index 36c248b169..847a6dec01 100644
--- a/tests/get_or_create/tests.py
+++ b/tests/get_or_create/tests.py
@@ -94,6 +94,8 @@ class GetOrCreateTests(TestCase):
class GetOrCreateTransactionTests(TransactionTestCase):
+ available_apps = ['get_or_create']
+
def test_get_or_create_integrityerror(self):
# Regression test for #15117. Requires a TransactionTestCase on
# databases that delay integrity checks until the end of transactions,
diff --git a/tests/handlers/tests.py b/tests/handlers/tests.py
index 397b63647a..2f9f304b81 100644
--- a/tests/handlers/tests.py
+++ b/tests/handlers/tests.py
@@ -37,6 +37,8 @@ class HandlerTests(TestCase):
class TransactionsPerRequestTests(TransactionTestCase):
+
+ available_apps = []
urls = 'handlers.urls'
def test_no_transaction(self):
diff --git a/tests/lookup/models.py b/tests/lookup/models.py
index f60c4962fd..f388ddf403 100644
--- a/tests/lookup/models.py
+++ b/tests/lookup/models.py
@@ -10,16 +10,29 @@ from django.db import models
from django.utils import six
from django.utils.encoding import python_2_unicode_compatible
-from shared_models.models import Author, Book
+class Author(models.Model):
+ name = models.CharField(max_length=100)
+ class Meta:
+ ordering = ('name', )
+
+@python_2_unicode_compatible
+class Article(models.Model):
+ headline = models.CharField(max_length=100)
+ pub_date = models.DateTimeField()
+ author = models.ForeignKey(Author, blank=True, null=True)
+ class Meta:
+ ordering = ('-pub_date', 'headline')
+
+ def __str__(self):
+ return self.headline
class Tag(models.Model):
- articles = models.ManyToManyField(Book)
+ articles = models.ManyToManyField(Article)
name = models.CharField(max_length=100)
class Meta:
ordering = ('name', )
-
@python_2_unicode_compatible
class Season(models.Model):
year = models.PositiveSmallIntegerField()
@@ -28,7 +41,6 @@ class Season(models.Model):
def __str__(self):
return six.text_type(self.year)
-
@python_2_unicode_compatible
class Game(models.Model):
season = models.ForeignKey(Season, related_name='games')
@@ -38,7 +50,6 @@ class Game(models.Model):
def __str__(self):
return "%s at %s" % (self.away, self.home)
-
@python_2_unicode_compatible
class Player(models.Model):
name = models.CharField(max_length=100)
diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py
index 6a6729ef22..de7105f92d 100644
--- a/tests/lookup/tests.py
+++ b/tests/lookup/tests.py
@@ -5,11 +5,8 @@ from operator import attrgetter
from django.core.exceptions import FieldError
from django.test import TestCase, skipUnlessDBFeature
-from django.utils import six
-from shared_models.models import Author, Book
-
-from .models import Tag, Game, Season, Player
+from .models import Author, Article, Tag, Game, Season, Player
class LookupTests(TestCase):
@@ -20,165 +17,165 @@ class LookupTests(TestCase):
self.au1.save()
self.au2 = Author(name='Author 2')
self.au2.save()
- # Create a couple of Books.
- self.b1 = Book(title='Book 1', pubdate=datetime(2005, 7, 26), author=self.au1)
- self.b1.save()
- self.b2 = Book(title='Book 2', pubdate=datetime(2005, 7, 27), author=self.au1)
- self.b2.save()
- self.b3 = Book(title='Book 3', pubdate=datetime(2005, 7, 27), author=self.au1)
- self.b3.save()
- self.b4 = Book(title='Book 4', pubdate=datetime(2005, 7, 28), author=self.au1)
- self.b4.save()
- self.b5 = Book(title='Book 5', pubdate=datetime(2005, 8, 1, 9, 0), author=self.au2)
- self.b5.save()
- self.b6 = Book(title='Book 6', pubdate=datetime(2005, 8, 1, 8, 0), author=self.au2)
- self.b6.save()
- self.b7 = Book(title='Book 7', pubdate=datetime(2005, 7, 27), author=self.au2)
- self.b7.save()
+ # Create a couple of Articles.
+ self.a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26), author=self.au1)
+ self.a1.save()
+ self.a2 = Article(headline='Article 2', pub_date=datetime(2005, 7, 27), author=self.au1)
+ self.a2.save()
+ self.a3 = Article(headline='Article 3', pub_date=datetime(2005, 7, 27), author=self.au1)
+ self.a3.save()
+ self.a4 = Article(headline='Article 4', pub_date=datetime(2005, 7, 28), author=self.au1)
+ self.a4.save()
+ self.a5 = Article(headline='Article 5', pub_date=datetime(2005, 8, 1, 9, 0), author=self.au2)
+ self.a5.save()
+ self.a6 = Article(headline='Article 6', pub_date=datetime(2005, 8, 1, 8, 0), author=self.au2)
+ self.a6.save()
+ self.a7 = Article(headline='Article 7', pub_date=datetime(2005, 7, 27), author=self.au2)
+ self.a7.save()
# Create a few Tags.
self.t1 = Tag(name='Tag 1')
self.t1.save()
- self.t1.articles.add(self.b1, self.b2, self.b3)
+ self.t1.articles.add(self.a1, self.a2, self.a3)
self.t2 = Tag(name='Tag 2')
self.t2.save()
- self.t2.articles.add(self.b3, self.b4, self.b5)
+ self.t2.articles.add(self.a3, self.a4, self.a5)
self.t3 = Tag(name='Tag 3')
self.t3.save()
- self.t3.articles.add(self.b5, self.b6, self.b7)
+ self.t3.articles.add(self.a5, self.a6, self.a7)
def test_exists(self):
# We can use .exists() to check that there are some
- self.assertTrue(Book.objects.exists())
- for a in Book.objects.all():
+ self.assertTrue(Article.objects.exists())
+ for a in Article.objects.all():
a.delete()
# There should be none now!
- self.assertFalse(Book.objects.exists())
+ self.assertFalse(Article.objects.exists())
def test_lookup_int_as_str(self):
# Integer value can be queried using string
- self.assertQuerysetEqual(Book.objects.filter(id__iexact=str(self.b1.id)),
- ['<Book: Book 1>'])
+ self.assertQuerysetEqual(Article.objects.filter(id__iexact=str(self.a1.id)),
+ ['<Article: Article 1>'])
@skipUnlessDBFeature('supports_date_lookup_using_string')
def test_lookup_date_as_str(self):
# A date lookup can be performed using a string search
- self.assertQuerysetEqual(Book.objects.filter(pubdate__startswith='2005'),
+ self.assertQuerysetEqual(Article.objects.filter(pub_date__startswith='2005'),
[
- '<Book: Book 5>',
- '<Book: Book 6>',
- '<Book: Book 4>',
- '<Book: Book 2>',
- '<Book: Book 3>',
- '<Book: Book 7>',
- '<Book: Book 1>',
+ '<Article: Article 5>',
+ '<Article: Article 6>',
+ '<Article: Article 4>',
+ '<Article: Article 2>',
+ '<Article: Article 3>',
+ '<Article: Article 7>',
+ '<Article: Article 1>',
])
def test_iterator(self):
# Each QuerySet gets iterator(), which is a generator that "lazily"
# returns results using database-level iteration.
- self.assertQuerysetEqual(Book.objects.iterator(),
+ self.assertQuerysetEqual(Article.objects.iterator(),
[
- 'Book 5',
- 'Book 6',
- 'Book 4',
- 'Book 2',
- 'Book 3',
- 'Book 7',
- 'Book 1',
+ 'Article 5',
+ 'Article 6',
+ 'Article 4',
+ 'Article 2',
+ 'Article 3',
+ 'Article 7',
+ 'Article 1',
],
- transform=attrgetter('title'))
+ transform=attrgetter('headline'))
# iterator() can be used on any QuerySet.
self.assertQuerysetEqual(
- Book.objects.filter(title__endswith='4').iterator(),
- ['Book 4'],
- transform=attrgetter('title'))
+ Article.objects.filter(headline__endswith='4').iterator(),
+ ['Article 4'],
+ transform=attrgetter('headline'))
def test_count(self):
# count() returns the number of objects matching search criteria.
- self.assertEqual(Book.objects.count(), 7)
- self.assertEqual(Book.objects.filter(pubdate__exact=datetime(2005, 7, 27)).count(), 3)
- self.assertEqual(Book.objects.filter(title__startswith='Blah blah').count(), 0)
+ self.assertEqual(Article.objects.count(), 7)
+ self.assertEqual(Article.objects.filter(pub_date__exact=datetime(2005, 7, 27)).count(), 3)
+ self.assertEqual(Article.objects.filter(headline__startswith='Blah blah').count(), 0)
# count() should respect sliced query sets.
- articles = Book.objects.all()
+ articles = Article.objects.all()
self.assertEqual(articles.count(), 7)
self.assertEqual(articles[:4].count(), 4)
self.assertEqual(articles[1:100].count(), 6)
self.assertEqual(articles[10:100].count(), 0)
# Date and date/time lookups can also be done with strings.
- self.assertEqual(Book.objects.filter(pubdate__exact='2005-07-27').count(), 3)
+ self.assertEqual(Article.objects.filter(pub_date__exact='2005-07-27 00:00:00').count(), 3)
def test_in_bulk(self):
# in_bulk() takes a list of IDs and returns a dictionary mapping IDs to objects.
- arts = Book.objects.in_bulk([self.b1.id, self.b2.id])
- self.assertEqual(arts[self.b1.id], self.b1)
- self.assertEqual(arts[self.b2.id], self.b2)
- self.assertEqual(Book.objects.in_bulk([self.b3.id]), {self.b3.id: self.b3})
- self.assertEqual(Book.objects.in_bulk(set([self.b3.id])), {self.b3.id: self.b3})
- self.assertEqual(Book.objects.in_bulk(frozenset([self.b3.id])), {self.b3.id: self.b3})
- self.assertEqual(Book.objects.in_bulk((self.b3.id,)), {self.b3.id: self.b3})
- self.assertEqual(Book.objects.in_bulk([1000]), {})
- self.assertEqual(Book.objects.in_bulk([]), {})
- self.assertEqual(Book.objects.in_bulk(iter([self.b1.id])), {self.b1.id: self.b1})
- self.assertEqual(Book.objects.in_bulk(iter([])), {})
- self.assertRaises(TypeError, Book.objects.in_bulk)
- self.assertRaises(TypeError, Book.objects.in_bulk, name__startswith='Blah')
+ arts = Article.objects.in_bulk([self.a1.id, self.a2.id])
+ self.assertEqual(arts[self.a1.id], self.a1)
+ self.assertEqual(arts[self.a2.id], self.a2)
+ self.assertEqual(Article.objects.in_bulk([self.a3.id]), {self.a3.id: self.a3})
+ self.assertEqual(Article.objects.in_bulk(set([self.a3.id])), {self.a3.id: self.a3})
+ self.assertEqual(Article.objects.in_bulk(frozenset([self.a3.id])), {self.a3.id: self.a3})
+ self.assertEqual(Article.objects.in_bulk((self.a3.id,)), {self.a3.id: self.a3})
+ self.assertEqual(Article.objects.in_bulk([1000]), {})
+ self.assertEqual(Article.objects.in_bulk([]), {})
+ self.assertEqual(Article.objects.in_bulk(iter([self.a1.id])), {self.a1.id: self.a1})
+ self.assertEqual(Article.objects.in_bulk(iter([])), {})
+ self.assertRaises(TypeError, Article.objects.in_bulk)
+ self.assertRaises(TypeError, Article.objects.in_bulk, headline__startswith='Blah')
def test_values(self):
# values() returns a list of dictionaries instead of object instances --
# and you can specify which fields you want to retrieve.
identity = lambda x:x
- self.assertQuerysetEqual(Book.objects.values('title'),
+ self.assertQuerysetEqual(Article.objects.values('headline'),
[
- {'title': 'Book 5'},
- {'title': 'Book 6'},
- {'title': 'Book 4'},
- {'title': 'Book 2'},
- {'title': 'Book 3'},
- {'title': 'Book 7'},
- {'title': 'Book 1'},
+ {'headline': 'Article 5'},
+ {'headline': 'Article 6'},
+ {'headline': 'Article 4'},
+ {'headline': 'Article 2'},
+ {'headline': 'Article 3'},
+ {'headline': 'Article 7'},
+ {'headline': 'Article 1'},
],
transform=identity)
self.assertQuerysetEqual(
- Book.objects.filter(pubdate__exact=datetime(2005, 7, 27)).values('id'),
- [{'id': self.b2.id}, {'id': self.b3.id}, {'id': self.b7.id}],
+ Article.objects.filter(pub_date__exact=datetime(2005, 7, 27)).values('id'),
+ [{'id': self.a2.id}, {'id': self.a3.id}, {'id': self.a7.id}],
transform=identity)
- self.assertQuerysetEqual(Book.objects.values('id', 'title'),
+ self.assertQuerysetEqual(Article.objects.values('id', 'headline'),
[
- {'id': self.b5.id, 'title': 'Book 5'},
- {'id': self.b6.id, 'title': 'Book 6'},
- {'id': self.b4.id, 'title': 'Book 4'},
- {'id': self.b2.id, 'title': 'Book 2'},
- {'id': self.b3.id, 'title': 'Book 3'},
- {'id': self.b7.id, 'title': 'Book 7'},
- {'id': self.b1.id, 'title': 'Book 1'},
+ {'id': self.a5.id, 'headline': 'Article 5'},
+ {'id': self.a6.id, 'headline': 'Article 6'},
+ {'id': self.a4.id, 'headline': 'Article 4'},
+ {'id': self.a2.id, 'headline': 'Article 2'},
+ {'id': self.a3.id, 'headline': 'Article 3'},
+ {'id': self.a7.id, 'headline': 'Article 7'},
+ {'id': self.a1.id, 'headline': 'Article 1'},
],
transform=identity)
# You can use values() with iterator() for memory savings,
# because iterator() uses database-level iteration.
- self.assertQuerysetEqual(Book.objects.values('id', 'title').iterator(),
+ self.assertQuerysetEqual(Article.objects.values('id', 'headline').iterator(),
[
- {'title': 'Book 5', 'id': self.b5.id},
- {'title': 'Book 6', 'id': self.b6.id},
- {'title': 'Book 4', 'id': self.b4.id},
- {'title': 'Book 2', 'id': self.b2.id},
- {'title': 'Book 3', 'id': self.b3.id},
- {'title': 'Book 7', 'id': self.b7.id},
- {'title': 'Book 1', 'id': self.b1.id},
+ {'headline': 'Article 5', 'id': self.a5.id},
+ {'headline': 'Article 6', 'id': self.a6.id},
+ {'headline': 'Article 4', 'id': self.a4.id},
+ {'headline': 'Article 2', 'id': self.a2.id},
+ {'headline': 'Article 3', 'id': self.a3.id},
+ {'headline': 'Article 7', 'id': self.a7.id},
+ {'headline': 'Article 1', 'id': self.a1.id},
],
transform=identity)
# The values() method works with "extra" fields specified in extra(select).
self.assertQuerysetEqual(
- Book.objects.extra(select={'id_plus_one': 'id + 1'}).values('id', 'id_plus_one'),
+ Article.objects.extra(select={'id_plus_one': 'id + 1'}).values('id', 'id_plus_one'),
[
- {'id': self.b5.id, 'id_plus_one': self.b5.id + 1},
- {'id': self.b6.id, 'id_plus_one': self.b6.id + 1},
- {'id': self.b4.id, 'id_plus_one': self.b4.id + 1},
- {'id': self.b2.id, 'id_plus_one': self.b2.id + 1},
- {'id': self.b3.id, 'id_plus_one': self.b3.id + 1},
- {'id': self.b7.id, 'id_plus_one': self.b7.id + 1},
- {'id': self.b1.id, 'id_plus_one': self.b1.id + 1},
+ {'id': self.a5.id, 'id_plus_one': self.a5.id + 1},
+ {'id': self.a6.id, 'id_plus_one': self.a6.id + 1},
+ {'id': self.a4.id, 'id_plus_one': self.a4.id + 1},
+ {'id': self.a2.id, 'id_plus_one': self.a2.id + 1},
+ {'id': self.a3.id, 'id_plus_one': self.a3.id + 1},
+ {'id': self.a7.id, 'id_plus_one': self.a7.id + 1},
+ {'id': self.a1.id, 'id_plus_one': self.a1.id + 1},
],
transform=identity)
data = {
@@ -192,67 +189,66 @@ class LookupTests(TestCase):
'id_plus_eight': 'id+8',
}
self.assertQuerysetEqual(
- Book.objects.filter(id=self.b1.id).extra(select=data).values(*data.keys()),
+ Article.objects.filter(id=self.a1.id).extra(select=data).values(*data.keys()),
[{
- 'id_plus_one': self.b1.id + 1,
- 'id_plus_two': self.b1.id + 2,
- 'id_plus_three': self.b1.id + 3,
- 'id_plus_four': self.b1.id + 4,
- 'id_plus_five': self.b1.id + 5,
- 'id_plus_six': self.b1.id + 6,
- 'id_plus_seven': self.b1.id + 7,
- 'id_plus_eight': self.b1.id + 8,
+ 'id_plus_one': self.a1.id + 1,
+ 'id_plus_two': self.a1.id + 2,
+ 'id_plus_three': self.a1.id + 3,
+ 'id_plus_four': self.a1.id + 4,
+ 'id_plus_five': self.a1.id + 5,
+ 'id_plus_six': self.a1.id + 6,
+ 'id_plus_seven': self.a1.id + 7,
+ 'id_plus_eight': self.a1.id + 8,
}], transform=identity)
# You can specify fields from forward and reverse relations, just like filter().
self.assertQuerysetEqual(
- Book.objects.values('title', 'author__name'),
+ Article.objects.values('headline', 'author__name'),
[
- {'title': self.b5.title, 'author__name': self.au2.name},
- {'title': self.b6.title, 'author__name': self.au2.name},
- {'title': self.b4.title, 'author__name': self.au1.name},
- {'title': self.b2.title, 'author__name': self.au1.name},
- {'title': self.b3.title, 'author__name': self.au1.name},
- {'title': self.b7.title, 'author__name': self.au2.name},
- {'title': self.b1.title, 'author__name': self.au1.name},
+ {'headline': self.a5.headline, 'author__name': self.au2.name},
+ {'headline': self.a6.headline, 'author__name': self.au2.name},
+ {'headline': self.a4.headline, 'author__name': self.au1.name},
+ {'headline': self.a2.headline, 'author__name': self.au1.name},
+ {'headline': self.a3.headline, 'author__name': self.au1.name},
+ {'headline': self.a7.headline, 'author__name': self.au2.name},
+ {'headline': self.a1.headline, 'author__name': self.au1.name},
], transform=identity)
self.assertQuerysetEqual(
- Author.objects.values('name', 'book__title').order_by('name', 'book__title'),
+ Author.objects.values('name', 'article__headline').order_by('name', 'article__headline'),
[
- {'name': self.au1.name, 'book__title': self.b1.title},
- {'name': self.au1.name, 'book__title': self.b2.title},
- {'name': self.au1.name, 'book__title': self.b3.title},
- {'name': self.au1.name, 'book__title': self.b4.title},
- {'name': self.au2.name, 'book__title': self.b5.title},
- {'name': self.au2.name, 'book__title': self.b6.title},
- {'name': self.au2.name, 'book__title': self.b7.title},
+ {'name': self.au1.name, 'article__headline': self.a1.headline},
+ {'name': self.au1.name, 'article__headline': self.a2.headline},
+ {'name': self.au1.name, 'article__headline': self.a3.headline},
+ {'name': self.au1.name, 'article__headline': self.a4.headline},
+ {'name': self.au2.name, 'article__headline': self.a5.headline},
+ {'name': self.au2.name, 'article__headline': self.a6.headline},
+ {'name': self.au2.name, 'article__headline': self.a7.headline},
], transform=identity)
self.assertQuerysetEqual(
- Author.objects.values('name', 'book__title', 'book__tag__name').order_by('name', 'book__title', 'book__tag__name'),
+ Author.objects.values('name', 'article__headline', 'article__tag__name').order_by('name', 'article__headline', 'article__tag__name'),
[
- {'name': self.au1.name, 'book__title': self.b1.title, 'book__tag__name': self.t1.name},
- {'name': self.au1.name, 'book__title': self.b2.title, 'book__tag__name': self.t1.name},
- {'name': self.au1.name, 'book__title': self.b3.title, 'book__tag__name': self.t1.name},
- {'name': self.au1.name, 'book__title': self.b3.title, 'book__tag__name': self.t2.name},
- {'name': self.au1.name, 'book__title': self.b4.title, 'book__tag__name': self.t2.name},
- {'name': self.au2.name, 'book__title': self.b5.title, 'book__tag__name': self.t2.name},
- {'name': self.au2.name, 'book__title': self.b5.title, 'book__tag__name': self.t3.name},
- {'name': self.au2.name, 'book__title': self.b6.title, 'book__tag__name': self.t3.name},
- {'name': self.au2.name, 'book__title': self.b7.title, 'book__tag__name': self.t3.name},
+ {'name': self.au1.name, 'article__headline': self.a1.headline, 'article__tag__name': self.t1.name},
+ {'name': self.au1.name, 'article__headline': self.a2.headline, 'article__tag__name': self.t1.name},
+ {'name': self.au1.name, 'article__headline': self.a3.headline, 'article__tag__name': self.t1.name},
+ {'name': self.au1.name, 'article__headline': self.a3.headline, 'article__tag__name': self.t2.name},
+ {'name': self.au1.name, 'article__headline': self.a4.headline, 'article__tag__name': self.t2.name},
+ {'name': self.au2.name, 'article__headline': self.a5.headline, 'article__tag__name': self.t2.name},
+ {'name': self.au2.name, 'article__headline': self.a5.headline, 'article__tag__name': self.t3.name},
+ {'name': self.au2.name, 'article__headline': self.a6.headline, 'article__tag__name': self.t3.name},
+ {'name': self.au2.name, 'article__headline': self.a7.headline, 'article__tag__name': self.t3.name},
], transform=identity)
# However, an exception FieldDoesNotExist will be thrown if you specify
# a non-existent field name in values() (a field that is neither in the
# model nor in extra(select)).
self.assertRaises(FieldError,
- Book.objects.extra(select={'id_plus_one': 'id + 1'}).values,
+ Article.objects.extra(select={'id_plus_one': 'id + 1'}).values,
'id', 'id_plus_two')
# If you don't specify field names to values(), all are returned.
- self.assertQuerysetEqual(Book.objects.filter(id=self.b5.id).values(),
+ self.assertQuerysetEqual(Article.objects.filter(id=self.a5.id).values(),
[{
- 'id': self.b5.id,
+ 'id': self.a5.id,
'author_id': self.au2.id,
- 'title': 'Book 5',
- 'pages': 0,
- 'pubdate': datetime(2005, 8, 1, 9, 0)
+ 'headline': 'Article 5',
+ 'pub_date': datetime(2005, 8, 1, 9, 0)
}], transform=identity)
def test_values_list(self):
@@ -261,353 +257,358 @@ class LookupTests(TestCase):
# Within each tuple, the order of the elements is the same as the order
# of fields in the values_list() call.
identity = lambda x:x
- self.assertQuerysetEqual(Book.objects.values_list('title'),
+ self.assertQuerysetEqual(Article.objects.values_list('headline'),
[
- ('Book 5',),
- ('Book 6',),
- ('Book 4',),
- ('Book 2',),
- ('Book 3',),
- ('Book 7',),
- ('Book 1',),
+ ('Article 5',),
+ ('Article 6',),
+ ('Article 4',),
+ ('Article 2',),
+ ('Article 3',),
+ ('Article 7',),
+ ('Article 1',),
], transform=identity)
- self.assertQuerysetEqual(Book.objects.values_list('id').order_by('id'),
- [(self.b1.id,), (self.b2.id,), (self.b3.id,), (self.b4.id,), (self.b5.id,), (self.b6.id,), (self.b7.id,)],
+ self.assertQuerysetEqual(Article.objects.values_list('id').order_by('id'),
+ [(self.a1.id,), (self.a2.id,), (self.a3.id,), (self.a4.id,), (self.a5.id,), (self.a6.id,), (self.a7.id,)],
transform=identity)
self.assertQuerysetEqual(
- Book.objects.values_list('id', flat=True).order_by('id'),
- [self.b1.id, self.b2.id, self.b3.id, self.b4.id, self.b5.id, self.b6.id, self.b7.id],
+ Article.objects.values_list('id', flat=True).order_by('id'),
+ [self.a1.id, self.a2.id, self.a3.id, self.a4.id, self.a5.id, self.a6.id, self.a7.id],
transform=identity)
self.assertQuerysetEqual(
- Book.objects.extra(select={'id_plus_one': 'id+1'})
+ Article.objects.extra(select={'id_plus_one': 'id+1'})
.order_by('id').values_list('id'),
- [(self.b1.id,), (self.b2.id,), (self.b3.id,), (self.b4.id,), (self.b5.id,), (self.b6.id,), (self.b7.id,)],
+ [(self.a1.id,), (self.a2.id,), (self.a3.id,), (self.a4.id,), (self.a5.id,), (self.a6.id,), (self.a7.id,)],
transform=identity)
self.assertQuerysetEqual(
- Book.objects.extra(select={'id_plus_one': 'id+1'})
+ Article.objects.extra(select={'id_plus_one': 'id+1'})
.order_by('id').values_list('id_plus_one', 'id'),
[
- (self.b1.id+1, self.b1.id),
- (self.b2.id+1, self.b2.id),
- (self.b3.id+1, self.b3.id),
- (self.b4.id+1, self.b4.id),
- (self.b5.id+1, self.b5.id),
- (self.b6.id+1, self.b6.id),
- (self.b7.id+1, self.b7.id)
+ (self.a1.id+1, self.a1.id),
+ (self.a2.id+1, self.a2.id),
+ (self.a3.id+1, self.a3.id),
+ (self.a4.id+1, self.a4.id),
+ (self.a5.id+1, self.a5.id),
+ (self.a6.id+1, self.a6.id),
+ (self.a7.id+1, self.a7.id)
],
transform=identity)
self.assertQuerysetEqual(
- Book.objects.extra(select={'id_plus_one': 'id+1'})
+ Article.objects.extra(select={'id_plus_one': 'id+1'})
.order_by('id').values_list('id', 'id_plus_one'),
[
- (self.b1.id, self.b1.id+1),
- (self.b2.id, self.b2.id+1),
- (self.b3.id, self.b3.id+1),
- (self.b4.id, self.b4.id+1),
- (self.b5.id, self.b5.id+1),
- (self.b6.id, self.b6.id+1),
- (self.b7.id, self.b7.id+1)
+ (self.a1.id, self.a1.id+1),
+ (self.a2.id, self.a2.id+1),
+ (self.a3.id, self.a3.id+1),
+ (self.a4.id, self.a4.id+1),
+ (self.a5.id, self.a5.id+1),
+ (self.a6.id, self.a6.id+1),
+ (self.a7.id, self.a7.id+1)
],
transform=identity)
self.assertQuerysetEqual(
- Author.objects.values_list('name', 'book__title', 'book__tag__name').order_by('name', 'book__title', 'book__tag__name'),
+ Author.objects.values_list('name', 'article__headline', 'article__tag__name').order_by('name', 'article__headline', 'article__tag__name'),
[
- (self.au1.name, self.b1.title, self.t1.name),
- (self.au1.name, self.b2.title, self.t1.name),
- (self.au1.name, self.b3.title, self.t1.name),
- (self.au1.name, self.b3.title, self.t2.name),
- (self.au1.name, self.b4.title, self.t2.name),
- (self.au2.name, self.b5.title, self.t2.name),
- (self.au2.name, self.b5.title, self.t3.name),
- (self.au2.name, self.b6.title, self.t3.name),
- (self.au2.name, self.b7.title, self.t3.name),
+ (self.au1.name, self.a1.headline, self.t1.name),
+ (self.au1.name, self.a2.headline, self.t1.name),
+ (self.au1.name, self.a3.headline, self.t1.name),
+ (self.au1.name, self.a3.headline, self.t2.name),
+ (self.au1.name, self.a4.headline, self.t2.name),
+ (self.au2.name, self.a5.headline, self.t2.name),
+ (self.au2.name, self.a5.headline, self.t3.name),
+ (self.au2.name, self.a6.headline, self.t3.name),
+ (self.au2.name, self.a7.headline, self.t3.name),
], transform=identity)
- self.assertRaises(TypeError, Book.objects.values_list, 'id', 'title', flat=True)
+ self.assertRaises(TypeError, Article.objects.values_list, 'id', 'headline', flat=True)
def test_get_next_previous_by(self):
# Every DateField and DateTimeField creates get_next_by_FOO() and
# get_previous_by_FOO() methods. In the case of identical date values,
# these methods will use the ID as a fallback check. This guarantees
# that no records are skipped or duplicated.
- self.assertEqual(repr(self.b1.get_next_by_pubdate()),
- '<Book: Book 2>')
- self.assertEqual(repr(self.b2.get_next_by_pubdate()),
- '<Book: Book 3>')
- self.assertEqual(repr(self.b2.get_next_by_pubdate(title__endswith='6')),
- '<Book: Book 6>')
- self.assertEqual(repr(self.b3.get_next_by_pubdate()),
- '<Book: Book 7>')
- self.assertEqual(repr(self.b4.get_next_by_pubdate()),
- '<Book: Book 6>')
- self.assertRaises(Book.DoesNotExist, self.b5.get_next_by_pubdate)
- self.assertEqual(repr(self.b6.get_next_by_pubdate()),
- '<Book: Book 5>')
- self.assertEqual(repr(self.b7.get_next_by_pubdate()),
- '<Book: Book 4>')
+ self.assertEqual(repr(self.a1.get_next_by_pub_date()),
+ '<Article: Article 2>')
+ self.assertEqual(repr(self.a2.get_next_by_pub_date()),
+ '<Article: Article 3>')
+ self.assertEqual(repr(self.a2.get_next_by_pub_date(headline__endswith='6')),
+ '<Article: Article 6>')
+ self.assertEqual(repr(self.a3.get_next_by_pub_date()),
+ '<Article: Article 7>')
+ self.assertEqual(repr(self.a4.get_next_by_pub_date()),
+ '<Article: Article 6>')
+ self.assertRaises(Article.DoesNotExist, self.a5.get_next_by_pub_date)
+ self.assertEqual(repr(self.a6.get_next_by_pub_date()),
+ '<Article: Article 5>')
+ self.assertEqual(repr(self.a7.get_next_by_pub_date()),
+ '<Article: Article 4>')
- self.assertEqual(repr(self.b7.get_previous_by_pubdate()),
- '<Book: Book 3>')
- self.assertEqual(repr(self.b6.get_previous_by_pubdate()),
- '<Book: Book 4>')
- self.assertEqual(repr(self.b5.get_previous_by_pubdate()),
- '<Book: Book 6>')
- self.assertEqual(repr(self.b4.get_previous_by_pubdate()),
- '<Book: Book 7>')
- self.assertEqual(repr(self.b3.get_previous_by_pubdate()),
- '<Book: Book 2>')
- self.assertEqual(repr(self.b2.get_previous_by_pubdate()),
- '<Book: Book 1>')
+ self.assertEqual(repr(self.a7.get_previous_by_pub_date()),
+ '<Article: Article 3>')
+ self.assertEqual(repr(self.a6.get_previous_by_pub_date()),
+ '<Article: Article 4>')
+ self.assertEqual(repr(self.a5.get_previous_by_pub_date()),
+ '<Article: Article 6>')
+ self.assertEqual(repr(self.a4.get_previous_by_pub_date()),
+ '<Article: Article 7>')
+ self.assertEqual(repr(self.a3.get_previous_by_pub_date()),
+ '<Article: Article 2>')
+ self.assertEqual(repr(self.a2.get_previous_by_pub_date()),
+ '<Article: Article 1>')
def test_escaping(self):
# Underscores, percent signs and backslashes have special meaning in the
# underlying SQL code, but Django handles the quoting of them automatically.
- b8 = Book(title='Book_ with underscore', pubdate=datetime(2005, 11, 20))
- b8.save()
- self.assertQuerysetEqual(Book.objects.filter(title__startswith='Book'),
+ a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
+ a8.save()
+ self.assertQuerysetEqual(Article.objects.filter(headline__startswith='Article'),
[
- '<Book: Book_ with underscore>',
- '<Book: Book 5>',
- '<Book: Book 6>',
- '<Book: Book 4>',
- '<Book: Book 2>',
- '<Book: Book 3>',
- '<Book: Book 7>',
- '<Book: Book 1>',
+ '<Article: Article_ with underscore>',
+ '<Article: Article 5>',
+ '<Article: Article 6>',
+ '<Article: Article 4>',
+ '<Article: Article 2>',
+ '<Article: Article 3>',
+ '<Article: Article 7>',
+ '<Article: Article 1>',
])
- self.assertQuerysetEqual(Book.objects.filter(title__startswith='Book_'),
- ['<Book: Book_ with underscore>'])
- b9 = Book(title='Book% with percent sign', pubdate=datetime(2005, 11, 21))
- b9.save()
- self.assertQuerysetEqual(Book.objects.filter(title__startswith='Book'),
+ self.assertQuerysetEqual(Article.objects.filter(headline__startswith='Article_'),
+ ['<Article: Article_ with underscore>'])
+ a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
+ a9.save()
+ self.assertQuerysetEqual(Article.objects.filter(headline__startswith='Article'),
[
- '<Book: Book% with percent sign>',
- '<Book: Book_ with underscore>',
- '<Book: Book 5>',
- '<Book: Book 6>',
- '<Book: Book 4>',
- '<Book: Book 2>',
- '<Book: Book 3>',
- '<Book: Book 7>',
- '<Book: Book 1>',
+ '<Article: Article% with percent sign>',
+ '<Article: Article_ with underscore>',
+ '<Article: Article 5>',
+ '<Article: Article 6>',
+ '<Article: Article 4>',
+ '<Article: Article 2>',
+ '<Article: Article 3>',
+ '<Article: Article 7>',
+ '<Article: Article 1>',
])
- self.assertQuerysetEqual(Book.objects.filter(title__startswith='Book%'),
- ['<Book: Book% with percent sign>'])
- b10 = Book(title='Book with \\ backslash', pubdate=datetime(2005, 11, 22))
- b10.save()
- self.assertQuerysetEqual(Book.objects.filter(title__contains='\\'),
- ['<Book: Book with \ backslash>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__startswith='Article%'),
+ ['<Article: Article% with percent sign>'])
+ a10 = Article(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22))
+ a10.save()
+ self.assertQuerysetEqual(Article.objects.filter(headline__contains='\\'),
+ ['<Article: Article with \ backslash>'])
def test_exclude(self):
- b8 = Book.objects.create(title='Book_ with underscore', pubdate=datetime(2005, 11, 20))
- b9 = Book.objects.create(title='Book% with percent sign', pubdate=datetime(2005, 11, 21))
- b10 = Book.objects.create(title='Book with \\ backslash', pubdate=datetime(2005, 11, 22))
+ a8 = Article.objects.create(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
+ a9 = Article.objects.create(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
+ a10 = Article.objects.create(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22))
# exclude() is the opposite of filter() when doing lookups:
self.assertQuerysetEqual(
- Book.objects.filter(title__contains='Book').exclude(title__contains='with'),
+ Article.objects.filter(headline__contains='Article').exclude(headline__contains='with'),
[
- '<Book: Book 5>',
- '<Book: Book 6>',
- '<Book: Book 4>',
- '<Book: Book 2>',
- '<Book: Book 3>',
- '<Book: Book 7>',
- '<Book: Book 1>',
+ '<Article: Article 5>',
+ '<Article: Article 6>',
+ '<Article: Article 4>',
+ '<Article: Article 2>',
+ '<Article: Article 3>',
+ '<Article: Article 7>',
+ '<Article: Article 1>',
])
- self.assertQuerysetEqual(Book.objects.exclude(title__startswith="Book_"),
+ self.assertQuerysetEqual(Article.objects.exclude(headline__startswith="Article_"),
[
- '<Book: Book with \\ backslash>',
- '<Book: Book% with percent sign>',
- '<Book: Book 5>',
- '<Book: Book 6>',
- '<Book: Book 4>',
- '<Book: Book 2>',
- '<Book: Book 3>',
- '<Book: Book 7>',
- '<Book: Book 1>',
+ '<Article: Article with \\ backslash>',
+ '<Article: Article% with percent sign>',
+ '<Article: Article 5>',
+ '<Article: Article 6>',
+ '<Article: Article 4>',
+ '<Article: Article 2>',
+ '<Article: Article 3>',
+ '<Article: Article 7>',
+ '<Article: Article 1>',
])
- self.assertQuerysetEqual(Book.objects.exclude(title="Book 7"),
+ self.assertQuerysetEqual(Article.objects.exclude(headline="Article 7"),
[
- '<Book: Book with \\ backslash>',
- '<Book: Book% with percent sign>',
- '<Book: Book_ with underscore>',
- '<Book: Book 5>',
- '<Book: Book 6>',
- '<Book: Book 4>',
- '<Book: Book 2>',
- '<Book: Book 3>',
- '<Book: Book 1>',
+ '<Article: Article with \\ backslash>',
+ '<Article: Article% with percent sign>',
+ '<Article: Article_ with underscore>',
+ '<Article: Article 5>',
+ '<Article: Article 6>',
+ '<Article: Article 4>',
+ '<Article: Article 2>',
+ '<Article: Article 3>',
+ '<Article: Article 1>',
])
def test_none(self):
# none() returns a QuerySet that behaves like any other QuerySet object
- self.assertQuerysetEqual(Book.objects.none(), [])
+ self.assertQuerysetEqual(Article.objects.none(), [])
self.assertQuerysetEqual(
- Book.objects.none().filter(title__startswith='Book'), [])
+ Article.objects.none().filter(headline__startswith='Article'), [])
self.assertQuerysetEqual(
- Book.objects.filter(title__startswith='Book').none(), [])
- self.assertEqual(Book.objects.none().count(), 0)
+ Article.objects.filter(headline__startswith='Article').none(), [])
+ self.assertEqual(Article.objects.none().count(), 0)
self.assertEqual(
- Book.objects.none().update(title="This should not take effect"), 0)
+ Article.objects.none().update(headline="This should not take effect"), 0)
self.assertQuerysetEqual(
- [article for article in Book.objects.none().iterator()],
+ [article for article in Article.objects.none().iterator()],
[])
def test_in(self):
# using __in with an empty list should return an empty query set
- self.assertQuerysetEqual(Book.objects.filter(id__in=[]), [])
- self.assertQuerysetEqual(Book.objects.exclude(id__in=[]),
+ self.assertQuerysetEqual(Article.objects.filter(id__in=[]), [])
+ self.assertQuerysetEqual(Article.objects.exclude(id__in=[]),
[
- '<Book: Book 5>',
- '<Book: Book 6>',
- '<Book: Book 4>',
- '<Book: Book 2>',
- '<Book: Book 3>',
- '<Book: Book 7>',
- '<Book: Book 1>',
+ '<Article: Article 5>',
+ '<Article: Article 6>',
+ '<Article: Article 4>',
+ '<Article: Article 2>',
+ '<Article: Article 3>',
+ '<Article: Article 7>',
+ '<Article: Article 1>',
])
def test_error_messages(self):
# Programming errors are pointed out with nice error messages
- with six.assertRaisesRegex(self, FieldError, "Cannot resolve keyword 'pubdate_year' "
- "into field. Choices are: .+"):
- Book.objects.filter(pubdate_year='2005').count()
-
- with self.assertRaises(FieldError, msg="Join on field 'title' not permitted. "
- "Did you misspell 'starts' for the lookup type?"):
- Book.objects.filter(title__starts='Book')
+ try:
+ Article.objects.filter(pub_date_year='2005').count()
+ self.fail('FieldError not raised')
+ except FieldError as ex:
+ self.assertEqual(str(ex), "Cannot resolve keyword 'pub_date_year' "
+ "into field. Choices are: author, headline, id, pub_date, tag")
+ try:
+ Article.objects.filter(headline__starts='Article')
+ self.fail('FieldError not raised')
+ except FieldError as ex:
+ self.assertEqual(str(ex), "Join on field 'headline' not permitted. "
+ "Did you misspell 'starts' for the lookup type?")
def test_regex(self):
- # Create some articles with a bit more interesting names for testing field lookups:
- for a in Book.objects.all():
+ # Create some articles with a bit more interesting headlines for testing field lookups:
+ for a in Article.objects.all():
a.delete()
now = datetime.now()
- b1 = Book(pubdate=now, title='f')
- b1.save()
- b2 = Book(pubdate=now, title='fo')
- b2.save()
- b3 = Book(pubdate=now, title='foo')
- b3.save()
- b4 = Book(pubdate=now, title='fooo')
- b4.save()
- b5 = Book(pubdate=now, title='hey-Foo')
- b5.save()
- b6 = Book(pubdate=now, title='bar')
- b6.save()
- b7 = Book(pubdate=now, title='AbBa')
- b7.save()
- b8 = Book(pubdate=now, title='baz')
- b8.save()
- b9 = Book(pubdate=now, title='baxZ')
- b9.save()
+ a1 = Article(pub_date=now, headline='f')
+ a1.save()
+ a2 = Article(pub_date=now, headline='fo')
+ a2.save()
+ a3 = Article(pub_date=now, headline='foo')
+ a3.save()
+ a4 = Article(pub_date=now, headline='fooo')
+ a4.save()
+ a5 = Article(pub_date=now, headline='hey-Foo')
+ a5.save()
+ a6 = Article(pub_date=now, headline='bar')
+ a6.save()
+ a7 = Article(pub_date=now, headline='AbBa')
+ a7.save()
+ a8 = Article(pub_date=now, headline='baz')
+ a8.save()
+ a9 = Article(pub_date=now, headline='baxZ')
+ a9.save()
# zero-or-more
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'fo*'),
- ['<Book: f>', '<Book: fo>', '<Book: foo>', '<Book: fooo>'])
- self.assertQuerysetEqual(Book.objects.filter(title__iregex=r'fo*'),
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'fo*'),
+ ['<Article: f>', '<Article: fo>', '<Article: foo>', '<Article: fooo>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'fo*'),
[
- '<Book: f>',
- '<Book: fo>',
- '<Book: foo>',
- '<Book: fooo>',
- '<Book: hey-Foo>',
+ '<Article: f>',
+ '<Article: fo>',
+ '<Article: foo>',
+ '<Article: fooo>',
+ '<Article: hey-Foo>',
])
# one-or-more
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'fo+'),
- ['<Book: fo>', '<Book: foo>', '<Book: fooo>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'fo+'),
+ ['<Article: fo>', '<Article: foo>', '<Article: fooo>'])
# wildcard
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'fooo?'),
- ['<Book: foo>', '<Book: fooo>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'fooo?'),
+ ['<Article: foo>', '<Article: fooo>'])
# leading anchor
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'^b'),
- ['<Book: bar>', '<Book: baxZ>', '<Book: baz>'])
- self.assertQuerysetEqual(Book.objects.filter(title__iregex=r'^a'),
- ['<Book: AbBa>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'^b'),
+ ['<Article: bar>', '<Article: baxZ>', '<Article: baz>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'^a'),
+ ['<Article: AbBa>'])
# trailing anchor
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'z$'),
- ['<Book: baz>'])
- self.assertQuerysetEqual(Book.objects.filter(title__iregex=r'z$'),
- ['<Book: baxZ>', '<Book: baz>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'z$'),
+ ['<Article: baz>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'z$'),
+ ['<Article: baxZ>', '<Article: baz>'])
# character sets
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'ba[rz]'),
- ['<Book: bar>', '<Book: baz>'])
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'ba.[RxZ]'),
- ['<Book: baxZ>'])
- self.assertQuerysetEqual(Book.objects.filter(title__iregex=r'ba[RxZ]'),
- ['<Book: bar>', '<Book: baxZ>', '<Book: baz>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'ba[rz]'),
+ ['<Article: bar>', '<Article: baz>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'ba.[RxZ]'),
+ ['<Article: baxZ>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'ba[RxZ]'),
+ ['<Article: bar>', '<Article: baxZ>', '<Article: baz>'])
# and more articles:
- b10 = Book(pubdate=now, title='foobar')
- b10.save()
- b11 = Book(pubdate=now, title='foobaz')
- b11.save()
- b12 = Book(pubdate=now, title='ooF')
- b12.save()
- b13 = Book(pubdate=now, title='foobarbaz')
- b13.save()
- b14 = Book(pubdate=now, title='zoocarfaz')
- b14.save()
- b15 = Book(pubdate=now, title='barfoobaz')
- b15.save()
- b16 = Book(pubdate=now, title='bazbaRFOO')
- b16.save()
+ a10 = Article(pub_date=now, headline='foobar')
+ a10.save()
+ a11 = Article(pub_date=now, headline='foobaz')
+ a11.save()
+ a12 = Article(pub_date=now, headline='ooF')
+ a12.save()
+ a13 = Article(pub_date=now, headline='foobarbaz')
+ a13.save()
+ a14 = Article(pub_date=now, headline='zoocarfaz')
+ a14.save()
+ a15 = Article(pub_date=now, headline='barfoobaz')
+ a15.save()
+ a16 = Article(pub_date=now, headline='bazbaRFOO')
+ a16.save()
# alternation
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'oo(f|b)'),
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'oo(f|b)'),
[
- '<Book: barfoobaz>',
- '<Book: foobar>',
- '<Book: foobarbaz>',
- '<Book: foobaz>',
+ '<Article: barfoobaz>',
+ '<Article: foobar>',
+ '<Article: foobarbaz>',
+ '<Article: foobaz>',
])
- self.assertQuerysetEqual(Book.objects.filter(title__iregex=r'oo(f|b)'),
+ self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'oo(f|b)'),
[
- '<Book: barfoobaz>',
- '<Book: foobar>',
- '<Book: foobarbaz>',
- '<Book: foobaz>',
- '<Book: ooF>',
+ '<Article: barfoobaz>',
+ '<Article: foobar>',
+ '<Article: foobarbaz>',
+ '<Article: foobaz>',
+ '<Article: ooF>',
])
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'^foo(f|b)'),
- ['<Book: foobar>', '<Book: foobarbaz>', '<Book: foobaz>'])
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'^foo(f|b)'),
+ ['<Article: foobar>', '<Article: foobarbaz>', '<Article: foobaz>'])
# greedy matching
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'b.*az'),
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'b.*az'),
[
- '<Book: barfoobaz>',
- '<Book: baz>',
- '<Book: bazbaRFOO>',
- '<Book: foobarbaz>',
- '<Book: foobaz>',
+ '<Article: barfoobaz>',
+ '<Article: baz>',
+ '<Article: bazbaRFOO>',
+ '<Article: foobarbaz>',
+ '<Article: foobaz>',
])
- self.assertQuerysetEqual(Book.objects.filter(title__iregex=r'b.*ar'),
+ self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'b.*ar'),
[
- '<Book: bar>',
- '<Book: barfoobaz>',
- '<Book: bazbaRFOO>',
- '<Book: foobar>',
- '<Book: foobarbaz>',
+ '<Article: bar>',
+ '<Article: barfoobaz>',
+ '<Article: bazbaRFOO>',
+ '<Article: foobar>',
+ '<Article: foobarbaz>',
])
@skipUnlessDBFeature('supports_regex_backreferencing')
def test_regex_backreferencing(self):
# grouping and backreferences
now = datetime.now()
- b10 = Book(pubdate=now, title='foobar')
- b10.save()
- b11 = Book(pubdate=now, title='foobaz')
- b11.save()
- b12 = Book(pubdate=now, title='ooF')
- b12.save()
- b13 = Book(pubdate=now, title='foobarbaz')
- b13.save()
- b14 = Book(pubdate=now, title='zoocarfaz')
- b14.save()
- b15 = Book(pubdate=now, title='barfoobaz')
- b15.save()
- b16 = Book(pubdate=now, title='bazbaRFOO')
- b16.save()
- self.assertQuerysetEqual(Book.objects.filter(title__regex=r'b(.).*b\1'),
- ['<Book: barfoobaz>', '<Book: bazbaRFOO>', '<Book: foobarbaz>'])
+ a10 = Article(pub_date=now, headline='foobar')
+ a10.save()
+ a11 = Article(pub_date=now, headline='foobaz')
+ a11.save()
+ a12 = Article(pub_date=now, headline='ooF')
+ a12.save()
+ a13 = Article(pub_date=now, headline='foobarbaz')
+ a13.save()
+ a14 = Article(pub_date=now, headline='zoocarfaz')
+ a14.save()
+ a15 = Article(pub_date=now, headline='barfoobaz')
+ a15.save()
+ a16 = Article(pub_date=now, headline='bazbaRFOO')
+ a16.save()
+ self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'b(.).*b\1'),
+ ['<Article: barfoobaz>', '<Article: bazbaRFOO>', '<Article: foobarbaz>'])
def test_nonfield_lookups(self):
"""
@@ -615,11 +616,11 @@ class LookupTests(TestCase):
exception.
"""
with self.assertRaises(FieldError):
- Book.objects.filter(name__blahblah=99)
+ Article.objects.filter(headline__blahblah=99)
with self.assertRaises(FieldError):
- Book.objects.filter(name__blahblah__exact=99)
+ Article.objects.filter(headline__blahblah__exact=99)
with self.assertRaises(FieldError):
- Book.objects.filter(blahblah=99)
+ Article.objects.filter(blahblah=99)
def test_lookup_collision(self):
"""
diff --git a/tests/m2m_through_regress/tests.py b/tests/m2m_through_regress/tests.py
index 5ac10462fa..de4d52a2db 100644
--- a/tests/m2m_through_regress/tests.py
+++ b/tests/m2m_through_regress/tests.py
@@ -10,6 +10,7 @@ from .models import (Person, Group, Membership, UserMembership, Car, Driver,
class M2MThroughTestCase(TestCase):
+
def test_everything(self):
bob = Person.objects.create(name="Bob")
jim = Person.objects.create(name="Jim")
diff --git a/tests/middleware/tests.py b/tests/middleware/tests.py
index 265eb97c36..20645cf91f 100644
--- a/tests/middleware/tests.py
+++ b/tests/middleware/tests.py
@@ -707,6 +707,9 @@ class TransactionMiddlewareTest(IgnorePendingDeprecationWarningsMixin, Transacti
"""
Test the transaction middleware.
"""
+
+ available_apps = ['middleware']
+
def setUp(self):
super(TransactionMiddlewareTest, self).setUp()
self.request = HttpRequest()
diff --git a/tests/model_forms/models.py b/tests/model_forms/models.py
index 610dc34001..a4cf9471de 100644
--- a/tests/model_forms/models.py
+++ b/tests/model_forms/models.py
@@ -11,13 +11,13 @@ from __future__ import unicode_literals
import os
import tempfile
+from django.core import validators
from django.core.exceptions import ImproperlyConfigured
from django.core.files.storage import FileSystemStorage
from django.db import models
from django.utils import six
from django.utils.encoding import python_2_unicode_compatible
-from shared_models.models import Author, Book
temp_storage_dir = tempfile.mkdtemp(dir=os.environ['DJANGO_TEST_TEMP_DIR'])
temp_storage = FileSystemStorage(temp_storage_dir)
@@ -47,12 +47,22 @@ class Category(models.Model):
return self.__str__()
@python_2_unicode_compatible
+class Writer(models.Model):
+ name = models.CharField(max_length=50, help_text='Use both first and last names.')
+
+ class Meta:
+ ordering = ('name',)
+
+ def __str__(self):
+ return self.name
+
+@python_2_unicode_compatible
class Article(models.Model):
headline = models.CharField(max_length=50)
slug = models.SlugField()
pub_date = models.DateField()
created = models.DateField(editable=False)
- writer = models.ForeignKey(Author)
+ writer = models.ForeignKey(Writer)
article = models.TextField()
categories = models.ManyToManyField(Category, blank=True)
status = models.PositiveIntegerField(choices=ARTICLE_STATUS, blank=True, null=True)
@@ -72,12 +82,12 @@ class ImprovedArticle(models.Model):
class ImprovedArticleWithParentLink(models.Model):
article = models.OneToOneField(Article, parent_link=True)
-class BetterAuthor(Author):
+class BetterWriter(Writer):
score = models.IntegerField()
@python_2_unicode_compatible
-class AuthorProfile(models.Model):
- writer = models.OneToOneField(Author, primary_key=True)
+class WriterProfile(models.Model):
+ writer = models.OneToOneField(Writer, primary_key=True)
age = models.PositiveIntegerField()
def __str__(self):
@@ -177,6 +187,14 @@ class Inventory(models.Model):
def __repr__(self):
return self.__str__()
+class Book(models.Model):
+ title = models.CharField(max_length=40)
+ author = models.ForeignKey(Writer, blank=True, null=True)
+ special_id = models.IntegerField(blank=True, null=True, unique=True)
+
+ class Meta:
+ unique_together = ('title', 'author')
+
class BookXtra(models.Model):
isbn = models.CharField(max_length=16, unique=True)
suffix1 = models.IntegerField(blank=True, default=0)
@@ -269,3 +287,12 @@ class ColourfulItem(models.Model):
class ArticleStatusNote(models.Model):
name = models.CharField(max_length=20)
status = models.ManyToManyField(ArticleStatus)
+
+class CustomErrorMessage(models.Model):
+ name1 = models.CharField(max_length=50,
+ validators=[validators.validate_slug],
+ error_messages={'invalid': 'Model custom error message.'})
+
+ name2 = models.CharField(max_length=50,
+ validators=[validators.validate_slug],
+ error_messages={'invalid': 'Model custom error message.'})
diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py
index 58dde13a8a..39be824798 100644
--- a/tests/model_forms/tests.py
+++ b/tests/model_forms/tests.py
@@ -17,14 +17,12 @@ from django.utils.unittest import skipUnless
from django.test import TestCase
from django.utils import six
-from shared_models.models import Author, Book
-
-from .models import (Article, ArticleStatus, BetterAuthor, BigInt,
+from .models import (Article, ArticleStatus, BetterWriter, BigInt, Book,
Category, CommaSeparatedInteger, CustomFieldForExclusionModel, DerivedBook,
DerivedPost, ExplicitPK, FlexibleDatePost, ImprovedArticle,
ImprovedArticleWithParentLink, Inventory, Post, Price,
- Product, TextFile, AuthorProfile, Colour, ColourfulItem,
- ArticleStatusNote, DateTimePost, test_images)
+ Product, TextFile, Writer, WriterProfile, Colour, ColourfulItem,
+ ArticleStatusNote, DateTimePost, CustomErrorMessage, test_images)
if test_images:
from .models import ImageFile, OptionalImageFile
@@ -54,14 +52,15 @@ class PriceForm(forms.ModelForm):
class BookForm(forms.ModelForm):
class Meta:
- fields = ['title', 'author', 'pubdate']
model = Book
+ fields = '__all__'
class DerivedBookForm(forms.ModelForm):
class Meta:
- fields = ['title', 'author', 'isbn', 'suffix1', 'suffix2']
model = DerivedBook
+ fields = '__all__'
+
class ExplicitPKForm(forms.ModelForm):
@@ -88,11 +87,11 @@ class DerivedPostForm(forms.ModelForm):
fields = '__all__'
-class CustomAuthorForm(forms.ModelForm):
+class CustomWriterForm(forms.ModelForm):
name = forms.CharField(required=False)
class Meta:
- model = Author
+ model = Writer
fields = '__all__'
@@ -128,7 +127,7 @@ class PartialArticleForm(forms.ModelForm):
class RoykoForm(forms.ModelForm):
class Meta:
- model = Author
+ model = Writer
fields = '__all__'
@@ -188,15 +187,14 @@ class ImprovedArticleWithParentLinkForm(forms.ModelForm):
fields = '__all__'
-class BetterAuthorForm(forms.ModelForm):
+class BetterWriterForm(forms.ModelForm):
class Meta:
- model = BetterAuthor
+ model = BetterWriter
fields = '__all__'
-
-class AuthorProfileForm(forms.ModelForm):
+class WriterProfileForm(forms.ModelForm):
class Meta:
- model = AuthorProfile
+ model = WriterProfile
fields = '__all__'
@@ -254,6 +252,12 @@ class StatusNoteCBM2mForm(forms.ModelForm):
fields = '__all__'
widgets = {'status': forms.CheckboxSelectMultiple}
+class CustomErrorMessageForm(forms.ModelForm):
+ name1 = forms.CharField(error_messages={'invalid': 'Form custom error message.'})
+
+ class Meta:
+ model = CustomErrorMessage
+
class ModelFormBaseTest(TestCase):
def test_base_form(self):
@@ -324,14 +328,14 @@ class ModelFormBaseTest(TestCase):
forms.fields.BooleanField)
def test_override_field(self):
- class AuthorForm(forms.ModelForm):
+ class WriterForm(forms.ModelForm):
book = forms.CharField(required=False)
class Meta:
- model = Author
+ model = Writer
fields = '__all__'
- wf = AuthorForm({'name': 'Richard Lockridge'})
+ wf = WriterForm({'name': 'Richard Lockridge'})
self.assertTrue(wf.is_valid())
def test_limit_nonexistent_field(self):
@@ -495,7 +499,7 @@ class ModelFormBaseTest(TestCase):
['slug', 'name'])
-class TestWidgetForm(forms.ModelForm):
+class FieldOverridesTroughFormMetaForm(forms.ModelForm):
class Meta:
model = Category
fields = ['name', 'url', 'slug']
@@ -503,25 +507,74 @@ class TestWidgetForm(forms.ModelForm):
'name': forms.Textarea,
'url': forms.TextInput(attrs={'class': 'url'})
}
+ labels = {
+ 'name': 'Title',
+ }
+ help_texts = {
+ 'slug': 'Watch out! Letters, numbers, underscores and hyphens only.',
+ }
+ error_messages = {
+ 'slug': {
+ 'invalid': (
+ "Didn't you read the help text? "
+ "We said letters, numbers, underscores and hyphens only!"
+ )
+ }
+ }
+class TestFieldOverridesTroughFormMeta(TestCase):
+ def test_widget_overrides(self):
+ form = FieldOverridesTroughFormMetaForm()
+ self.assertHTMLEqual(
+ str(form['name']),
+ '<textarea id="id_name" rows="10" cols="40" name="name"></textarea>',
+ )
+ self.assertHTMLEqual(
+ str(form['url']),
+ '<input id="id_url" type="text" class="url" name="url" maxlength="40" />',
+ )
+ self.assertHTMLEqual(
+ str(form['slug']),
+ '<input id="id_slug" type="text" name="slug" maxlength="20" />',
+ )
-class TestWidgets(TestCase):
- def test_base_widgets(self):
- frm = TestWidgetForm()
+ def test_label_overrides(self):
+ form = FieldOverridesTroughFormMetaForm()
self.assertHTMLEqual(
- str(frm['name']),
- '<textarea id="id_name" rows="10" cols="40" name="name"></textarea>'
+ str(form['name'].label_tag()),
+ '<label for="id_name">Title:</label>',
)
self.assertHTMLEqual(
- str(frm['url']),
- '<input id="id_url" type="text" class="url" name="url" maxlength="40" />'
+ str(form['url'].label_tag()),
+ '<label for="id_url">The URL:</label>',
)
self.assertHTMLEqual(
- str(frm['slug']),
- '<input id="id_slug" type="text" name="slug" maxlength="20" />'
+ str(form['slug'].label_tag()),
+ '<label for="id_slug">Slug:</label>',
+ )
+
+ def test_help_text_overrides(self):
+ form = FieldOverridesTroughFormMetaForm()
+ self.assertEqual(
+ form['slug'].help_text,
+ 'Watch out! Letters, numbers, underscores and hyphens only.',
)
+ def test_error_messages_overrides(self):
+ form = FieldOverridesTroughFormMetaForm(data={
+ 'name': 'Category',
+ 'url': '/category/',
+ 'slug': '!%#*@',
+ })
+ form.full_clean()
+
+ error = [
+ "Didn't you read the help text? "
+ "We said letters, numbers, underscores and hyphens only!",
+ ]
+ self.assertEqual(form.errors, {'slug': error})
+
class IncompleteCategoryFormWithFields(forms.ModelForm):
"""
@@ -556,7 +609,7 @@ class ValidationTest(TestCase):
assert form.is_valid()
def test_notrequired_overrides_notblank(self):
- form = CustomAuthorForm({})
+ form = CustomWriterForm({})
assert form.is_valid()
@@ -565,7 +618,7 @@ class ValidationTest(TestCase):
# unique/unique_together validation
class UniqueTest(TestCase):
def setUp(self):
- self.author = Author.objects.create(name='Mike Royko')
+ self.writer = Writer.objects.create(name='Mike Royko')
def test_simple_unique(self):
form = ProductForm({'slug': 'teddy-bear-blue'})
@@ -589,31 +642,33 @@ class UniqueTest(TestCase):
def test_unique_null(self):
title = 'I May Be Wrong But I Doubt It'
- form = BookForm({'title': title, 'author': self.author.pk, 'pubdate': '2012-12-12 00:00:00'})
+ form = BookForm({'title': title, 'author': self.writer.pk})
self.assertTrue(form.is_valid())
form.save()
- form = BookForm({'title': title, 'author': self.author.pk, 'pubdate': '2012-12-12 00:00:00'})
+ form = BookForm({'title': title, 'author': self.writer.pk})
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
self.assertEqual(form.errors['__all__'], ['Book with this Title and Author already exists.'])
- form = BookForm({'title': title, 'pubdate': '2012-12-12 00:00:00'})
+ form = BookForm({'title': title})
self.assertTrue(form.is_valid())
form.save()
- form = BookForm({'title': title, 'pubdate': '2012-12-12 00:00:00'})
+ form = BookForm({'title': title})
self.assertTrue(form.is_valid())
def test_inherited_unique(self):
- form = BetterAuthorForm({'name': 'Mike Royko', 'score': 3})
+ title = 'Boss'
+ Book.objects.create(title=title, author=self.writer, special_id=1)
+ form = DerivedBookForm({'title': 'Other', 'author': self.writer.pk, 'special_id': '1', 'isbn': '12345'})
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
- self.assertEqual(form.errors['name'], ['Author with this Name already exists.'])
+ self.assertEqual(form.errors['special_id'], ['Book with this Special id already exists.'])
def test_inherited_unique_together(self):
title = 'Boss'
- form = BookForm({'title': title, 'author': self.author.pk, 'pubdate': '2012-12-12 00:00:00'})
+ form = BookForm({'title': title, 'author': self.writer.pk})
self.assertTrue(form.is_valid())
form.save()
- form = DerivedBookForm({'title': title, 'author': self.author.pk, 'isbn': '12345'})
+ form = DerivedBookForm({'title': title, 'author': self.writer.pk, 'isbn': '12345'})
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
self.assertEqual(form.errors['__all__'], ['Book with this Title and Author already exists.'])
@@ -621,9 +676,8 @@ class UniqueTest(TestCase):
def test_abstract_inherited_unique(self):
title = 'Boss'
isbn = '12345'
- dbook = DerivedBook.objects.create(title=title, author=self.author, isbn=isbn,
- pubdate='2012-12-12 00:00')
- form = DerivedBookForm({'title': 'Other', 'author': self.author.pk, 'isbn': isbn})
+ dbook = DerivedBook.objects.create(title=title, author=self.writer, isbn=isbn)
+ form = DerivedBookForm({'title': 'Other', 'author': self.writer.pk, 'isbn': isbn})
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
self.assertEqual(form.errors['isbn'], ['Derived book with this Isbn already exists.'])
@@ -631,11 +685,10 @@ class UniqueTest(TestCase):
def test_abstract_inherited_unique_together(self):
title = 'Boss'
isbn = '12345'
- dbook = DerivedBook.objects.create(title=title, author=self.author, isbn=isbn,
- pubdate='2012-12-12 00:00')
+ dbook = DerivedBook.objects.create(title=title, author=self.writer, isbn=isbn)
form = DerivedBookForm({
'title': 'Other',
- 'author': self.author.pk,
+ 'author': self.writer.pk,
'isbn': '9876',
'suffix1': '0',
'suffix2': '0'
@@ -753,7 +806,7 @@ class ModelToDictTests(TestCase):
]
for c in categories:
c.save()
- writer = Author(name='Test writer')
+ writer = Writer(name='Test writer')
writer.save()
art = Article(
@@ -862,10 +915,10 @@ class OldFormForXTests(TestCase):
with self.assertRaises(ValueError):
f.save()
- # Create a couple of Authors.
- w_royko = Author(name='Mike Royko')
+ # Create a couple of Writers.
+ w_royko = Writer(name='Mike Royko')
w_royko.save()
- w_woodward = Author(name='Bob Woodward')
+ w_woodward = Writer(name='Bob Woodward')
w_woodward.save()
# ManyToManyFields are represented by a MultipleChoiceField, ForeignKeys and any
# fields with the 'choices' attribute are represented by a ChoiceField.
@@ -903,9 +956,9 @@ class OldFormForXTests(TestCase):
# When the ModelForm is passed an instance, that instance's current values are
# inserted as 'initial' data in each Field.
- w = Author.objects.get(name='Mike Royko')
+ w = Writer.objects.get(name='Mike Royko')
f = RoykoForm(auto_id=False, instance=w)
- self.assertHTMLEqual(six.text_type(f), '''<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="100" /><br /><span class="helptext">Use both first and last names.</span></td></tr>''')
+ self.assertHTMLEqual(six.text_type(f), '''<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br /><span class="helptext">Use both first and last names.</span></td></tr>''')
art = Article(
headline='Test article',
@@ -1117,7 +1170,7 @@ class OldFormForXTests(TestCase):
c4 = Category.objects.create(name='Fourth', url='4th')
self.assertEqual(c4.name, 'Fourth')
- w_bernstein = Author.objects.create(name='Carl Bernstein')
+ w_bernstein = Writer.objects.create(name='Carl Bernstein')
self.assertEqual(w_bernstein.name, 'Carl Bernstein')
self.assertHTMLEqual(f.as_ul(), '''<li>Headline: <input type="text" name="headline" maxlength="50" /></li>
<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
@@ -1294,17 +1347,17 @@ class OldFormForXTests(TestCase):
self.assertEqual(list(ImprovedArticleWithParentLinkForm.base_fields), [])
- bw = BetterAuthor(name='Joe Better', score=10)
+ bw = BetterWriter(name='Joe Better', score=10)
bw.save()
self.assertEqual(sorted(model_to_dict(bw)),
- ['author_ptr', 'id', 'name', 'score'])
+ ['id', 'name', 'score', 'writer_ptr'])
- form = BetterAuthorForm({'name': 'Some Name', 'score': 12})
+ form = BetterWriterForm({'name': 'Some Name', 'score': 12})
self.assertEqual(form.is_valid(), True)
bw2 = form.save()
bw2.delete()
- form = AuthorProfileForm()
+ form = WriterProfileForm()
self.assertHTMLEqual(form.as_p(), '''<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer">
<option value="" selected="selected">---------</option>
<option value="%s">Bob Woodward</option>
@@ -1318,11 +1371,11 @@ class OldFormForXTests(TestCase):
'writer': six.text_type(w_woodward.pk),
'age': '65',
}
- form = AuthorProfileForm(data)
+ form = WriterProfileForm(data)
instance = form.save()
self.assertEqual(six.text_type(instance), 'Bob Woodward is 65')
- form = AuthorProfileForm(instance=instance)
+ form = WriterProfileForm(instance=instance)
self.assertHTMLEqual(form.as_p(), '''<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer">
<option value="">---------</option>
<option value="%s" selected="selected">Bob Woodward</option>
@@ -1715,6 +1768,18 @@ class OldFormForXTests(TestCase):
</select> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></p>"""
% {'blue_pk': colour.pk})
+ def test_custom_error_messages(self) :
+ data = {'name1': '@#$!!**@#$', 'name2': '@#$!!**@#$'}
+ errors = CustomErrorMessageForm(data).errors
+ self.assertHTMLEqual(
+ str(errors['name1']),
+ '<ul class="errorlist"><li>Form custom error message.</li></ul>'
+ )
+ self.assertHTMLEqual(
+ str(errors['name2']),
+ '<ul class="errorlist"><li>Model custom error message.</li></ul>'
+ )
+
class M2mHelpTextTest(TestCase):
"""Tests for ticket #9321."""
diff --git a/tests/model_forms_regress/tests.py b/tests/model_forms_regress/tests.py
index 80900a59e0..39ae857219 100644
--- a/tests/model_forms_regress/tests.py
+++ b/tests/model_forms_regress/tests.py
@@ -97,12 +97,14 @@ class PartiallyLocalizedTripleForm(forms.ModelForm):
class Meta:
model = Triple
localized_fields = ('left', 'right',)
+ fields = '__all__'
class FullyLocalizedTripleForm(forms.ModelForm):
class Meta:
model = Triple
- localized_fields = "__all__"
+ localized_fields = '__all__'
+ fields = '__all__'
class LocalizedModelFormTest(TestCase):
def test_model_form_applies_localize_to_some_fields(self):
diff --git a/tests/model_formsets/tests.py b/tests/model_formsets/tests.py
index 8cfdf53995..03cd3b0159 100644
--- a/tests/model_formsets/tests.py
+++ b/tests/model_formsets/tests.py
@@ -1261,7 +1261,7 @@ class ModelFormsetTest(TestCase):
['Please correct the duplicate data for subtitle which must be unique for the month in posted.'])
-class TestModelFormsetWidgets(TestCase):
+class TestModelFormsetOverridesTroughFormMeta(TestCase):
def test_modelformset_factory_widgets(self):
widgets = {
'name': forms.TextInput(attrs={'class': 'poet'})
@@ -1283,3 +1283,53 @@ class TestModelFormsetWidgets(TestCase):
"%s" % form['title'],
'<input class="book" id="id_title" maxlength="100" name="title" type="text" />'
)
+
+ def test_modelformset_factory_labels_overrides(self):
+ BookFormSet = modelformset_factory(Book, fields="__all__", labels={
+ 'title': 'Name'
+ })
+ form = BookFormSet.form()
+ self.assertHTMLEqual(form['title'].label_tag(), '<label for="id_title">Name:</label>')
+
+ def test_inlineformset_factory_labels_overrides(self):
+ BookFormSet = inlineformset_factory(Author, Book, fields="__all__", labels={
+ 'title': 'Name'
+ })
+ form = BookFormSet.form()
+ self.assertHTMLEqual(form['title'].label_tag(), '<label for="id_title">Name:</label>')
+
+ def test_modelformset_factory_help_text_overrides(self):
+ BookFormSet = modelformset_factory(Book, fields="__all__", help_texts={
+ 'title': 'Choose carefully.'
+ })
+ form = BookFormSet.form()
+ self.assertEqual(form['title'].help_text, 'Choose carefully.')
+
+ def test_inlineformset_factory_help_text_overrides(self):
+ BookFormSet = inlineformset_factory(Author, Book, fields="__all__", help_texts={
+ 'title': 'Choose carefully.'
+ })
+ form = BookFormSet.form()
+ self.assertEqual(form['title'].help_text, 'Choose carefully.')
+
+ def test_modelformset_factory_error_messages_overrides(self):
+ author = Author.objects.create(pk=1, name='Charles Baudelaire')
+ BookFormSet = modelformset_factory(Book, fields="__all__", error_messages={
+ 'title': {
+ 'max_length': 'Title too long!!'
+ }
+ })
+ form = BookFormSet.form(data={'title': 'Foo ' * 30, 'author': author.id})
+ form.full_clean()
+ self.assertEqual(form.errors, {'title': ['Title too long!!']})
+
+ def test_inlineformset_factory_error_messages_overrides(self):
+ author = Author.objects.create(pk=1, name='Charles Baudelaire')
+ BookFormSet = inlineformset_factory(Author, Book, fields="__all__", error_messages={
+ 'title': {
+ 'max_length': 'Title too long!!'
+ }
+ })
+ form = BookFormSet.form(data={'title': 'Foo ' * 30, 'author': author.id})
+ form.full_clean()
+ self.assertEqual(form.errors, {'title': ['Title too long!!']})
diff --git a/tests/multiple_database/tests.py b/tests/multiple_database/tests.py
index e72fb6a4f9..a0d937ce81 100644
--- a/tests/multiple_database/tests.py
+++ b/tests/multiple_database/tests.py
@@ -1943,6 +1943,12 @@ class SyncOnlyDefaultDatabaseRouter(object):
class SyncDBTestCase(TestCase):
+
+ available_apps = [
+ 'multiple_database',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes'
+ ]
multi_db = True
def test_syncdb_to_other_database(self):
diff --git a/tests/proxy_model_inheritance/tests.py b/tests/proxy_model_inheritance/tests.py
index 239bc67809..85bf74a4e9 100644
--- a/tests/proxy_model_inheritance/tests.py
+++ b/tests/proxy_model_inheritance/tests.py
@@ -22,6 +22,8 @@ class ProxyModelInheritanceTests(TransactionTestCase):
apps and calls syncdb, then verifies that the table has been created.
"""
+ available_apps = []
+
def setUp(self):
self.old_sys_path = sys.path[:]
sys.path.append(os.path.dirname(os.path.abspath(upath(__file__))))
@@ -38,7 +40,11 @@ class ProxyModelInheritanceTests(TransactionTestCase):
del cache.app_models['app2']
def test_table_exists(self):
- call_command('syncdb', verbosity=0)
+ try:
+ cache.set_available_apps(settings.INSTALLED_APPS)
+ call_command('syncdb', verbosity=0)
+ finally:
+ cache.unset_available_apps()
from .app1.models import ProxyModel
from .app2.models import NiceModel
self.assertEqual(NiceModel.objects.all().count(), 0)
diff --git a/tests/queries/tests.py b/tests/queries/tests.py
index 481b690c20..352e87a634 100644
--- a/tests/queries/tests.py
+++ b/tests/queries/tests.py
@@ -16,15 +16,16 @@ from django.test.utils import str_prefix
from django.utils import unittest
from django.utils.datastructures import SortedDict
-from .models import (Annotation, Article, Author, Celebrity, Child, Cover,
- Detail, DumbCategory, ExtraInfo, Fan, Item, LeafA, Join, LeafB, LoopX, LoopZ,
- ManagedModel, Member, NamedCategory, Note, Number, Plaything, PointerA,
- Ranking, Related, Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten,
- Node, ObjectA, ObjectB, ObjectC, CategoryItem, SimpleCategory,
- SpecialCategory, OneToOneCategory, NullableName, ProxyCategory,
- SingleObject, RelatedObject, ModelA, ModelB, ModelC, ModelD, Responsibility,
- Job, JobResponsibilities, BaseA, Identifier, Program, Channel, Page,
- Paragraph, Chapter, Book, MyObject, Order, OrderItem)
+from .models import (
+ Annotation, Article, Author, Celebrity, Child, Cover, Detail, DumbCategory,
+ ExtraInfo, Fan, Item, LeafA, Join, LeafB, LoopX, LoopZ, ManagedModel,
+ Member, NamedCategory, Note, Number, Plaything, PointerA, Ranking, Related,
+ Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten, Node, ObjectA,
+ ObjectB, ObjectC, CategoryItem, SimpleCategory, SpecialCategory,
+ OneToOneCategory, NullableName, ProxyCategory, SingleObject, RelatedObject,
+ ModelA, ModelB, ModelC, ModelD, Responsibility, Job, JobResponsibilities,
+ BaseA, FK1, Identifier, Program, Channel, Page, Paragraph, Chapter, Book,
+ MyObject, Order, OrderItem)
class BaseQuerysetTest(TestCase):
@@ -1975,13 +1976,62 @@ class EmptyQuerySetTests(TestCase):
class ValuesQuerysetTests(BaseQuerysetTest):
- def test_flat_values_lits(self):
+ def setUp(self):
Number.objects.create(num=72)
+ self.identity = lambda x: x
+
+ def test_flat_values_list(self):
qs = Number.objects.values_list("num")
qs = qs.values_list("num", flat=True)
- self.assertValueQuerysetEqual(
- qs, [72]
- )
+ self.assertValueQuerysetEqual(qs, [72])
+
+ def test_extra_values(self):
+ # testing for ticket 14930 issues
+ qs = Number.objects.extra(select=SortedDict([('value_plus_x', 'num+%s'),
+ ('value_minus_x', 'num-%s')]),
+ select_params=(1, 2))
+ qs = qs.order_by('value_minus_x')
+ qs = qs.values('num')
+ self.assertQuerysetEqual(qs, [{'num': 72}], self.identity)
+
+ def test_extra_values_order_twice(self):
+ # testing for ticket 14930 issues
+ qs = Number.objects.extra(select={'value_plus_one': 'num+1', 'value_minus_one': 'num-1'})
+ qs = qs.order_by('value_minus_one').order_by('value_plus_one')
+ qs = qs.values('num')
+ self.assertQuerysetEqual(qs, [{'num': 72}], self.identity)
+
+ def test_extra_values_order_multiple(self):
+ # Postgres doesn't allow constants in order by, so check for that.
+ qs = Number.objects.extra(select={
+ 'value_plus_one': 'num+1',
+ 'value_minus_one': 'num-1',
+ 'constant_value': '1'
+ })
+ qs = qs.order_by('value_plus_one', 'value_minus_one', 'constant_value')
+ qs = qs.values('num')
+ self.assertQuerysetEqual(qs, [{'num': 72}], self.identity)
+
+ def test_extra_values_order_in_extra(self):
+ # testing for ticket 14930 issues
+ qs = Number.objects.extra(
+ select={'value_plus_one': 'num+1', 'value_minus_one': 'num-1'},
+ order_by=['value_minus_one'])
+ qs = qs.values('num')
+
+ def test_extra_values_list(self):
+ # testing for ticket 14930 issues
+ qs = Number.objects.extra(select={'value_plus_one': 'num+1'})
+ qs = qs.order_by('value_plus_one')
+ qs = qs.values_list('num')
+ self.assertQuerysetEqual(qs, [(72,)], self.identity)
+
+ def test_flat_extra_values_list(self):
+ # testing for ticket 14930 issues
+ qs = Number.objects.extra(select={'value_plus_one': 'num+1'})
+ qs = qs.order_by('value_plus_one')
+ qs = qs.values_list('num', flat=True)
+ self.assertQuerysetEqual(qs, [72], self.identity)
class WeirdQuerysetSlicingTests(BaseQuerysetTest):
@@ -2620,6 +2670,19 @@ class JoinReuseTest(TestCase):
self.assertEqual(str(qs.query).count('JOIN'), 2)
class DisjunctionPromotionTests(TestCase):
+ def test_disjuction_promotion_select_related(self):
+ fk1 = FK1.objects.create(f1='f1', f2='f2')
+ basea = BaseA.objects.create(a=fk1)
+ qs = BaseA.objects.filter(Q(a=fk1) | Q(b=2))
+ self.assertEqual(str(qs.query).count(' JOIN '), 0)
+ qs = qs.select_related('a', 'b')
+ self.assertEqual(str(qs.query).count(' INNER JOIN '), 0)
+ self.assertEqual(str(qs.query).count(' LEFT OUTER JOIN '), 2)
+ with self.assertNumQueries(1):
+ self.assertQuerysetEqual(qs, [basea], lambda x: x)
+ self.assertEqual(qs[0].a, fk1)
+ self.assertIs(qs[0].b, None)
+
def test_disjunction_promotion1(self):
# Pre-existing join, add two ORed filters to the same join,
# all joins can be INNER JOINS.
@@ -2669,17 +2732,23 @@ class DisjunctionPromotionTests(TestCase):
self.assertEqual(str(qs.query).count('INNER JOIN'), 1)
self.assertEqual(str(qs.query).count('LEFT OUTER JOIN'), 1)
- def test_disjunction_promotion4(self):
+ @unittest.expectedFailure
+ def test_disjunction_promotion4_failing(self):
+ # Failure because no join repromotion
qs = BaseA.objects.filter(Q(a=1) | Q(a=2))
self.assertEqual(str(qs.query).count('JOIN'), 0)
qs = qs.filter(a__f1='foo')
self.assertEqual(str(qs.query).count('INNER JOIN'), 1)
+
+ def test_disjunction_promotion4(self):
qs = BaseA.objects.filter(a__f1='foo')
self.assertEqual(str(qs.query).count('INNER JOIN'), 1)
qs = qs.filter(Q(a=1) | Q(a=2))
self.assertEqual(str(qs.query).count('INNER JOIN'), 1)
- def test_disjunction_promotion5(self):
+ @unittest.expectedFailure
+ def test_disjunction_promotion5_failing(self):
+ # Failure because no join repromotion logic.
qs = BaseA.objects.filter(Q(a=1) | Q(a=2))
# Note that the above filters on a force the join to an
# inner join even if it is trimmed.
@@ -2688,15 +2757,10 @@ class DisjunctionPromotionTests(TestCase):
# So, now the a__f1 join doesn't need promotion.
self.assertEqual(str(qs.query).count('INNER JOIN'), 1)
self.assertEqual(str(qs.query).count('LEFT OUTER JOIN'), 1)
-
- @unittest.expectedFailure
- def test_disjunction_promotion5_failing(self):
qs = BaseA.objects.filter(Q(a__f1='foo') | Q(b__f1='foo'))
# Now the join to a is created as LOUTER
self.assertEqual(str(qs.query).count('LEFT OUTER JOIN'), 0)
- # The below filter should force the a to be inner joined. But,
- # this is failing as we do not have join unpromotion logic.
- qs = BaseA.objects.filter(Q(a=1) | Q(a=2))
+ qs = qs.objects.filter(Q(a=1) | Q(a=2))
self.assertEqual(str(qs.query).count('INNER JOIN'), 1)
self.assertEqual(str(qs.query).count('LEFT OUTER JOIN'), 1)
diff --git a/tests/queryset_pickle/models.py b/tests/queryset_pickle/models.py
index 4bcfcfbf04..3a8973505c 100644
--- a/tests/queryset_pickle/models.py
+++ b/tests/queryset_pickle/models.py
@@ -36,3 +36,13 @@ class Happening(models.Model):
number2 = models.IntegerField(blank=True, default=Numbers.get_static_number)
number3 = models.IntegerField(blank=True, default=Numbers.get_class_number)
number4 = models.IntegerField(blank=True, default=nn.get_member_number)
+
+class Container(object):
+ # To test pickling we need a class that isn't defined on module, but
+ # is still available from app-cache. So, the Container class moves
+ # SomeModel outside of module level
+ class SomeModel(models.Model):
+ somefield = models.IntegerField()
+
+class M2MModel(models.Model):
+ groups = models.ManyToManyField(Group)
diff --git a/tests/queryset_pickle/tests.py b/tests/queryset_pickle/tests.py
index da1bb8cb73..b4b540c80d 100644
--- a/tests/queryset_pickle/tests.py
+++ b/tests/queryset_pickle/tests.py
@@ -3,9 +3,10 @@ from __future__ import absolute_import
import pickle
import datetime
+from django.db import models
from django.test import TestCase
-from .models import Group, Event, Happening
+from .models import Group, Event, Happening, Container, M2MModel
class PickleabilityTestCase(TestCase):
@@ -49,3 +50,43 @@ class PickleabilityTestCase(TestCase):
# can't just use assertEqual(original, unpickled)
self.assertEqual(original.__class__, unpickled.__class__)
self.assertEqual(original.args, unpickled.args)
+
+ def test_model_pickle(self):
+ """
+ Test that a model not defined on module level is pickleable.
+ """
+ original = Container.SomeModel(pk=1)
+ dumped = pickle.dumps(original)
+ reloaded = pickle.loads(dumped)
+ self.assertEqual(original, reloaded)
+ # Also, deferred dynamic model works
+ Container.SomeModel.objects.create(somefield=1)
+ original = Container.SomeModel.objects.defer('somefield')[0]
+ dumped = pickle.dumps(original)
+ reloaded = pickle.loads(dumped)
+ self.assertEqual(original, reloaded)
+ self.assertEqual(original.somefield, reloaded.somefield)
+
+ def test_model_pickle_m2m(self):
+ """
+ Test intentionally the automatically created through model.
+ """
+ m1 = M2MModel.objects.create()
+ g1 = Group.objects.create(name='foof')
+ m1.groups.add(g1)
+ m2m_through = M2MModel._meta.get_field_by_name('groups')[0].rel.through
+ original = m2m_through.objects.get()
+ dumped = pickle.dumps(original)
+ reloaded = pickle.loads(dumped)
+ self.assertEqual(original, reloaded)
+
+ def test_model_pickle_dynamic(self):
+ class Meta:
+ proxy = True
+ dynclass = type("DynamicEventSubclass", (Event, ),
+ {'Meta': Meta, '__module__': Event.__module__})
+ original = dynclass(pk=1)
+ dumped = pickle.dumps(original)
+ reloaded = pickle.loads(dumped)
+ self.assertEqual(original, reloaded)
+ self.assertIs(reloaded.__class__, dynclass)
diff --git a/tests/requests/tests.py b/tests/requests/tests.py
index 4d730bb561..d9120db4e7 100644
--- a/tests/requests/tests.py
+++ b/tests/requests/tests.py
@@ -683,6 +683,8 @@ class RequestsTests(SimpleTestCase):
"Cannot establish two connections to an in-memory SQLite database.")
class DatabaseConnectionHandlingTests(TransactionTestCase):
+ available_apps = []
+
def setUp(self):
# Use a temporary connection to avoid messing with the main one.
self._old_default_connection = connections['default']
diff --git a/tests/runtests.py b/tests/runtests.py
index a18324f676..da4592ecc0 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -5,6 +5,7 @@ import shutil
import subprocess
import sys
import tempfile
+import warnings
from django import contrib
from django.utils._os import upath
@@ -29,7 +30,6 @@ SUBDIRS_TO_SKIP = [
]
ALWAYS_INSTALLED_APPS = [
- 'shared_models',
'django.contrib.contenttypes',
'django.contrib.auth',
'django.contrib.sites',
@@ -72,6 +72,15 @@ def get_installed():
def setup(verbosity, test_labels):
from django.conf import settings
from django.db.models.loading import get_apps, load_app
+ from django.test.testcases import TransactionTestCase, TestCase
+
+ # Force declaring available_apps in TransactionTestCase for faster tests.
+ def no_available_apps(self):
+ raise Exception("Please define available_apps in TransactionTestCase "
+ "and its subclasses.")
+ TransactionTestCase.available_apps = property(no_available_apps)
+ TestCase.available_apps = None
+
state = {
'INSTALLED_APPS': settings.INSTALLED_APPS,
'ROOT_URLCONF': getattr(settings, "ROOT_URLCONF", ""),
@@ -99,7 +108,9 @@ def setup(verbosity, test_labels):
logger.addHandler(handler)
# Load all the ALWAYS_INSTALLED_APPS.
- get_apps()
+ with warnings.catch_warnings():
+ warnings.filterwarnings('ignore', 'django.contrib.comments is deprecated and will be removed before Django 1.8.', PendingDeprecationWarning)
+ get_apps()
# Load all the test model apps.
test_modules = get_test_modules()
diff --git a/tests/select_for_update/tests.py b/tests/select_for_update/tests.py
index c2fa22705a..f087ca123a 100644
--- a/tests/select_for_update/tests.py
+++ b/tests/select_for_update/tests.py
@@ -23,6 +23,8 @@ requires_threading = unittest.skipUnless(threading, 'requires threading')
class SelectForUpdateTests(TransactionTestCase):
+ available_apps = ['select_for_update']
+
def setUp(self):
transaction.enter_transaction_management()
self.person = Person.objects.create(name='Reinhardt')
diff --git a/tests/serializers/tests.py b/tests/serializers/tests.py
index a96a1af748..038276ca21 100644
--- a/tests/serializers/tests.py
+++ b/tests/serializers/tests.py
@@ -259,6 +259,9 @@ class SerializersTestBase(object):
class SerializersTransactionTestBase(object):
+
+ available_apps = ['serializers']
+
def test_forward_refs(self):
"""
Tests that objects ids can be referenced before they are
diff --git a/tests/servers/tests.py b/tests/servers/tests.py
index 920149477c..3377793d68 100644
--- a/tests/servers/tests.py
+++ b/tests/servers/tests.py
@@ -30,8 +30,15 @@ TEST_SETTINGS = {
class LiveServerBase(LiveServerTestCase):
- urls = 'servers.urls'
+
+ available_apps = [
+ 'servers',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ ]
fixtures = ['testdata.json']
+ urls = 'servers.urls'
@classmethod
def setUpClass(cls):
diff --git a/tests/settings_tests/tests.py b/tests/settings_tests/tests.py
index 97e43ff0eb..f8d66bb2b7 100644
--- a/tests/settings_tests/tests.py
+++ b/tests/settings_tests/tests.py
@@ -12,6 +12,8 @@ from django.utils import unittest, six
@override_settings(TEST='override')
class FullyDecoratedTranTestCase(TransactionTestCase):
+ available_apps = []
+
def test_override(self):
self.assertEqual(settings.TEST, 'override')
diff --git a/tests/shared_models/models.py b/tests/shared_models/models.py
deleted file mode 100644
index 145edad1bf..0000000000
--- a/tests/shared_models/models.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from __future__ import unicode_literals
-
-from django.db import models
-from django.utils import timezone
-from django.utils.encoding import python_2_unicode_compatible
-
-
-class Tag(models.Model):
- name = models.CharField(max_length=255)
-
-
-@python_2_unicode_compatible
-class Author(models.Model):
- name = models.CharField(max_length=100, help_text='Use both first and last names.',
- unique=True)
-
- class Meta:
- ordering = ['name']
-
- def __str__(self):
- return self.name
-
-
-@python_2_unicode_compatible
-class Book(models.Model):
- title = models.CharField(max_length=200)
- pages = models.IntegerField(default=0)
- author = models.ForeignKey(Author, null=True, blank=True)
- pubdate = models.DateTimeField()
- tags = models.ManyToManyField(Tag)
-
- class Meta:
- ordering = ['-pubdate', 'title']
- unique_together = ['title', 'author']
-
- def __str__(self):
- return self.title
diff --git a/tests/signals_regress/models.py b/tests/signals_regress/models.py
index e69de29bb2..829314c06c 100644
--- a/tests/signals_regress/models.py
+++ b/tests/signals_regress/models.py
@@ -0,0 +1,18 @@
+from django.db import models
+from django.utils.encoding import python_2_unicode_compatible
+
+
+@python_2_unicode_compatible
+class Author(models.Model):
+ name = models.CharField(max_length=20)
+
+ def __str__(self):
+ return self.name
+
+@python_2_unicode_compatible
+class Book(models.Model):
+ name = models.CharField(max_length=20)
+ authors = models.ManyToManyField(Author)
+
+ def __str__(self):
+ return self.name
diff --git a/tests/signals_regress/tests.py b/tests/signals_regress/tests.py
index b806d2116e..8fb3ad5a48 100644
--- a/tests/signals_regress/tests.py
+++ b/tests/signals_regress/tests.py
@@ -3,7 +3,7 @@ from __future__ import absolute_import
from django.db import models
from django.test import TestCase
-from shared_models.models import Author, Book
+from .models import Author, Book
class SignalsRegressTests(TestCase):
@@ -77,7 +77,7 @@ class SignalsRegressTests(TestCase):
"Is created"
])
- b1 = Book(title='Snow Crash', pubdate='2012-02-02 12:00')
+ b1 = Book(name='Snow Crash')
self.assertEqual(self.get_signal_output(b1.save), [
"pre_save signal, Snow Crash",
"post_save signal, Snow Crash",
@@ -87,7 +87,7 @@ class SignalsRegressTests(TestCase):
def test_m2m_signals(self):
""" Assigning and removing to/from m2m shouldn't generate an m2m signal """
- b1 = Book(title='Snow Crash', pubdate='2012-02-02 12:00')
+ b1 = Book(name='Snow Crash')
self.get_signal_output(b1.save)
a1 = Author(name='Neal Stephenson')
self.get_signal_output(a1.save)
diff --git a/tests/swappable_models/tests.py b/tests/swappable_models/tests.py
index d3d61341d2..858061db23 100644
--- a/tests/swappable_models/tests.py
+++ b/tests/swappable_models/tests.py
@@ -13,6 +13,13 @@ from swappable_models.models import Article
class SwappableModelTests(TestCase):
+
+ available_apps = [
+ 'swappable_models',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ ]
+
def setUp(self):
# This test modifies the installed apps, so we need to make sure
# we're not dealing with a cached app list.
diff --git a/tests/syncdb_signals/tests.py b/tests/syncdb_signals/tests.py
index d9be3b65d4..d70fb2c2c0 100644
--- a/tests/syncdb_signals/tests.py
+++ b/tests/syncdb_signals/tests.py
@@ -3,7 +3,7 @@ from django.test import TestCase
from django.core import management
from django.utils import six
-from shared_models import models
+from . import models
PRE_SYNCDB_ARGS = ['app', 'create_models', 'verbosity', 'interactive', 'db']
@@ -55,6 +55,11 @@ signals.pre_syncdb.connect(pre_syncdb_receiver, sender=models)
class SyncdbSignalTests(TestCase):
+
+ available_apps = [
+ 'syncdb_signals',
+ ]
+
def test_pre_syncdb_call_time(self):
self.assertEqual(pre_syncdb_receiver.call_counter, 1)
diff --git a/tests/test_runner/tests.py b/tests/test_runner/tests.py
index 95ccf0242a..0dc7a0155a 100644
--- a/tests/test_runner/tests.py
+++ b/tests/test_runner/tests.py
@@ -9,9 +9,9 @@ from optparse import make_option
from django.core.exceptions import ImproperlyConfigured
from django.core.management import call_command
from django import db
-from django.test import runner, TransactionTestCase, skipUnlessDBFeature
-from django.test.simple import DjangoTestSuiteRunner, get_tests
+from django.test import runner, TestCase, TransactionTestCase, skipUnlessDBFeature
from django.test.testcases import connections_support_transactions
+from django.test.utils import IgnorePendingDeprecationWarningsMixin
from django.utils import unittest
from django.utils.importlib import import_module
@@ -225,20 +225,24 @@ class Ticket17477RegressionTests(AdminScriptTestCase):
self.assertNoOutput(err)
-class ModulesTestsPackages(unittest.TestCase):
+class ModulesTestsPackages(IgnorePendingDeprecationWarningsMixin, unittest.TestCase):
def test_get_tests(self):
"Check that the get_tests helper function can find tests in a directory"
+ from django.test.simple import get_tests
module = import_module(TEST_APP_OK)
tests = get_tests(module)
self.assertIsInstance(tests, type(module))
def test_import_error(self):
"Test for #12658 - Tests with ImportError's shouldn't fail silently"
+ from django.test.simple import get_tests
module = import_module(TEST_APP_ERROR)
self.assertRaises(ImportError, get_tests, module)
-class Sqlite3InMemoryTestDbs(unittest.TestCase):
+class Sqlite3InMemoryTestDbs(TestCase):
+
+ available_apps = []
@unittest.skipUnless(all(db.connections[conn].vendor == 'sqlite' for conn in db.connections),
"This is a sqlite-specific issue")
@@ -258,7 +262,7 @@ class Sqlite3InMemoryTestDbs(unittest.TestCase):
},
})
other = db.connections['other']
- DjangoTestSuiteRunner(verbosity=0).setup_databases()
+ runner.DiscoverRunner(verbosity=0).setup_databases()
msg = "DATABASES setting '%s' option set to sqlite3's ':memory:' value shouldn't interfere with transaction support detection." % option
# Transaction support should be properly initialised for the 'other' DB
self.assertTrue(other.features.supports_transactions, msg)
@@ -273,12 +277,12 @@ class DummyBackendTest(unittest.TestCase):
"""
Test that setup_databases() doesn't fail with dummy database backend.
"""
- runner = DjangoTestSuiteRunner(verbosity=0)
+ runner_instance = runner.DiscoverRunner(verbosity=0)
old_db_connections = db.connections
try:
db.connections = db.ConnectionHandler({})
- old_config = runner.setup_databases()
- runner.teardown_databases(old_config)
+ old_config = runner_instance.setup_databases()
+ runner_instance.teardown_databases(old_config)
except Exception as e:
self.fail("setup_databases/teardown_databases unexpectedly raised "
"an error: %s" % e)
@@ -318,6 +322,8 @@ class AutoIncrementResetTest(TransactionTestCase):
that AutoField values start from 1 for each transactional test case.
"""
+ available_apps = ['test_runner']
+
reset_sequences = True
@skipUnlessDBFeature('supports_sequence_reset')
diff --git a/tests/test_suite_override/tests.py b/tests/test_suite_override/tests.py
index dea110434f..35ca2b060b 100644
--- a/tests/test_suite_override/tests.py
+++ b/tests/test_suite_override/tests.py
@@ -1,5 +1,5 @@
from django.db.models import get_app
-from django.test.simple import build_suite
+from django.test.utils import IgnorePendingDeprecationWarningsMixin
from django.utils import unittest
@@ -9,7 +9,7 @@ def suite():
return testSuite
-class SuiteOverrideTest(unittest.TestCase):
+class SuiteOverrideTest(IgnorePendingDeprecationWarningsMixin, unittest.TestCase):
def test_suite_override(self):
"""
Validate that you can define a custom suite when running tests with
@@ -17,6 +17,7 @@ class SuiteOverrideTest(unittest.TestCase):
suite using ``build_suite``).
"""
+ from django.test.simple import build_suite
app = get_app("test_suite_override")
suite = build_suite(app)
self.assertEqual(suite.countTestCases(), 1)
diff --git a/tests/test_utils/tests.py b/tests/test_utils/tests.py
index d72a482819..5f7fb05eb4 100644
--- a/tests/test_utils/tests.py
+++ b/tests/test_utils/tests.py
@@ -8,8 +8,7 @@ from django.http import HttpResponse
from django.template.loader import render_to_string
from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature
from django.test.html import HTMLParseError, parse_html
-from django.test.simple import make_doctest
-from django.test.utils import CaptureQueriesContext
+from django.test.utils import CaptureQueriesContext, IgnorePendingDeprecationWarningsMixin
from django.utils import six
from django.utils import unittest
from django.utils.unittest import skip
@@ -624,9 +623,10 @@ class AssertFieldOutputTests(SimpleTestCase):
self.assertFieldOutput(MyCustomField, {}, {}, empty_value=None)
-class DoctestNormalizerTest(SimpleTestCase):
+class DoctestNormalizerTest(IgnorePendingDeprecationWarningsMixin, SimpleTestCase):
def test_normalizer(self):
+ from django.test.simple import make_doctest
suite = make_doctest("test_utils.doctest_output")
failures = unittest.TextTestRunner(stream=six.StringIO()).run(suite)
self.assertEqual(failures.failures, [])
diff --git a/tests/transactions/tests.py b/tests/transactions/tests.py
index 0f16a9c805..24b7615d6f 100644
--- a/tests/transactions/tests.py
+++ b/tests/transactions/tests.py
@@ -26,6 +26,8 @@ class AtomicTests(TransactionTestCase):
syntax and the bulk of the tests use the context manager syntax.
"""
+ available_apps = ['transactions']
+
def test_decorator_syntax_commit(self):
@transaction.atomic
def make_reporter():
@@ -232,6 +234,8 @@ class AtomicInsideLegacyTransactionManagementTests(AtomicTests):
class AtomicMergeTests(TransactionTestCase):
"""Test merging transactions with savepoint=False."""
+ available_apps = ['transactions']
+
def test_merged_outer_rollback(self):
with transaction.atomic():
Reporter.objects.create(first_name="Tintin")
@@ -286,6 +290,8 @@ class AtomicMergeTests(TransactionTestCase):
"'atomic' requires transactions and savepoints.")
class AtomicErrorsTests(TransactionTestCase):
+ available_apps = []
+
def test_atomic_prevents_setting_autocommit(self):
autocommit = transaction.get_autocommit()
with transaction.atomic():
@@ -311,6 +317,8 @@ class AtomicErrorsTests(TransactionTestCase):
class AtomicMiscTests(TransactionTestCase):
+ available_apps = []
+
def test_wrap_callable_instance(self):
# Regression test for #20028
class Callable(object):
@@ -322,6 +330,8 @@ class AtomicMiscTests(TransactionTestCase):
class TransactionTests(IgnorePendingDeprecationWarningsMixin, TransactionTestCase):
+ available_apps = ['transactions']
+
def create_a_reporter_then_fail(self, first, last):
a = Reporter(first_name=first, last_name=last)
a.save()
@@ -477,6 +487,9 @@ class TransactionTests(IgnorePendingDeprecationWarningsMixin, TransactionTestCas
class TransactionRollbackTests(IgnorePendingDeprecationWarningsMixin, TransactionTestCase):
+
+ available_apps = ['transactions']
+
def execute_bad_sql(self):
cursor = connection.cursor()
cursor.execute("INSERT INTO transactions_reporter (first_name, last_name) VALUES ('Douglas', 'Adams');")
@@ -494,6 +507,9 @@ class TransactionRollbackTests(IgnorePendingDeprecationWarningsMixin, Transactio
transaction.rollback()
class TransactionContextManagerTests(IgnorePendingDeprecationWarningsMixin, TransactionTestCase):
+
+ available_apps = ['transactions']
+
def create_reporter_and_fail(self):
Reporter.objects.create(first_name="Bob", last_name="Holtzman")
raise Exception
diff --git a/tests/transactions_regress/tests.py b/tests/transactions_regress/tests.py
index 5339b4a8ea..8078f1d128 100644
--- a/tests/transactions_regress/tests.py
+++ b/tests/transactions_regress/tests.py
@@ -10,6 +10,9 @@ from django.utils.unittest import skipIf, skipUnless
from .models import Mod, M2mA, M2mB, SubMod
class ModelInheritanceTests(TransactionTestCase):
+
+ available_apps = ['transactions_regress']
+
def test_save(self):
# First, create a SubMod, then try to save another with conflicting
# cnt field. The problem was that transactions were committed after
@@ -33,6 +36,13 @@ class TestTransactionClosing(IgnorePendingDeprecationWarningsMixin, TransactionT
when they should be, and aren't left pending after operations
have been performed in them. Refs #9964.
"""
+
+ available_apps = [
+ 'transactions_regress',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ ]
+
def test_raw_committed_on_success(self):
"""
Make sure a transaction consisting of raw SQL execution gets
@@ -188,6 +198,9 @@ class TestNewConnection(IgnorePendingDeprecationWarningsMixin, TransactionTestCa
"""
Check that new connections don't have special behaviour.
"""
+
+ available_apps = ['transactions_regress']
+
def setUp(self):
self._old_backend = connections[DEFAULT_DB_ALIAS]
settings = self._old_backend.settings_dict.copy()
@@ -235,6 +248,9 @@ class TestPostgresAutocommitAndIsolation(IgnorePendingDeprecationWarningsMixin,
is restored after entering and leaving transaction management.
Refs #16047, #18130.
"""
+
+ available_apps = ['transactions_regress']
+
def setUp(self):
from psycopg2.extensions import (ISOLATION_LEVEL_AUTOCOMMIT,
ISOLATION_LEVEL_SERIALIZABLE,
@@ -311,6 +327,9 @@ class TestPostgresAutocommitAndIsolation(IgnorePendingDeprecationWarningsMixin,
class TestManyToManyAddTransaction(IgnorePendingDeprecationWarningsMixin, TransactionTestCase):
+
+ available_apps = ['transactions_regress']
+
def test_manyrelated_add_commit(self):
"Test for https://code.djangoproject.com/ticket/16818"
a = M2mA.objects.create()
@@ -327,6 +346,8 @@ class TestManyToManyAddTransaction(IgnorePendingDeprecationWarningsMixin, Transa
class SavepointTest(IgnorePendingDeprecationWarningsMixin, TransactionTestCase):
+ available_apps = ['transactions_regress']
+
@skipIf(connection.vendor == 'sqlite',
"SQLite doesn't support savepoints in managed mode")
@skipUnlessDBFeature('uses_savepoints')
diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py
index f54c796d30..3962f69288 100644
--- a/tests/urlpatterns_reverse/tests.py
+++ b/tests/urlpatterns_reverse/tests.py
@@ -192,6 +192,20 @@ class URLPatternReverse(TestCase):
self.assertEqual('/%7Eme/places/1/',
reverse('places', args=[1], prefix='/~me/'))
+ def test_patterns_reported(self):
+ # Regression for #17076
+ try:
+ # this url exists, but requires an argument
+ reverse("people", args=[])
+ except NoReverseMatch as e:
+ pattern_description = r"1 pattern(s) tried: ['people/(?P<name>\\w+)/$']"
+ self.assertIn(pattern_description, str(e))
+ else:
+ # we can't use .assertRaises, since we want to inspect the
+ # exception
+ self.fail("Expected a NoReverseMatch, but none occurred.")
+
+
class ResolverTests(unittest.TestCase):
def test_resolver_repr(self):
"""
diff --git a/tests/validation/models.py b/tests/validation/models.py
index e95a1e0744..958740dd2d 100644
--- a/tests/validation/models.py
+++ b/tests/validation/models.py
@@ -19,6 +19,7 @@ class ModelToValidate(models.Model):
email = models.EmailField(blank=True)
url = models.URLField(blank=True)
f_with_custom_validator = models.IntegerField(blank=True, null=True, validators=[validate_answer_to_universe])
+ slug = models.SlugField(blank=True)
def clean(self):
super(ModelToValidate, self).clean()
diff --git a/tests/validation/tests.py b/tests/validation/tests.py
index 9ddf796c2b..c8b679541a 100644
--- a/tests/validation/tests.py
+++ b/tests/validation/tests.py
@@ -53,7 +53,11 @@ class BaseModelValidationTests(ValidationTestCase):
def test_text_greater_that_charfields_max_length_raises_erros(self):
mtv = ModelToValidate(number=10, name='Some Name'*100)
- self.assertFailsValidation(mtv.full_clean, ['name',])
+ self.assertFailsValidation(mtv.full_clean, ['name'])
+
+ def test_malformed_slug_raises_error(self):
+ mtv = ModelToValidate(number=10, name='Some Name', slug='##invalid##')
+ self.assertFailsValidation(mtv.full_clean, ['slug'])
class ArticleForm(forms.ModelForm):
diff --git a/tests/validators/tests.py b/tests/validators/tests.py
index 6b46c53cc3..a1555d8e91 100644
--- a/tests/validators/tests.py
+++ b/tests/validators/tests.py
@@ -213,9 +213,9 @@ class TestSimpleValidators(TestCase):
self.assertEqual(repr(v), str_prefix("ValidationError([%(_)s'First Problem', %(_)s'Second Problem'])"))
def test_message_dict(self):
- v = ValidationError({'first': 'First Problem'})
- self.assertEqual(str(v), str_prefix("{%(_)s'first': %(_)s'First Problem'}"))
- self.assertEqual(repr(v), str_prefix("ValidationError({%(_)s'first': %(_)s'First Problem'})"))
+ v = ValidationError({'first': ['First Problem']})
+ self.assertEqual(str(v), str_prefix("{%(_)s'first': [%(_)s'First Problem']}"))
+ self.assertEqual(repr(v), str_prefix("ValidationError({%(_)s'first': [%(_)s'First Problem']})"))
test_counter = 0
for validator, value, expected in TEST_DATA:
diff --git a/tests/view_tests/tests/test_i18n.py b/tests/view_tests/tests/test_i18n.py
index 2da17dd0f5..b35b192fd0 100644
--- a/tests/view_tests/tests/test_i18n.py
+++ b/tests/view_tests/tests/test_i18n.py
@@ -183,6 +183,8 @@ skip_selenium = not os.environ.get('DJANGO_SELENIUM_TESTS', False)
@unittest.skipIf(skip_selenium, 'Selenium tests not requested')
@unittest.skipUnless(firefox, 'Selenium not installed')
class JavascriptI18nTests(LiveServerTestCase):
+
+ available_apps = []
urls = 'view_tests.urls'
@classmethod