diff options
author | django-bot <ops@djangoproject.com> | 2022-02-03 20:24:19 +0100 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-02-07 20:37:05 +0100 |
commit | 9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch) | |
tree | f0506b668a013d0063e5fba3dbf4863b466713ba /tests/generic_views | |
parent | f68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff) | |
download | django-9c19aff7c7561e3a82978a272ecdaad40dda5c00.tar.gz |
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'tests/generic_views')
-rw-r--r-- | tests/generic_views/forms.py | 6 | ||||
-rw-r--r-- | tests/generic_views/models.py | 12 | ||||
-rw-r--r-- | tests/generic_views/test_base.py | 301 | ||||
-rw-r--r-- | tests/generic_views/test_dates.py | 766 | ||||
-rw-r--r-- | tests/generic_views/test_detail.py | 207 | ||||
-rw-r--r-- | tests/generic_views/test_edit.py | 401 | ||||
-rw-r--r-- | tests/generic_views/test_list.py | 256 | ||||
-rw-r--r-- | tests/generic_views/urls.py | 476 | ||||
-rw-r--r-- | tests/generic_views/views.py | 120 |
9 files changed, 1465 insertions, 1080 deletions
diff --git a/tests/generic_views/forms.py b/tests/generic_views/forms.py index 7d07dbc576..08bc07da8e 100644 --- a/tests/generic_views/forms.py +++ b/tests/generic_views/forms.py @@ -9,7 +9,7 @@ class AuthorForm(forms.ModelForm): class Meta: model = Author - fields = ['name', 'slug'] + fields = ["name", "slug"] class ContactForm(forms.Form): @@ -22,5 +22,5 @@ class ConfirmDeleteForm(forms.Form): def clean(self): cleaned_data = super().clean() - if 'confirm' not in cleaned_data: - raise forms.ValidationError('You must confirm the delete.') + if "confirm" not in cleaned_data: + raise forms.ValidationError("You must confirm the delete.") diff --git a/tests/generic_views/models.py b/tests/generic_views/models.py index 5733e44093..aef0ae23f5 100644 --- a/tests/generic_views/models.py +++ b/tests/generic_views/models.py @@ -8,15 +8,15 @@ class Artist(models.Model): name = models.CharField(max_length=100) class Meta: - ordering = ['name'] - verbose_name = 'professional artist' - verbose_name_plural = 'professional artists' + ordering = ["name"] + verbose_name = "professional artist" + verbose_name_plural = "professional artists" def __str__(self): return self.name def get_absolute_url(self): - return reverse('artist_detail', kwargs={'pk': self.id}) + return reverse("artist_detail", kwargs={"pk": self.id}) class Author(models.Model): @@ -24,7 +24,7 @@ class Author(models.Model): slug = models.SlugField() class Meta: - ordering = ['name'] + ordering = ["name"] def __str__(self): return self.name @@ -49,7 +49,7 @@ class Book(models.Model): does_not_exist = DoesNotExistBookManager() class Meta: - ordering = ['-pubdate'] + ordering = ["-pubdate"] def __str__(self): return self.name diff --git a/tests/generic_views/test_base.py b/tests/generic_views/test_base.py index 95b03681cc..b139d1089b 100644 --- a/tests/generic_views/test_base.py +++ b/tests/generic_views/test_base.py @@ -14,8 +14,9 @@ class SimpleView(View): """ A simple view with a docstring. """ + def get(self, request): - return HttpResponse('This is a simple view') + return HttpResponse("This is a simple view") class SimplePostView(SimpleView): @@ -24,7 +25,7 @@ class SimplePostView(SimpleView): class PostOnlyView(View): def post(self, request): - return HttpResponse('This view only accepts POST') + return HttpResponse("This view only accepts POST") class CustomizableView(SimpleView): @@ -37,7 +38,6 @@ def decorator(view): class DecoratedDispatchView(SimpleView): - @decorator def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) @@ -48,18 +48,17 @@ class AboutTemplateView(TemplateView): return self.render_to_response({}) def get_template_names(self): - return ['generic_views/about.html'] + return ["generic_views/about.html"] class AboutTemplateAttributeView(TemplateView): - template_name = 'generic_views/about.html' + template_name = "generic_views/about.html" def get(self, request): return self.render_to_response(context={}) class InstanceView(View): - def get(self, request): return self @@ -69,74 +68,81 @@ class ViewTest(SimpleTestCase): def _assert_simple(self, response): self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, b'This is a simple view') + self.assertEqual(response.content, b"This is a simple view") def test_no_init_kwargs(self): """ A view can't be accidentally instantiated before deployment """ - msg = 'This method is available only on the class, not on instances.' + msg = "This method is available only on the class, not on instances." with self.assertRaisesMessage(AttributeError, msg): - SimpleView(key='value').as_view() + SimpleView(key="value").as_view() def test_no_init_args(self): """ A view can't be accidentally instantiated before deployment """ - msg = 'as_view() takes 1 positional argument but 2 were given' + msg = "as_view() takes 1 positional argument but 2 were given" with self.assertRaisesMessage(TypeError, msg): - SimpleView.as_view('value') + SimpleView.as_view("value") def test_pathological_http_method(self): """ The edge case of an HTTP request that spoofs an existing method name is caught. """ - self.assertEqual(SimpleView.as_view()( - self.rf.get('/', REQUEST_METHOD='DISPATCH') - ).status_code, 405) + self.assertEqual( + SimpleView.as_view()( + self.rf.get("/", REQUEST_METHOD="DISPATCH") + ).status_code, + 405, + ) def test_get_only(self): """ Test a view which only allows GET doesn't allow other methods. """ - self._assert_simple(SimpleView.as_view()(self.rf.get('/'))) - self.assertEqual(SimpleView.as_view()(self.rf.post('/')).status_code, 405) - self.assertEqual(SimpleView.as_view()( - self.rf.get('/', REQUEST_METHOD='FAKE') - ).status_code, 405) + self._assert_simple(SimpleView.as_view()(self.rf.get("/"))) + self.assertEqual(SimpleView.as_view()(self.rf.post("/")).status_code, 405) + self.assertEqual( + SimpleView.as_view()(self.rf.get("/", REQUEST_METHOD="FAKE")).status_code, + 405, + ) def test_get_and_head(self): """ Test a view which supplies a GET method also responds correctly to HEAD. """ - self._assert_simple(SimpleView.as_view()(self.rf.get('/'))) - response = SimpleView.as_view()(self.rf.head('/')) + self._assert_simple(SimpleView.as_view()(self.rf.get("/"))) + response = SimpleView.as_view()(self.rf.head("/")) self.assertEqual(response.status_code, 200) def test_setup_get_and_head(self): view_instance = SimpleView() - self.assertFalse(hasattr(view_instance, 'head')) - view_instance.setup(self.rf.get('/')) - self.assertTrue(hasattr(view_instance, 'head')) + self.assertFalse(hasattr(view_instance, "head")) + view_instance.setup(self.rf.get("/")) + self.assertTrue(hasattr(view_instance, "head")) self.assertEqual(view_instance.head, view_instance.get) def test_head_no_get(self): """ Test a view which supplies no GET method responds to HEAD with HTTP 405. """ - response = PostOnlyView.as_view()(self.rf.head('/')) + response = PostOnlyView.as_view()(self.rf.head("/")) self.assertEqual(response.status_code, 405) def test_get_and_post(self): """ Test a view which only allows both GET and POST. """ - self._assert_simple(SimplePostView.as_view()(self.rf.get('/'))) - self._assert_simple(SimplePostView.as_view()(self.rf.post('/'))) - self.assertEqual(SimplePostView.as_view()( - self.rf.get('/', REQUEST_METHOD='FAKE') - ).status_code, 405) + self._assert_simple(SimplePostView.as_view()(self.rf.get("/"))) + self._assert_simple(SimplePostView.as_view()(self.rf.post("/"))) + self.assertEqual( + SimplePostView.as_view()( + self.rf.get("/", REQUEST_METHOD="FAKE") + ).status_code, + 405, + ) def test_invalid_keyword_argument(self): """ @@ -144,13 +150,13 @@ class ViewTest(SimpleTestCase): be named like an HTTP method. """ msg = ( - 'The method name %s is not accepted as a keyword argument to ' - 'SimpleView().' + "The method name %s is not accepted as a keyword argument to " + "SimpleView()." ) # Check each of the allowed method names for method in SimpleView.http_method_names: with self.assertRaisesMessage(TypeError, msg % method): - SimpleView.as_view(**{method: 'value'}) + SimpleView.as_view(**{method: "value"}) # Check the case view argument is ok if predefined on the class... CustomizableView.as_view(parameter="value") @@ -167,7 +173,7 @@ class ViewTest(SimpleTestCase): """ Test a view can only be called once. """ - request = self.rf.get('/') + request = self.rf.get("/") view = InstanceView.as_view() self.assertNotEqual(view(request), view(request)) @@ -178,11 +184,11 @@ class ViewTest(SimpleTestCase): cls = SimpleView view = cls.as_view() self.assertEqual(view.__doc__, cls.__doc__) - self.assertEqual(view.__name__, 'view') + self.assertEqual(view.__name__, "view") self.assertEqual(view.__module__, cls.__module__) - self.assertEqual(view.__qualname__, f'{cls.as_view.__qualname__}.<locals>.view') + self.assertEqual(view.__qualname__, f"{cls.as_view.__qualname__}.<locals>.view") self.assertEqual(view.__annotations__, cls.dispatch.__annotations__) - self.assertFalse(hasattr(view, '__wrapped__')) + self.assertFalse(hasattr(view, "__wrapped__")) def test_dispatch_decoration(self): """ @@ -196,43 +202,43 @@ class ViewTest(SimpleTestCase): Views respond to HTTP OPTIONS requests with an Allow header appropriate for the methods implemented by the view class. """ - request = self.rf.options('/') + request = self.rf.options("/") view = SimpleView.as_view() response = view(request) self.assertEqual(200, response.status_code) - self.assertTrue(response.headers['Allow']) + self.assertTrue(response.headers["Allow"]) def test_options_for_get_view(self): """ A view implementing GET allows GET and HEAD. """ - request = self.rf.options('/') + request = self.rf.options("/") view = SimpleView.as_view() response = view(request) - self._assert_allows(response, 'GET', 'HEAD') + self._assert_allows(response, "GET", "HEAD") def test_options_for_get_and_post_view(self): """ A view implementing GET and POST allows GET, HEAD, and POST. """ - request = self.rf.options('/') + request = self.rf.options("/") view = SimplePostView.as_view() response = view(request) - self._assert_allows(response, 'GET', 'HEAD', 'POST') + self._assert_allows(response, "GET", "HEAD", "POST") def test_options_for_post_view(self): """ A view implementing POST allows POST. """ - request = self.rf.options('/') + request = self.rf.options("/") view = PostOnlyView.as_view() response = view(request) - self._assert_allows(response, 'POST') + self._assert_allows(response, "POST") def _assert_allows(self, response, *expected_methods): "Assert allowed HTTP methods reported in the Allow response header" - response_allows = set(response.headers['Allow'].split(', ')) - self.assertEqual(set(expected_methods + ('OPTIONS',)), response_allows) + response_allows = set(response.headers["Allow"].split(", ")) + self.assertEqual(set(expected_methods + ("OPTIONS",)), response_allows) def test_args_kwargs_request_on_self(self): """ @@ -240,8 +246,8 @@ class ViewTest(SimpleTestCase): has been called. """ bare_view = InstanceView() - view = InstanceView.as_view()(self.rf.get('/')) - for attribute in ('args', 'kwargs', 'request'): + view = InstanceView.as_view()(self.rf.get("/")) + for attribute in ("args", "kwargs", "request"): self.assertNotIn(attribute, dir(bare_view)) self.assertIn(attribute, dir(view)) @@ -253,10 +259,10 @@ class ViewTest(SimpleTestCase): class CheckSetupView(SetAttributeMixin, SimpleView): def dispatch(self, request, *args, **kwargs): - assert hasattr(self, 'attr') + assert hasattr(self, "attr") return super().dispatch(request, *args, **kwargs) - response = CheckSetupView.as_view()(self.rf.get('/')) + response = CheckSetupView.as_view()(self.rf.get("/")) self.assertEqual(response.status_code, 200) def test_not_calling_parent_setup_error(self): @@ -269,12 +275,12 @@ class ViewTest(SimpleTestCase): "setup() and forget to call super()?" ) with self.assertRaisesMessage(AttributeError, msg): - TestView.as_view()(self.rf.get('/')) + TestView.as_view()(self.rf.get("/")) def test_setup_adds_args_kwargs_request(self): - request = self.rf.get('/') - args = ('arg 1', 'arg 2') - kwargs = {'kwarg_1': 1, 'kwarg_2': 'year'} + request = self.rf.get("/") + args = ("arg 1", "arg 2") + kwargs = {"kwarg_1": 1, "kwarg_2": "year"} view = View() view.setup(request, *args, **kwargs) @@ -288,30 +294,30 @@ class ViewTest(SimpleTestCase): without going through .as_view() (#21564). """ view = PostOnlyView() - response = view.dispatch(self.rf.head('/')) + response = view.dispatch(self.rf.head("/")) self.assertEqual(response.status_code, 405) -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class TemplateViewTest(SimpleTestCase): rf = RequestFactory() def _assert_about(self, response): response.render() - self.assertContains(response, '<h1>About</h1>') + self.assertContains(response, "<h1>About</h1>") def test_get(self): """ Test a view that simply renders a template on GET """ - self._assert_about(AboutTemplateView.as_view()(self.rf.get('/about/'))) + self._assert_about(AboutTemplateView.as_view()(self.rf.get("/about/"))) def test_head(self): """ Test a TemplateView responds correctly to HEAD """ - response = AboutTemplateView.as_view()(self.rf.head('/about/')) + response = AboutTemplateView.as_view()(self.rf.head("/about/")) self.assertEqual(response.status_code, 200) def test_get_template_attribute(self): @@ -319,14 +325,18 @@ class TemplateViewTest(SimpleTestCase): Test a view that renders a template on GET with the template name as an attribute on the class. """ - self._assert_about(AboutTemplateAttributeView.as_view()(self.rf.get('/about/'))) + self._assert_about(AboutTemplateAttributeView.as_view()(self.rf.get("/about/"))) def test_get_generic_template(self): """ Test a completely generic view that renders a template on GET with the template name as an argument at instantiation. """ - self._assert_about(TemplateView.as_view(template_name='generic_views/about.html')(self.rf.get('/about/'))) + self._assert_about( + TemplateView.as_view(template_name="generic_views/about.html")( + self.rf.get("/about/") + ) + ) def test_template_name_required(self): """ @@ -337,50 +347,54 @@ class TemplateViewTest(SimpleTestCase): "'template_name' or an implementation of 'get_template_names()'" ) with self.assertRaisesMessage(ImproperlyConfigured, msg): - self.client.get('/template/no_template/') + self.client.get("/template/no_template/") @require_jinja2 def test_template_engine(self): """ A template view may provide a template engine. """ - request = self.rf.get('/using/') - view = TemplateView.as_view(template_name='generic_views/using.html') - self.assertEqual(view(request).render().content, b'DTL\n') - view = TemplateView.as_view(template_name='generic_views/using.html', template_engine='django') - self.assertEqual(view(request).render().content, b'DTL\n') - view = TemplateView.as_view(template_name='generic_views/using.html', template_engine='jinja2') - self.assertEqual(view(request).render().content, b'Jinja2\n') + request = self.rf.get("/using/") + view = TemplateView.as_view(template_name="generic_views/using.html") + self.assertEqual(view(request).render().content, b"DTL\n") + view = TemplateView.as_view( + template_name="generic_views/using.html", template_engine="django" + ) + self.assertEqual(view(request).render().content, b"DTL\n") + view = TemplateView.as_view( + template_name="generic_views/using.html", template_engine="jinja2" + ) + self.assertEqual(view(request).render().content, b"Jinja2\n") def test_template_params(self): """ A generic template view passes kwargs as context. """ - response = self.client.get('/template/simple/bar/') + response = self.client.get("/template/simple/bar/") self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['foo'], 'bar') - self.assertIsInstance(response.context['view'], View) + self.assertEqual(response.context["foo"], "bar") + self.assertIsInstance(response.context["view"], View) def test_extra_template_params(self): """ A template view can be customized to return extra context. """ - response = self.client.get('/template/custom/bar/') + response = self.client.get("/template/custom/bar/") self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['foo'], 'bar') - self.assertEqual(response.context['key'], 'value') - self.assertIsInstance(response.context['view'], View) + self.assertEqual(response.context["foo"], "bar") + self.assertEqual(response.context["key"], "value") + self.assertIsInstance(response.context["view"], View) def test_cached_views(self): """ A template view can be cached """ - response = self.client.get('/template/cached/bar/') + response = self.client.get("/template/cached/bar/") self.assertEqual(response.status_code, 200) time.sleep(1.0) - response2 = self.client.get('/template/cached/bar/') + response2 = self.client.get("/template/cached/bar/") self.assertEqual(response2.status_code, 200) self.assertEqual(response.content, response2.content) @@ -388,131 +402,144 @@ class TemplateViewTest(SimpleTestCase): time.sleep(2.0) # Let the cache expire and test again - response2 = self.client.get('/template/cached/bar/') + response2 = self.client.get("/template/cached/bar/") self.assertEqual(response2.status_code, 200) self.assertNotEqual(response.content, response2.content) def test_content_type(self): - response = self.client.get('/template/content_type/') - self.assertEqual(response.headers['Content-Type'], 'text/plain') + response = self.client.get("/template/content_type/") + self.assertEqual(response.headers["Content-Type"], "text/plain") def test_resolve_view(self): - match = resolve('/template/content_type/') + match = resolve("/template/content_type/") self.assertIs(match.func.view_class, TemplateView) - self.assertEqual(match.func.view_initkwargs['content_type'], 'text/plain') + self.assertEqual(match.func.view_initkwargs["content_type"], "text/plain") def test_resolve_login_required_view(self): - match = resolve('/template/login_required/') + match = resolve("/template/login_required/") self.assertIs(match.func.view_class, TemplateView) def test_extra_context(self): - response = self.client.get('/template/extra_context/') - self.assertEqual(response.context['title'], 'Title') + response = self.client.get("/template/extra_context/") + self.assertEqual(response.context["title"], "Title") -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class RedirectViewTest(SimpleTestCase): rf = RequestFactory() def test_no_url(self): "Without any configuration, returns HTTP 410 GONE" - response = RedirectView.as_view()(self.rf.get('/foo/')) + response = RedirectView.as_view()(self.rf.get("/foo/")) self.assertEqual(response.status_code, 410) def test_default_redirect(self): "Default is a temporary redirect" - response = RedirectView.as_view(url='/bar/')(self.rf.get('/foo/')) + response = RedirectView.as_view(url="/bar/")(self.rf.get("/foo/")) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") def test_permanent_redirect(self): "Permanent redirects are an option" - response = RedirectView.as_view(url='/bar/', permanent=True)(self.rf.get('/foo/')) + response = RedirectView.as_view(url="/bar/", permanent=True)( + self.rf.get("/foo/") + ) self.assertEqual(response.status_code, 301) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") def test_temporary_redirect(self): "Temporary redirects are an option" - response = RedirectView.as_view(url='/bar/', permanent=False)(self.rf.get('/foo/')) + response = RedirectView.as_view(url="/bar/", permanent=False)( + self.rf.get("/foo/") + ) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") def test_include_args(self): "GET arguments can be included in the redirected URL" - response = RedirectView.as_view(url='/bar/')(self.rf.get('/foo/')) + response = RedirectView.as_view(url="/bar/")(self.rf.get("/foo/")) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") - response = RedirectView.as_view(url='/bar/', query_string=True)(self.rf.get('/foo/?pork=spam')) + response = RedirectView.as_view(url="/bar/", query_string=True)( + self.rf.get("/foo/?pork=spam") + ) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/?pork=spam') + self.assertEqual(response.url, "/bar/?pork=spam") def test_include_urlencoded_args(self): "GET arguments can be URL-encoded when included in the redirected URL" - response = RedirectView.as_view(url='/bar/', query_string=True)( - self.rf.get('/foo/?unicode=%E2%9C%93')) + response = RedirectView.as_view(url="/bar/", query_string=True)( + self.rf.get("/foo/?unicode=%E2%9C%93") + ) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/?unicode=%E2%9C%93') + self.assertEqual(response.url, "/bar/?unicode=%E2%9C%93") def test_parameter_substitution(self): "Redirection URLs can be parameterized" - response = RedirectView.as_view(url='/bar/%(object_id)d/')(self.rf.get('/foo/42/'), object_id=42) + response = RedirectView.as_view(url="/bar/%(object_id)d/")( + self.rf.get("/foo/42/"), object_id=42 + ) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/42/') + 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) + response = RedirectView.as_view(pattern_name="artist_detail")( + self.rf.get("/foo/"), pk=1 + ) self.assertEqual(response.status_code, 302) - self.assertEqual(response.headers['Location'], '/detail/artist/1/') + self.assertEqual(response.headers["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) + response = RedirectView.as_view(pattern_name="artist_detail")( + self.rf.get("/foo/"), 1 + ) self.assertEqual(response.status_code, 302) - self.assertEqual(response.headers['Location'], '/detail/artist/1/') + self.assertEqual(response.headers["Location"], "/detail/artist/1/") def test_redirect_POST(self): "Default is a temporary redirect" - response = RedirectView.as_view(url='/bar/')(self.rf.post('/foo/')) + response = RedirectView.as_view(url="/bar/")(self.rf.post("/foo/")) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") def test_redirect_HEAD(self): "Default is a temporary redirect" - response = RedirectView.as_view(url='/bar/')(self.rf.head('/foo/')) + response = RedirectView.as_view(url="/bar/")(self.rf.head("/foo/")) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") def test_redirect_OPTIONS(self): "Default is a temporary redirect" - response = RedirectView.as_view(url='/bar/')(self.rf.options('/foo/')) + response = RedirectView.as_view(url="/bar/")(self.rf.options("/foo/")) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") def test_redirect_PUT(self): "Default is a temporary redirect" - response = RedirectView.as_view(url='/bar/')(self.rf.put('/foo/')) + response = RedirectView.as_view(url="/bar/")(self.rf.put("/foo/")) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") def test_redirect_PATCH(self): "Default is a temporary redirect" - response = RedirectView.as_view(url='/bar/')(self.rf.patch('/foo/')) + response = RedirectView.as_view(url="/bar/")(self.rf.patch("/foo/")) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") def test_redirect_DELETE(self): "Default is a temporary redirect" - response = RedirectView.as_view(url='/bar/')(self.rf.delete('/foo/')) + response = RedirectView.as_view(url="/bar/")(self.rf.delete("/foo/")) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, '/bar/') + self.assertEqual(response.url, "/bar/") def test_redirect_when_meta_contains_no_query_string(self): "regression for #16705" # we can't use self.rf.get because it always sets QUERY_STRING - response = RedirectView.as_view(url='/bar/')(self.rf.request(PATH_INFO='/foo/')) + response = RedirectView.as_view(url="/bar/")(self.rf.request(PATH_INFO="/foo/")) self.assertEqual(response.status_code, 302) def test_direct_instantiation(self): @@ -521,37 +548,36 @@ class RedirectViewTest(SimpleTestCase): (#21564). """ view = RedirectView() - response = view.dispatch(self.rf.head('/foo/')) + response = view.dispatch(self.rf.head("/foo/")) self.assertEqual(response.status_code, 410) class GetContextDataTest(SimpleTestCase): - def test_get_context_data_super(self): test_view = views.CustomContextView() - context = test_view.get_context_data(kwarg_test='kwarg_value') + context = test_view.get_context_data(kwarg_test="kwarg_value") # the test_name key is inserted by the test classes parent - self.assertIn('test_name', context) - self.assertEqual(context['kwarg_test'], 'kwarg_value') - self.assertEqual(context['custom_key'], 'custom_value') + self.assertIn("test_name", context) + self.assertEqual(context["kwarg_test"], "kwarg_value") + self.assertEqual(context["custom_key"], "custom_value") # test that kwarg overrides values assigned higher up - context = test_view.get_context_data(test_name='test_value') - self.assertEqual(context['test_name'], 'test_value') + context = test_view.get_context_data(test_name="test_value") + self.assertEqual(context["test_name"], "test_value") def test_object_at_custom_name_in_context_data(self): # Checks 'pony' key presence in dict returned by get_context_date test_view = views.CustomSingleObjectView() - test_view.context_object_name = 'pony' + test_view.context_object_name = "pony" context = test_view.get_context_data() - self.assertEqual(context['pony'], test_view.object) + self.assertEqual(context["pony"], test_view.object) def test_object_in_get_context_data(self): # Checks 'object' key presence in dict returned by get_context_date #20234 test_view = views.CustomSingleObjectView() context = test_view.get_context_data() - self.assertEqual(context['object'], test_view.object) + self.assertEqual(context["object"], test_view.object) class UseMultipleObjectMixinTest(SimpleTestCase): @@ -559,23 +585,22 @@ class UseMultipleObjectMixinTest(SimpleTestCase): def test_use_queryset_from_view(self): test_view = views.CustomMultipleObjectMixinView() - test_view.get(self.rf.get('/')) + test_view.get(self.rf.get("/")) # Don't pass queryset as argument context = test_view.get_context_data() - self.assertEqual(context['object_list'], test_view.queryset) + self.assertEqual(context["object_list"], test_view.queryset) def test_overwrite_queryset(self): test_view = views.CustomMultipleObjectMixinView() - test_view.get(self.rf.get('/')) - queryset = [{'name': 'Lennon'}, {'name': 'Ono'}] + test_view.get(self.rf.get("/")) + queryset = [{"name": "Lennon"}, {"name": "Ono"}] self.assertNotEqual(test_view.queryset, queryset) # Overwrite the view's queryset with queryset from kwarg context = test_view.get_context_data(object_list=queryset) - self.assertEqual(context['object_list'], queryset) + self.assertEqual(context["object_list"], queryset) class SingleObjectTemplateResponseMixinTest(SimpleTestCase): - def test_template_mixin_without_template(self): """ We want to makes sure that if you use a template mixin, but forget the diff --git a/tests/generic_views/test_dates.py b/tests/generic_views/test_dates.py index bff58dcd0c..a826d5498d 100644 --- a/tests/generic_views/test_dates.py +++ b/tests/generic_views/test_dates.py @@ -12,275 +12,351 @@ from .models import Artist, Author, Book, BookSigning, Page def _make_books(n, base_date): for i in range(n): Book.objects.create( - name='Book %d' % i, - slug='book-%d' % i, + name="Book %d" % i, + slug="book-%d" % i, pages=100 + i, - pubdate=base_date - datetime.timedelta(days=i)) + pubdate=base_date - datetime.timedelta(days=i), + ) class TestDataMixin: - @classmethod def setUpTestData(cls): - cls.artist1 = Artist.objects.create(name='Rene Magritte') - cls.author1 = Author.objects.create(name='Roberto Bolaño', slug='roberto-bolano') - cls.author2 = Author.objects.create(name='Scott Rosenberg', slug='scott-rosenberg') - cls.book1 = Book.objects.create(name='2066', slug='2066', pages=800, pubdate=datetime.date(2008, 10, 1)) + cls.artist1 = Artist.objects.create(name="Rene Magritte") + cls.author1 = Author.objects.create( + name="Roberto Bolaño", slug="roberto-bolano" + ) + cls.author2 = Author.objects.create( + name="Scott Rosenberg", slug="scott-rosenberg" + ) + cls.book1 = Book.objects.create( + name="2066", slug="2066", pages=800, pubdate=datetime.date(2008, 10, 1) + ) cls.book1.authors.add(cls.author1) cls.book2 = Book.objects.create( - name='Dreaming in Code', slug='dreaming-in-code', pages=300, pubdate=datetime.date(2006, 5, 1) + name="Dreaming in Code", + slug="dreaming-in-code", + pages=300, + pubdate=datetime.date(2006, 5, 1), ) cls.page1 = Page.objects.create( - content='I was once bitten by a moose.', template='generic_views/page_template.html' + content="I was once bitten by a moose.", + template="generic_views/page_template.html", ) -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class ArchiveIndexViewTests(TestDataMixin, TestCase): - def test_archive_view(self): - res = self.client.get('/dates/books/') + res = self.client.get("/dates/books/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) - self.assertEqual(list(res.context['latest']), list(Book.objects.all())) - self.assertTemplateUsed(res, 'generic_views/book_archive.html') + self.assertEqual( + list(res.context["date_list"]), + list(Book.objects.dates("pubdate", "year", "DESC")), + ) + self.assertEqual(list(res.context["latest"]), list(Book.objects.all())) + self.assertTemplateUsed(res, "generic_views/book_archive.html") def test_archive_view_context_object_name(self): - res = self.client.get('/dates/books/context_object_name/') + res = self.client.get("/dates/books/context_object_name/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) - self.assertEqual(list(res.context['thingies']), list(Book.objects.all())) - self.assertNotIn('latest', res.context) - self.assertTemplateUsed(res, 'generic_views/book_archive.html') + self.assertEqual( + list(res.context["date_list"]), + list(Book.objects.dates("pubdate", "year", "DESC")), + ) + self.assertEqual(list(res.context["thingies"]), list(Book.objects.all())) + self.assertNotIn("latest", res.context) + self.assertTemplateUsed(res, "generic_views/book_archive.html") def test_empty_archive_view(self): Book.objects.all().delete() - res = self.client.get('/dates/books/') + res = self.client.get("/dates/books/") self.assertEqual(res.status_code, 404) def test_allow_empty_archive_view(self): Book.objects.all().delete() - res = self.client.get('/dates/books/allow_empty/') + res = self.client.get("/dates/books/allow_empty/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), []) - self.assertTemplateUsed(res, 'generic_views/book_archive.html') + self.assertEqual(list(res.context["date_list"]), []) + self.assertTemplateUsed(res, "generic_views/book_archive.html") def test_archive_view_template(self): - res = self.client.get('/dates/books/template_name/') + res = self.client.get("/dates/books/template_name/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) - self.assertEqual(list(res.context['latest']), list(Book.objects.all())) - self.assertTemplateUsed(res, 'generic_views/list.html') + self.assertEqual( + list(res.context["date_list"]), + list(Book.objects.dates("pubdate", "year", "DESC")), + ) + self.assertEqual(list(res.context["latest"]), list(Book.objects.all())) + self.assertTemplateUsed(res, "generic_views/list.html") def test_archive_view_template_suffix(self): - res = self.client.get('/dates/books/template_name_suffix/') + res = self.client.get("/dates/books/template_name_suffix/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) - self.assertEqual(list(res.context['latest']), list(Book.objects.all())) - self.assertTemplateUsed(res, 'generic_views/book_detail.html') + self.assertEqual( + list(res.context["date_list"]), + list(Book.objects.dates("pubdate", "year", "DESC")), + ) + self.assertEqual(list(res.context["latest"]), list(Book.objects.all())) + self.assertTemplateUsed(res, "generic_views/book_detail.html") def test_archive_view_invalid(self): msg = ( - 'BookArchive is missing a QuerySet. Define BookArchive.model, ' - 'BookArchive.queryset, or override BookArchive.get_queryset().' + "BookArchive is missing a QuerySet. Define BookArchive.model, " + "BookArchive.queryset, or override BookArchive.get_queryset()." ) with self.assertRaisesMessage(ImproperlyConfigured, msg): - self.client.get('/dates/books/invalid/') + self.client.get("/dates/books/invalid/") def test_archive_view_by_month(self): - res = self.client.get('/dates/books/by_month/') + res = self.client.get("/dates/books/by_month/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'month', 'DESC'))) + self.assertEqual( + list(res.context["date_list"]), + list(Book.objects.dates("pubdate", "month", "DESC")), + ) def test_paginated_archive_view(self): _make_books(20, base_date=datetime.date.today()) - res = self.client.get('/dates/books/paginated/') + res = self.client.get("/dates/books/paginated/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) - self.assertEqual(list(res.context['latest']), list(Book.objects.all()[0:10])) - self.assertTemplateUsed(res, 'generic_views/book_archive.html') + self.assertEqual( + list(res.context["date_list"]), + list(Book.objects.dates("pubdate", "year", "DESC")), + ) + self.assertEqual(list(res.context["latest"]), list(Book.objects.all()[0:10])) + self.assertTemplateUsed(res, "generic_views/book_archive.html") - res = self.client.get('/dates/books/paginated/?page=2') + res = self.client.get("/dates/books/paginated/?page=2") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['page_obj'].number, 2) - self.assertEqual(list(res.context['latest']), list(Book.objects.all()[10:20])) + self.assertEqual(res.context["page_obj"].number, 2) + self.assertEqual(list(res.context["latest"]), list(Book.objects.all()[10:20])) def test_paginated_archive_view_does_not_load_entire_table(self): # Regression test for #18087 _make_books(20, base_date=datetime.date.today()) # 1 query for years list + 1 query for books with self.assertNumQueries(2): - self.client.get('/dates/books/') + self.client.get("/dates/books/") # same as above + 1 query to test if books exist + 1 query to count them with self.assertNumQueries(4): - self.client.get('/dates/books/paginated/') + self.client.get("/dates/books/paginated/") def test_no_duplicate_query(self): # Regression test for #18354 with self.assertNumQueries(2): - self.client.get('/dates/books/reverse/') + self.client.get("/dates/books/reverse/") def test_datetime_archive_view(self): BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0)) - res = self.client.get('/dates/booksignings/') + res = self.client.get("/dates/booksignings/") self.assertEqual(res.status_code, 200) @requires_tz_support - @skipUnlessDBFeature('has_zoneinfo_database') - @override_settings(USE_TZ=True, TIME_ZONE='Africa/Nairobi') + @skipUnlessDBFeature("has_zoneinfo_database") + @override_settings(USE_TZ=True, TIME_ZONE="Africa/Nairobi") def test_aware_datetime_archive_view(self): - BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc)) - res = self.client.get('/dates/booksignings/') + BookSigning.objects.create( + event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc) + ) + res = self.client.get("/dates/booksignings/") self.assertEqual(res.status_code, 200) def test_date_list_order(self): """date_list should be sorted descending in index""" _make_books(5, base_date=datetime.date(2011, 12, 25)) - res = self.client.get('/dates/books/') + res = self.client.get("/dates/books/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), list(reversed(sorted(res.context['date_list'])))) + self.assertEqual( + list(res.context["date_list"]), + list(reversed(sorted(res.context["date_list"]))), + ) def test_archive_view_custom_sorting(self): - Book.objects.create(name="Zebras for Dummies", pages=600, pubdate=datetime.date(2007, 5, 1)) - res = self.client.get('/dates/books/sortedbyname/') + Book.objects.create( + name="Zebras for Dummies", pages=600, pubdate=datetime.date(2007, 5, 1) + ) + res = self.client.get("/dates/books/sortedbyname/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) - self.assertEqual(list(res.context['latest']), list(Book.objects.order_by('name').all())) - self.assertTemplateUsed(res, 'generic_views/book_archive.html') + self.assertEqual( + list(res.context["date_list"]), + list(Book.objects.dates("pubdate", "year", "DESC")), + ) + self.assertEqual( + list(res.context["latest"]), list(Book.objects.order_by("name").all()) + ) + self.assertTemplateUsed(res, "generic_views/book_archive.html") def test_archive_view_custom_sorting_dec(self): - Book.objects.create(name="Zebras for Dummies", pages=600, pubdate=datetime.date(2007, 5, 1)) - res = self.client.get('/dates/books/sortedbynamedec/') + Book.objects.create( + name="Zebras for Dummies", pages=600, pubdate=datetime.date(2007, 5, 1) + ) + res = self.client.get("/dates/books/sortedbynamedec/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), list(Book.objects.dates('pubdate', 'year', 'DESC'))) - self.assertEqual(list(res.context['latest']), list(Book.objects.order_by('-name').all())) - self.assertTemplateUsed(res, 'generic_views/book_archive.html') + self.assertEqual( + list(res.context["date_list"]), + list(Book.objects.dates("pubdate", "year", "DESC")), + ) + self.assertEqual( + list(res.context["latest"]), list(Book.objects.order_by("-name").all()) + ) + self.assertTemplateUsed(res, "generic_views/book_archive.html") def test_archive_view_without_date_field(self): - msg = 'BookArchiveWithoutDateField.date_field is required.' + msg = "BookArchiveWithoutDateField.date_field is required." with self.assertRaisesMessage(ImproperlyConfigured, msg): - self.client.get('/dates/books/without_date_field/') + self.client.get("/dates/books/without_date_field/") -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class YearArchiveViewTests(TestDataMixin, TestCase): - def test_year_view(self): - res = self.client.get('/dates/books/2008/') + res = self.client.get("/dates/books/2008/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), [datetime.date(2008, 10, 1)]) - self.assertEqual(res.context['year'], datetime.date(2008, 1, 1)) - self.assertTemplateUsed(res, 'generic_views/book_archive_year.html') + self.assertEqual(list(res.context["date_list"]), [datetime.date(2008, 10, 1)]) + self.assertEqual(res.context["year"], datetime.date(2008, 1, 1)) + self.assertTemplateUsed(res, "generic_views/book_archive_year.html") # Since allow_empty=False, next/prev years must be valid (#7164) - self.assertIsNone(res.context['next_year']) - self.assertEqual(res.context['previous_year'], datetime.date(2006, 1, 1)) + self.assertIsNone(res.context["next_year"]) + self.assertEqual(res.context["previous_year"], datetime.date(2006, 1, 1)) def test_year_view_make_object_list(self): - res = self.client.get('/dates/books/2006/make_object_list/') + res = self.client.get("/dates/books/2006/make_object_list/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), [datetime.date(2006, 5, 1)]) - self.assertEqual(list(res.context['book_list']), list(Book.objects.filter(pubdate__year=2006))) - self.assertEqual(list(res.context['object_list']), list(Book.objects.filter(pubdate__year=2006))) - self.assertTemplateUsed(res, 'generic_views/book_archive_year.html') + self.assertEqual(list(res.context["date_list"]), [datetime.date(2006, 5, 1)]) + self.assertEqual( + list(res.context["book_list"]), + list(Book.objects.filter(pubdate__year=2006)), + ) + self.assertEqual( + list(res.context["object_list"]), + list(Book.objects.filter(pubdate__year=2006)), + ) + self.assertTemplateUsed(res, "generic_views/book_archive_year.html") def test_year_view_empty(self): - res = self.client.get('/dates/books/1999/') + res = self.client.get("/dates/books/1999/") self.assertEqual(res.status_code, 404) - res = self.client.get('/dates/books/1999/allow_empty/') + res = self.client.get("/dates/books/1999/allow_empty/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), []) - self.assertEqual(list(res.context['book_list']), []) + self.assertEqual(list(res.context["date_list"]), []) + self.assertEqual(list(res.context["book_list"]), []) # Since allow_empty=True, next/prev are allowed to be empty years (#7164) - self.assertEqual(res.context['next_year'], datetime.date(2000, 1, 1)) - self.assertEqual(res.context['previous_year'], datetime.date(1998, 1, 1)) + self.assertEqual(res.context["next_year"], datetime.date(2000, 1, 1)) + self.assertEqual(res.context["previous_year"], datetime.date(1998, 1, 1)) def test_year_view_allow_future(self): # Create a new book in the future year = datetime.date.today().year + 1 - Book.objects.create(name="The New New Testement", pages=600, pubdate=datetime.date(year, 1, 1)) - res = self.client.get('/dates/books/%s/' % year) + Book.objects.create( + name="The New New Testement", pages=600, pubdate=datetime.date(year, 1, 1) + ) + res = self.client.get("/dates/books/%s/" % year) self.assertEqual(res.status_code, 404) - res = self.client.get('/dates/books/%s/allow_empty/' % year) + res = self.client.get("/dates/books/%s/allow_empty/" % year) self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['book_list']), []) + self.assertEqual(list(res.context["book_list"]), []) - res = self.client.get('/dates/books/%s/allow_future/' % year) + res = self.client.get("/dates/books/%s/allow_future/" % year) self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), [datetime.date(year, 1, 1)]) + self.assertEqual(list(res.context["date_list"]), [datetime.date(year, 1, 1)]) def test_year_view_paginated(self): - res = self.client.get('/dates/books/2006/paginated/') + res = self.client.get("/dates/books/2006/paginated/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['book_list']), list(Book.objects.filter(pubdate__year=2006))) - self.assertEqual(list(res.context['object_list']), list(Book.objects.filter(pubdate__year=2006))) - self.assertTemplateUsed(res, 'generic_views/book_archive_year.html') + self.assertEqual( + list(res.context["book_list"]), + list(Book.objects.filter(pubdate__year=2006)), + ) + self.assertEqual( + list(res.context["object_list"]), + list(Book.objects.filter(pubdate__year=2006)), + ) + self.assertTemplateUsed(res, "generic_views/book_archive_year.html") def test_year_view_custom_sort_order(self): # Zebras comes after Dreaming by name, but before on '-pubdate' which is the default sorting - Book.objects.create(name="Zebras for Dummies", pages=600, pubdate=datetime.date(2006, 9, 1)) - res = self.client.get('/dates/books/2006/sortedbyname/') + Book.objects.create( + name="Zebras for Dummies", pages=600, pubdate=datetime.date(2006, 9, 1) + ) + res = self.client.get("/dates/books/2006/sortedbyname/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), [datetime.date(2006, 5, 1), datetime.date(2006, 9, 1)]) self.assertEqual( - list(res.context['book_list']), - list(Book.objects.filter(pubdate__year=2006).order_by('name')) + list(res.context["date_list"]), + [datetime.date(2006, 5, 1), datetime.date(2006, 9, 1)], + ) + self.assertEqual( + list(res.context["book_list"]), + list(Book.objects.filter(pubdate__year=2006).order_by("name")), ) self.assertEqual( - list(res.context['object_list']), - list(Book.objects.filter(pubdate__year=2006).order_by('name')) + list(res.context["object_list"]), + list(Book.objects.filter(pubdate__year=2006).order_by("name")), ) - self.assertTemplateUsed(res, 'generic_views/book_archive_year.html') + self.assertTemplateUsed(res, "generic_views/book_archive_year.html") def test_year_view_two_custom_sort_orders(self): - Book.objects.create(name="Zebras for Dummies", pages=300, pubdate=datetime.date(2006, 9, 1)) - Book.objects.create(name="Hunting Hippos", pages=400, pubdate=datetime.date(2006, 3, 1)) - res = self.client.get('/dates/books/2006/sortedbypageandnamedec/') + Book.objects.create( + name="Zebras for Dummies", pages=300, pubdate=datetime.date(2006, 9, 1) + ) + Book.objects.create( + name="Hunting Hippos", pages=400, pubdate=datetime.date(2006, 3, 1) + ) + res = self.client.get("/dates/books/2006/sortedbypageandnamedec/") self.assertEqual(res.status_code, 200) self.assertEqual( - list(res.context['date_list']), - [datetime.date(2006, 3, 1), datetime.date(2006, 5, 1), datetime.date(2006, 9, 1)] + list(res.context["date_list"]), + [ + datetime.date(2006, 3, 1), + datetime.date(2006, 5, 1), + datetime.date(2006, 9, 1), + ], ) self.assertEqual( - list(res.context['book_list']), - list(Book.objects.filter(pubdate__year=2006).order_by('pages', '-name')) + list(res.context["book_list"]), + list(Book.objects.filter(pubdate__year=2006).order_by("pages", "-name")), ) self.assertEqual( - list(res.context['object_list']), - list(Book.objects.filter(pubdate__year=2006).order_by('pages', '-name')) + list(res.context["object_list"]), + list(Book.objects.filter(pubdate__year=2006).order_by("pages", "-name")), ) - self.assertTemplateUsed(res, 'generic_views/book_archive_year.html') + self.assertTemplateUsed(res, "generic_views/book_archive_year.html") def test_year_view_invalid_pattern(self): - res = self.client.get('/dates/books/no_year/') + res = self.client.get("/dates/books/no_year/") self.assertEqual(res.status_code, 404) def test_no_duplicate_query(self): # Regression test for #18354 with self.assertNumQueries(4): - self.client.get('/dates/books/2008/reverse/') + self.client.get("/dates/books/2008/reverse/") def test_datetime_year_view(self): BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0)) - res = self.client.get('/dates/booksignings/2008/') + res = self.client.get("/dates/booksignings/2008/") self.assertEqual(res.status_code, 200) - @skipUnlessDBFeature('has_zoneinfo_database') - @override_settings(USE_TZ=True, TIME_ZONE='Africa/Nairobi') + @skipUnlessDBFeature("has_zoneinfo_database") + @override_settings(USE_TZ=True, TIME_ZONE="Africa/Nairobi") def test_aware_datetime_year_view(self): - BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc)) - res = self.client.get('/dates/booksignings/2008/') + BookSigning.objects.create( + event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc) + ) + res = self.client.get("/dates/booksignings/2008/") self.assertEqual(res.status_code, 200) def test_date_list_order(self): """date_list should be sorted ascending in year view""" _make_books(10, base_date=datetime.date(2011, 12, 25)) - res = self.client.get('/dates/books/2011/') - self.assertEqual(list(res.context['date_list']), list(sorted(res.context['date_list']))) + res = self.client.get("/dates/books/2011/") + self.assertEqual( + list(res.context["date_list"]), list(sorted(res.context["date_list"])) + ) - @mock.patch('django.views.generic.list.MultipleObjectMixin.get_context_data') + @mock.patch("django.views.generic.list.MultipleObjectMixin.get_context_data") def test_get_context_data_receives_extra_context(self, mock): """ MultipleObjectMixin.get_context_data() receives the context set by @@ -288,200 +364,218 @@ class YearArchiveViewTests(TestDataMixin, TestCase): BaseDateListView.get(). """ BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0)) - with self.assertRaisesMessage(TypeError, 'context must be a dict rather than MagicMock.'): - self.client.get('/dates/booksignings/2008/') + with self.assertRaisesMessage( + TypeError, "context must be a dict rather than MagicMock." + ): + self.client.get("/dates/booksignings/2008/") args, kwargs = mock.call_args # These are context values from get_dated_items(). - self.assertEqual(kwargs['year'], datetime.date(2008, 1, 1)) - self.assertIsNone(kwargs['previous_year']) - self.assertIsNone(kwargs['next_year']) + self.assertEqual(kwargs["year"], datetime.date(2008, 1, 1)) + self.assertIsNone(kwargs["previous_year"]) + self.assertIsNone(kwargs["next_year"]) def test_get_dated_items_not_implemented(self): - msg = 'A DateView must provide an implementation of get_dated_items()' + msg = "A DateView must provide an implementation of get_dated_items()" with self.assertRaisesMessage(NotImplementedError, msg): - self.client.get('/BaseDateListViewTest/') + self.client.get("/BaseDateListViewTest/") -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class MonthArchiveViewTests(TestDataMixin, TestCase): - def test_month_view(self): - res = self.client.get('/dates/books/2008/oct/') + res = self.client.get("/dates/books/2008/oct/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/book_archive_month.html') - self.assertEqual(list(res.context['date_list']), [datetime.date(2008, 10, 1)]) - self.assertEqual(list(res.context['book_list']), - list(Book.objects.filter(pubdate=datetime.date(2008, 10, 1)))) - self.assertEqual(res.context['month'], datetime.date(2008, 10, 1)) + self.assertTemplateUsed(res, "generic_views/book_archive_month.html") + self.assertEqual(list(res.context["date_list"]), [datetime.date(2008, 10, 1)]) + self.assertEqual( + list(res.context["book_list"]), + list(Book.objects.filter(pubdate=datetime.date(2008, 10, 1))), + ) + self.assertEqual(res.context["month"], datetime.date(2008, 10, 1)) # Since allow_empty=False, next/prev months must be valid (#7164) - self.assertIsNone(res.context['next_month']) - self.assertEqual(res.context['previous_month'], datetime.date(2006, 5, 1)) + self.assertIsNone(res.context["next_month"]) + self.assertEqual(res.context["previous_month"], datetime.date(2006, 5, 1)) def test_month_view_allow_empty(self): # allow_empty = False, empty month - res = self.client.get('/dates/books/2000/jan/') + res = self.client.get("/dates/books/2000/jan/") self.assertEqual(res.status_code, 404) # allow_empty = True, empty month - res = self.client.get('/dates/books/2000/jan/allow_empty/') + res = self.client.get("/dates/books/2000/jan/allow_empty/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['date_list']), []) - self.assertEqual(list(res.context['book_list']), []) - self.assertEqual(res.context['month'], datetime.date(2000, 1, 1)) + self.assertEqual(list(res.context["date_list"]), []) + self.assertEqual(list(res.context["book_list"]), []) + self.assertEqual(res.context["month"], datetime.date(2000, 1, 1)) # Since allow_empty=True, next/prev are allowed to be empty months (#7164) - self.assertEqual(res.context['next_month'], datetime.date(2000, 2, 1)) - self.assertEqual(res.context['previous_month'], datetime.date(1999, 12, 1)) + self.assertEqual(res.context["next_month"], datetime.date(2000, 2, 1)) + self.assertEqual(res.context["previous_month"], datetime.date(1999, 12, 1)) # allow_empty but not allow_future: next_month should be empty (#7164) - url = datetime.date.today().strftime('/dates/books/%Y/%b/allow_empty/').lower() + url = datetime.date.today().strftime("/dates/books/%Y/%b/allow_empty/").lower() res = self.client.get(url) self.assertEqual(res.status_code, 200) - self.assertIsNone(res.context['next_month']) + self.assertIsNone(res.context["next_month"]) def test_month_view_allow_future(self): future = (datetime.date.today() + datetime.timedelta(days=60)).replace(day=1) - urlbit = future.strftime('%Y/%b').lower() + urlbit = future.strftime("%Y/%b").lower() b = Book.objects.create(name="The New New Testement", pages=600, pubdate=future) # allow_future = False, future month - res = self.client.get('/dates/books/%s/' % urlbit) + res = self.client.get("/dates/books/%s/" % urlbit) self.assertEqual(res.status_code, 404) # allow_future = True, valid future month - res = self.client.get('/dates/books/%s/allow_future/' % urlbit) + res = self.client.get("/dates/books/%s/allow_future/" % urlbit) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['date_list'][0], b.pubdate) - self.assertEqual(list(res.context['book_list']), [b]) - self.assertEqual(res.context['month'], future) + self.assertEqual(res.context["date_list"][0], b.pubdate) + self.assertEqual(list(res.context["book_list"]), [b]) + self.assertEqual(res.context["month"], future) # Since allow_future = True but not allow_empty, next/prev are not # allowed to be empty months (#7164) - self.assertIsNone(res.context['next_month']) - self.assertEqual(res.context['previous_month'], datetime.date(2008, 10, 1)) + self.assertIsNone(res.context["next_month"]) + self.assertEqual(res.context["previous_month"], datetime.date(2008, 10, 1)) # allow_future, but not allow_empty, with a current month. So next # should be in the future (yup, #7164, again) - res = self.client.get('/dates/books/2008/oct/allow_future/') + res = self.client.get("/dates/books/2008/oct/allow_future/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['next_month'], future) - self.assertEqual(res.context['previous_month'], datetime.date(2006, 5, 1)) + self.assertEqual(res.context["next_month"], future) + self.assertEqual(res.context["previous_month"], datetime.date(2006, 5, 1)) def test_month_view_paginated(self): - res = self.client.get('/dates/books/2008/oct/paginated/') + res = self.client.get("/dates/books/2008/oct/paginated/") self.assertEqual(res.status_code, 200) self.assertEqual( - list(res.context['book_list']), - list(Book.objects.filter(pubdate__year=2008, pubdate__month=10)) + list(res.context["book_list"]), + list(Book.objects.filter(pubdate__year=2008, pubdate__month=10)), ) self.assertEqual( - list(res.context['object_list']), - list(Book.objects.filter(pubdate__year=2008, pubdate__month=10)) + list(res.context["object_list"]), + list(Book.objects.filter(pubdate__year=2008, pubdate__month=10)), ) - self.assertTemplateUsed(res, 'generic_views/book_archive_month.html') + self.assertTemplateUsed(res, "generic_views/book_archive_month.html") def test_custom_month_format(self): - res = self.client.get('/dates/books/2008/10/') + res = self.client.get("/dates/books/2008/10/") self.assertEqual(res.status_code, 200) def test_month_view_invalid_pattern(self): - res = self.client.get('/dates/books/2007/no_month/') + res = self.client.get("/dates/books/2007/no_month/") self.assertEqual(res.status_code, 404) def test_previous_month_without_content(self): "Content can exist on any day of the previous month. Refs #14711" self.pubdate_list = [ - datetime.date(2010, month, day) - for month, day in ((9, 1), (10, 2), (11, 3)) + datetime.date(2010, month, day) for month, day in ((9, 1), (10, 2), (11, 3)) ] for pubdate in self.pubdate_list: name = str(pubdate) Book.objects.create(name=name, slug=name, pages=100, pubdate=pubdate) - res = self.client.get('/dates/books/2010/nov/allow_empty/') + res = self.client.get("/dates/books/2010/nov/allow_empty/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['previous_month'], datetime.date(2010, 10, 1)) + self.assertEqual(res.context["previous_month"], datetime.date(2010, 10, 1)) # The following test demonstrates the bug - res = self.client.get('/dates/books/2010/nov/') + res = self.client.get("/dates/books/2010/nov/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['previous_month'], datetime.date(2010, 10, 1)) + self.assertEqual(res.context["previous_month"], datetime.date(2010, 10, 1)) # The bug does not occur here because a Book with pubdate of Sep 1 exists - res = self.client.get('/dates/books/2010/oct/') + res = self.client.get("/dates/books/2010/oct/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['previous_month'], datetime.date(2010, 9, 1)) + self.assertEqual(res.context["previous_month"], datetime.date(2010, 9, 1)) def test_datetime_month_view(self): BookSigning.objects.create(event_date=datetime.datetime(2008, 2, 1, 12, 0)) BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0)) BookSigning.objects.create(event_date=datetime.datetime(2008, 6, 3, 12, 0)) - res = self.client.get('/dates/booksignings/2008/apr/') + res = self.client.get("/dates/booksignings/2008/apr/") self.assertEqual(res.status_code, 200) def test_month_view_get_month_from_request(self): oct1 = datetime.date(2008, 10, 1) - res = self.client.get('/dates/books/without_month/2008/?month=oct') + res = self.client.get("/dates/books/without_month/2008/?month=oct") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/book_archive_month.html') - self.assertEqual(list(res.context['date_list']), [oct1]) - self.assertEqual(list(res.context['book_list']), list(Book.objects.filter(pubdate=oct1))) - self.assertEqual(res.context['month'], oct1) + self.assertTemplateUsed(res, "generic_views/book_archive_month.html") + self.assertEqual(list(res.context["date_list"]), [oct1]) + self.assertEqual( + list(res.context["book_list"]), list(Book.objects.filter(pubdate=oct1)) + ) + self.assertEqual(res.context["month"], oct1) def test_month_view_without_month_in_url(self): - res = self.client.get('/dates/books/without_month/2008/') + res = self.client.get("/dates/books/without_month/2008/") self.assertEqual(res.status_code, 404) - self.assertEqual(res.context['exception'], 'No month specified') + self.assertEqual(res.context["exception"], "No month specified") - @skipUnlessDBFeature('has_zoneinfo_database') - @override_settings(USE_TZ=True, TIME_ZONE='Africa/Nairobi') + @skipUnlessDBFeature("has_zoneinfo_database") + @override_settings(USE_TZ=True, TIME_ZONE="Africa/Nairobi") def test_aware_datetime_month_view(self): - BookSigning.objects.create(event_date=datetime.datetime(2008, 2, 1, 12, 0, tzinfo=timezone.utc)) - BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc)) - BookSigning.objects.create(event_date=datetime.datetime(2008, 6, 3, 12, 0, tzinfo=timezone.utc)) - res = self.client.get('/dates/booksignings/2008/apr/') + BookSigning.objects.create( + event_date=datetime.datetime(2008, 2, 1, 12, 0, tzinfo=timezone.utc) + ) + BookSigning.objects.create( + event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc) + ) + BookSigning.objects.create( + event_date=datetime.datetime(2008, 6, 3, 12, 0, tzinfo=timezone.utc) + ) + res = self.client.get("/dates/booksignings/2008/apr/") self.assertEqual(res.status_code, 200) def test_date_list_order(self): """date_list should be sorted ascending in month view""" _make_books(10, base_date=datetime.date(2011, 12, 25)) - res = self.client.get('/dates/books/2011/dec/') - self.assertEqual(list(res.context['date_list']), list(sorted(res.context['date_list']))) + res = self.client.get("/dates/books/2011/dec/") + self.assertEqual( + list(res.context["date_list"]), list(sorted(res.context["date_list"])) + ) -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class WeekArchiveViewTests(TestDataMixin, TestCase): - def test_week_view(self): - res = self.client.get('/dates/books/2008/week/39/') + res = self.client.get("/dates/books/2008/week/39/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/book_archive_week.html') - self.assertEqual(res.context['book_list'][0], Book.objects.get(pubdate=datetime.date(2008, 10, 1))) - self.assertEqual(res.context['week'], datetime.date(2008, 9, 28)) + self.assertTemplateUsed(res, "generic_views/book_archive_week.html") + self.assertEqual( + res.context["book_list"][0], + Book.objects.get(pubdate=datetime.date(2008, 10, 1)), + ) + self.assertEqual(res.context["week"], datetime.date(2008, 9, 28)) # Since allow_empty=False, next/prev weeks must be valid - self.assertIsNone(res.context['next_week']) - self.assertEqual(res.context['previous_week'], datetime.date(2006, 4, 30)) + self.assertIsNone(res.context["next_week"]) + self.assertEqual(res.context["previous_week"], datetime.date(2006, 4, 30)) def test_week_view_allow_empty(self): # allow_empty = False, empty week - res = self.client.get('/dates/books/2008/week/12/') + res = self.client.get("/dates/books/2008/week/12/") self.assertEqual(res.status_code, 404) # allow_empty = True, empty month - res = self.client.get('/dates/books/2008/week/12/allow_empty/') + res = self.client.get("/dates/books/2008/week/12/allow_empty/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['book_list']), []) - self.assertEqual(res.context['week'], datetime.date(2008, 3, 23)) + self.assertEqual(list(res.context["book_list"]), []) + self.assertEqual(res.context["week"], datetime.date(2008, 3, 23)) # Since allow_empty=True, next/prev are allowed to be empty weeks - self.assertEqual(res.context['next_week'], datetime.date(2008, 3, 30)) - self.assertEqual(res.context['previous_week'], datetime.date(2008, 3, 16)) + self.assertEqual(res.context["next_week"], datetime.date(2008, 3, 30)) + self.assertEqual(res.context["previous_week"], datetime.date(2008, 3, 16)) # allow_empty but not allow_future: next_week should be empty - url = datetime.date.today().strftime('/dates/books/%Y/week/%U/allow_empty/').lower() + url = ( + datetime.date.today() + .strftime("/dates/books/%Y/week/%U/allow_empty/") + .lower() + ) res = self.client.get(url) self.assertEqual(res.status_code, 200) - self.assertIsNone(res.context['next_week']) + self.assertIsNone(res.context["next_week"]) def test_week_view_allow_future(self): # January 7th always falls in week 1, given Python's definition of week numbers @@ -489,69 +583,69 @@ class WeekArchiveViewTests(TestDataMixin, TestCase): future_sunday = future - datetime.timedelta(days=(future.weekday() + 1) % 7) b = Book.objects.create(name="The New New Testement", pages=600, pubdate=future) - res = self.client.get('/dates/books/%s/week/1/' % future.year) + res = self.client.get("/dates/books/%s/week/1/" % future.year) self.assertEqual(res.status_code, 404) - res = self.client.get('/dates/books/%s/week/1/allow_future/' % future.year) + res = self.client.get("/dates/books/%s/week/1/allow_future/" % future.year) self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['book_list']), [b]) - self.assertEqual(res.context['week'], future_sunday) + self.assertEqual(list(res.context["book_list"]), [b]) + self.assertEqual(res.context["week"], future_sunday) # Since allow_future = True but not allow_empty, next/prev are not # allowed to be empty weeks - self.assertIsNone(res.context['next_week']) - self.assertEqual(res.context['previous_week'], datetime.date(2008, 9, 28)) + self.assertIsNone(res.context["next_week"]) + self.assertEqual(res.context["previous_week"], datetime.date(2008, 9, 28)) # allow_future, but not allow_empty, with a current week. So next # should be in the future - res = self.client.get('/dates/books/2008/week/39/allow_future/') + res = self.client.get("/dates/books/2008/week/39/allow_future/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['next_week'], future_sunday) - self.assertEqual(res.context['previous_week'], datetime.date(2006, 4, 30)) + self.assertEqual(res.context["next_week"], future_sunday) + self.assertEqual(res.context["previous_week"], datetime.date(2006, 4, 30)) def test_week_view_paginated(self): week_start = datetime.date(2008, 9, 28) week_end = week_start + datetime.timedelta(days=7) - res = self.client.get('/dates/books/2008/week/39/') + res = self.client.get("/dates/books/2008/week/39/") self.assertEqual(res.status_code, 200) self.assertEqual( - list(res.context['book_list']), - list(Book.objects.filter(pubdate__gte=week_start, pubdate__lt=week_end)) + list(res.context["book_list"]), + list(Book.objects.filter(pubdate__gte=week_start, pubdate__lt=week_end)), ) self.assertEqual( - list(res.context['object_list']), - list(Book.objects.filter(pubdate__gte=week_start, pubdate__lt=week_end)) + list(res.context["object_list"]), + list(Book.objects.filter(pubdate__gte=week_start, pubdate__lt=week_end)), ) - self.assertTemplateUsed(res, 'generic_views/book_archive_week.html') + self.assertTemplateUsed(res, "generic_views/book_archive_week.html") def test_week_view_invalid_pattern(self): - res = self.client.get('/dates/books/2007/week/no_week/') + res = self.client.get("/dates/books/2007/week/no_week/") self.assertEqual(res.status_code, 404) def test_week_start_Monday(self): # Regression for #14752 - res = self.client.get('/dates/books/2008/week/39/') + res = self.client.get("/dates/books/2008/week/39/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['week'], datetime.date(2008, 9, 28)) + self.assertEqual(res.context["week"], datetime.date(2008, 9, 28)) - res = self.client.get('/dates/books/2008/week/39/monday/') + res = self.client.get("/dates/books/2008/week/39/monday/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['week'], datetime.date(2008, 9, 29)) + self.assertEqual(res.context["week"], datetime.date(2008, 9, 29)) def test_week_iso_format(self): - res = self.client.get('/dates/books/2008/week/40/iso_format/') + res = self.client.get("/dates/books/2008/week/40/iso_format/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/book_archive_week.html') + self.assertTemplateUsed(res, "generic_views/book_archive_week.html") self.assertEqual( - list(res.context['book_list']), + list(res.context["book_list"]), [Book.objects.get(pubdate=datetime.date(2008, 10, 1))], ) - self.assertEqual(res.context['week'], datetime.date(2008, 9, 29)) + self.assertEqual(res.context["week"], datetime.date(2008, 9, 29)) def test_unknown_week_format(self): msg = "Unknown week format '%T'. Choices are: %U, %V, %W" with self.assertRaisesMessage(ValueError, msg): - self.client.get('/dates/books/2008/week/39/unknown_week_format/') + self.client.get("/dates/books/2008/week/39/unknown_week_format/") def test_incompatible_iso_week_format_view(self): msg = ( @@ -559,192 +653,212 @@ class WeekArchiveViewTests(TestDataMixin, TestCase): "'%Y'. Use the ISO year '%G' instead." ) with self.assertRaisesMessage(ValueError, msg): - self.client.get('/dates/books/2008/week/40/invalid_iso_week_year_format/') + self.client.get("/dates/books/2008/week/40/invalid_iso_week_year_format/") def test_datetime_week_view(self): BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0)) - res = self.client.get('/dates/booksignings/2008/week/13/') + res = self.client.get("/dates/booksignings/2008/week/13/") self.assertEqual(res.status_code, 200) - @override_settings(USE_TZ=True, TIME_ZONE='Africa/Nairobi') + @override_settings(USE_TZ=True, TIME_ZONE="Africa/Nairobi") def test_aware_datetime_week_view(self): - BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc)) - res = self.client.get('/dates/booksignings/2008/week/13/') + BookSigning.objects.create( + event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc) + ) + res = self.client.get("/dates/booksignings/2008/week/13/") self.assertEqual(res.status_code, 200) -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class DayArchiveViewTests(TestDataMixin, TestCase): - def test_day_view(self): - res = self.client.get('/dates/books/2008/oct/01/') + res = self.client.get("/dates/books/2008/oct/01/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/book_archive_day.html') - self.assertEqual(list(res.context['book_list']), - list(Book.objects.filter(pubdate=datetime.date(2008, 10, 1)))) - self.assertEqual(res.context['day'], datetime.date(2008, 10, 1)) + self.assertTemplateUsed(res, "generic_views/book_archive_day.html") + self.assertEqual( + list(res.context["book_list"]), + list(Book.objects.filter(pubdate=datetime.date(2008, 10, 1))), + ) + self.assertEqual(res.context["day"], datetime.date(2008, 10, 1)) # Since allow_empty=False, next/prev days must be valid. - self.assertIsNone(res.context['next_day']) - self.assertEqual(res.context['previous_day'], datetime.date(2006, 5, 1)) + self.assertIsNone(res.context["next_day"]) + self.assertEqual(res.context["previous_day"], datetime.date(2006, 5, 1)) def test_day_view_allow_empty(self): # allow_empty = False, empty month - res = self.client.get('/dates/books/2000/jan/1/') + res = self.client.get("/dates/books/2000/jan/1/") self.assertEqual(res.status_code, 404) # allow_empty = True, empty month - res = self.client.get('/dates/books/2000/jan/1/allow_empty/') + res = self.client.get("/dates/books/2000/jan/1/allow_empty/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['book_list']), []) - self.assertEqual(res.context['day'], datetime.date(2000, 1, 1)) + self.assertEqual(list(res.context["book_list"]), []) + self.assertEqual(res.context["day"], datetime.date(2000, 1, 1)) # Since it's allow empty, next/prev are allowed to be empty months (#7164) - self.assertEqual(res.context['next_day'], datetime.date(2000, 1, 2)) - self.assertEqual(res.context['previous_day'], datetime.date(1999, 12, 31)) + self.assertEqual(res.context["next_day"], datetime.date(2000, 1, 2)) + self.assertEqual(res.context["previous_day"], datetime.date(1999, 12, 31)) # allow_empty but not allow_future: next_month should be empty (#7164) - url = datetime.date.today().strftime('/dates/books/%Y/%b/%d/allow_empty/').lower() + url = ( + datetime.date.today().strftime("/dates/books/%Y/%b/%d/allow_empty/").lower() + ) res = self.client.get(url) self.assertEqual(res.status_code, 200) - self.assertIsNone(res.context['next_day']) + self.assertIsNone(res.context["next_day"]) def test_day_view_allow_future(self): - future = (datetime.date.today() + datetime.timedelta(days=60)) - urlbit = future.strftime('%Y/%b/%d').lower() + future = datetime.date.today() + datetime.timedelta(days=60) + urlbit = future.strftime("%Y/%b/%d").lower() b = Book.objects.create(name="The New New Testement", pages=600, pubdate=future) # allow_future = False, future month - res = self.client.get('/dates/books/%s/' % urlbit) + res = self.client.get("/dates/books/%s/" % urlbit) self.assertEqual(res.status_code, 404) # allow_future = True, valid future month - res = self.client.get('/dates/books/%s/allow_future/' % urlbit) + res = self.client.get("/dates/books/%s/allow_future/" % urlbit) self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['book_list']), [b]) - self.assertEqual(res.context['day'], future) + self.assertEqual(list(res.context["book_list"]), [b]) + self.assertEqual(res.context["day"], future) # allow_future but not allow_empty, next/prev must be valid - self.assertIsNone(res.context['next_day']) - self.assertEqual(res.context['previous_day'], datetime.date(2008, 10, 1)) + self.assertIsNone(res.context["next_day"]) + self.assertEqual(res.context["previous_day"], datetime.date(2008, 10, 1)) # allow_future, but not allow_empty, with a current month. - res = self.client.get('/dates/books/2008/oct/01/allow_future/') + res = self.client.get("/dates/books/2008/oct/01/allow_future/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['next_day'], future) - self.assertEqual(res.context['previous_day'], datetime.date(2006, 5, 1)) + self.assertEqual(res.context["next_day"], future) + self.assertEqual(res.context["previous_day"], datetime.date(2006, 5, 1)) # allow_future for yesterday, next_day is today (#17192) today = datetime.date.today() yesterday = today - datetime.timedelta(days=1) - res = self.client.get('/dates/books/%s/allow_empty_and_future/' - % yesterday.strftime('%Y/%b/%d').lower()) - self.assertEqual(res.context['next_day'], today) + res = self.client.get( + "/dates/books/%s/allow_empty_and_future/" + % yesterday.strftime("%Y/%b/%d").lower() + ) + self.assertEqual(res.context["next_day"], today) def test_day_view_paginated(self): - res = self.client.get('/dates/books/2008/oct/1/') + res = self.client.get("/dates/books/2008/oct/1/") self.assertEqual(res.status_code, 200) self.assertEqual( - list(res.context['book_list']), - list(Book.objects.filter(pubdate__year=2008, pubdate__month=10, pubdate__day=1)) + list(res.context["book_list"]), + list( + Book.objects.filter( + pubdate__year=2008, pubdate__month=10, pubdate__day=1 + ) + ), ) self.assertEqual( - list(res.context['object_list']), - list(Book.objects.filter(pubdate__year=2008, pubdate__month=10, pubdate__day=1)) + list(res.context["object_list"]), + list( + Book.objects.filter( + pubdate__year=2008, pubdate__month=10, pubdate__day=1 + ) + ), ) - self.assertTemplateUsed(res, 'generic_views/book_archive_day.html') + self.assertTemplateUsed(res, "generic_views/book_archive_day.html") def test_next_prev_context(self): - res = self.client.get('/dates/books/2008/oct/01/') - self.assertEqual(res.content, b"Archive for Oct. 1, 2008. Previous day is May 1, 2006\n") + res = self.client.get("/dates/books/2008/oct/01/") + self.assertEqual( + res.content, b"Archive for Oct. 1, 2008. Previous day is May 1, 2006\n" + ) def test_custom_month_format(self): - res = self.client.get('/dates/books/2008/10/01/') + res = self.client.get("/dates/books/2008/10/01/") self.assertEqual(res.status_code, 200) def test_day_view_invalid_pattern(self): - res = self.client.get('/dates/books/2007/oct/no_day/') + res = self.client.get("/dates/books/2007/oct/no_day/") self.assertEqual(res.status_code, 404) def test_today_view(self): - res = self.client.get('/dates/books/today/') + res = self.client.get("/dates/books/today/") self.assertEqual(res.status_code, 404) - res = self.client.get('/dates/books/today/allow_empty/') + res = self.client.get("/dates/books/today/allow_empty/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['day'], datetime.date.today()) + self.assertEqual(res.context["day"], datetime.date.today()) def test_datetime_day_view(self): BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0)) - res = self.client.get('/dates/booksignings/2008/apr/2/') + res = self.client.get("/dates/booksignings/2008/apr/2/") self.assertEqual(res.status_code, 200) @requires_tz_support - @override_settings(USE_TZ=True, TIME_ZONE='Africa/Nairobi') + @override_settings(USE_TZ=True, TIME_ZONE="Africa/Nairobi") def test_aware_datetime_day_view(self): - bs = BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc)) - res = self.client.get('/dates/booksignings/2008/apr/2/') + bs = BookSigning.objects.create( + event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc) + ) + res = self.client.get("/dates/booksignings/2008/apr/2/") self.assertEqual(res.status_code, 200) # 2008-04-02T00:00:00+03:00 (beginning of day) > 2008-04-01T22:00:00+00:00 (book signing event date) bs.event_date = datetime.datetime(2008, 4, 1, 22, 0, tzinfo=timezone.utc) bs.save() - res = self.client.get('/dates/booksignings/2008/apr/2/') + res = self.client.get("/dates/booksignings/2008/apr/2/") self.assertEqual(res.status_code, 200) # 2008-04-03T00:00:00+03:00 (end of day) > 2008-04-02T22:00:00+00:00 (book signing event date) bs.event_date = datetime.datetime(2008, 4, 2, 22, 0, tzinfo=timezone.utc) bs.save() - res = self.client.get('/dates/booksignings/2008/apr/2/') + res = self.client.get("/dates/booksignings/2008/apr/2/") self.assertEqual(res.status_code, 404) -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class DateDetailViewTests(TestDataMixin, TestCase): - def test_date_detail_by_pk(self): - res = self.client.get('/dates/books/2008/oct/01/%s/' % self.book1.pk) + res = self.client.get("/dates/books/2008/oct/01/%s/" % self.book1.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.book1) - self.assertEqual(res.context['book'], self.book1) - self.assertTemplateUsed(res, 'generic_views/book_detail.html') + self.assertEqual(res.context["object"], self.book1) + self.assertEqual(res.context["book"], self.book1) + self.assertTemplateUsed(res, "generic_views/book_detail.html") def test_date_detail_by_slug(self): - res = self.client.get('/dates/books/2006/may/01/byslug/dreaming-in-code/') + res = self.client.get("/dates/books/2006/may/01/byslug/dreaming-in-code/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['book'], Book.objects.get(slug='dreaming-in-code')) + self.assertEqual(res.context["book"], Book.objects.get(slug="dreaming-in-code")) def test_date_detail_custom_month_format(self): - res = self.client.get('/dates/books/2008/10/01/%s/' % self.book1.pk) + res = self.client.get("/dates/books/2008/10/01/%s/" % self.book1.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['book'], self.book1) + self.assertEqual(res.context["book"], self.book1) def test_date_detail_allow_future(self): - future = (datetime.date.today() + datetime.timedelta(days=60)) - urlbit = future.strftime('%Y/%b/%d').lower() - b = Book.objects.create(name="The New New Testement", slug="new-new", pages=600, pubdate=future) + future = datetime.date.today() + datetime.timedelta(days=60) + urlbit = future.strftime("%Y/%b/%d").lower() + b = Book.objects.create( + name="The New New Testement", slug="new-new", pages=600, pubdate=future + ) - res = self.client.get('/dates/books/%s/new-new/' % urlbit) + res = self.client.get("/dates/books/%s/new-new/" % urlbit) self.assertEqual(res.status_code, 404) - res = self.client.get('/dates/books/%s/%s/allow_future/' % (urlbit, b.id)) + res = self.client.get("/dates/books/%s/%s/allow_future/" % (urlbit, b.id)) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['book'], b) - self.assertTemplateUsed(res, 'generic_views/book_detail.html') + self.assertEqual(res.context["book"], b) + self.assertTemplateUsed(res, "generic_views/book_detail.html") def test_year_out_of_range(self): urls = [ - '/dates/books/9999/', - '/dates/books/9999/12/', - '/dates/books/9999/week/52/', + "/dates/books/9999/", + "/dates/books/9999/12/", + "/dates/books/9999/week/52/", ] for url in urls: with self.subTest(url=url): res = self.client.get(url) self.assertEqual(res.status_code, 404) - self.assertEqual(res.context['exception'], 'Date out of range') + self.assertEqual(res.context["exception"], "Date out of range") def test_invalid_url(self): msg = ( - 'Generic detail view BookDetail must be called with either an ' - 'object pk or a slug in the URLconf.' + "Generic detail view BookDetail must be called with either an " + "object pk or a slug in the URLconf." ) with self.assertRaisesMessage(AttributeError, msg): self.client.get("/dates/books/2008/oct/01/nopk/") @@ -755,38 +869,42 @@ class DateDetailViewTests(TestDataMixin, TestCase): BaseDateDetailView.get_object(). """ res = self.client.get( - '/dates/books/get_object_custom_queryset/2006/may/01/%s/' % self.book2.pk) + "/dates/books/get_object_custom_queryset/2006/may/01/%s/" % self.book2.pk + ) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.book2) - self.assertEqual(res.context['book'], self.book2) - self.assertTemplateUsed(res, 'generic_views/book_detail.html') + self.assertEqual(res.context["object"], self.book2) + self.assertEqual(res.context["book"], self.book2) + self.assertTemplateUsed(res, "generic_views/book_detail.html") res = self.client.get( - '/dates/books/get_object_custom_queryset/2008/oct/01/9999999/') + "/dates/books/get_object_custom_queryset/2008/oct/01/9999999/" + ) self.assertEqual(res.status_code, 404) def test_get_object_custom_queryset_numqueries(self): with self.assertNumQueries(1): - self.client.get('/dates/books/get_object_custom_queryset/2006/may/01/2/') + self.client.get("/dates/books/get_object_custom_queryset/2006/may/01/2/") def test_datetime_date_detail(self): bs = BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0)) - res = self.client.get('/dates/booksignings/2008/apr/2/%d/' % bs.pk) + res = self.client.get("/dates/booksignings/2008/apr/2/%d/" % bs.pk) self.assertEqual(res.status_code, 200) @requires_tz_support - @override_settings(USE_TZ=True, TIME_ZONE='Africa/Nairobi') + @override_settings(USE_TZ=True, TIME_ZONE="Africa/Nairobi") def test_aware_datetime_date_detail(self): - bs = BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc)) - res = self.client.get('/dates/booksignings/2008/apr/2/%d/' % bs.pk) + bs = BookSigning.objects.create( + event_date=datetime.datetime(2008, 4, 2, 12, 0, tzinfo=timezone.utc) + ) + res = self.client.get("/dates/booksignings/2008/apr/2/%d/" % bs.pk) self.assertEqual(res.status_code, 200) # 2008-04-02T00:00:00+03:00 (beginning of day) > 2008-04-01T22:00:00+00:00 (book signing event date) bs.event_date = datetime.datetime(2008, 4, 1, 22, 0, tzinfo=timezone.utc) bs.save() - res = self.client.get('/dates/booksignings/2008/apr/2/%d/' % bs.pk) + res = self.client.get("/dates/booksignings/2008/apr/2/%d/" % bs.pk) self.assertEqual(res.status_code, 200) # 2008-04-03T00:00:00+03:00 (end of day) > 2008-04-02T22:00:00+00:00 (book signing event date) bs.event_date = datetime.datetime(2008, 4, 2, 22, 0, tzinfo=timezone.utc) bs.save() - res = self.client.get('/dates/booksignings/2008/apr/2/%d/' % bs.pk) + res = self.client.get("/dates/booksignings/2008/apr/2/%d/" % bs.pk) self.assertEqual(res.status_code, 404) diff --git a/tests/generic_views/test_detail.py b/tests/generic_views/test_detail.py index 002435dfce..7203100576 100644 --- a/tests/generic_views/test_detail.py +++ b/tests/generic_views/test_detail.py @@ -10,133 +10,164 @@ from django.views.generic.edit import ModelFormMixin from .models import Artist, Author, Book, Page -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class DetailViewTest(TestCase): - @classmethod def setUpTestData(cls): - cls.artist1 = Artist.objects.create(name='Rene Magritte') - cls.author1 = Author.objects.create(name='Roberto Bolaño', slug='roberto-bolano') - cls.author2 = Author.objects.create(name='Scott Rosenberg', slug='scott-rosenberg') - cls.book1 = Book.objects.create(name='2066', slug='2066', pages=800, pubdate=datetime.date(2008, 10, 1)) + cls.artist1 = Artist.objects.create(name="Rene Magritte") + cls.author1 = Author.objects.create( + name="Roberto Bolaño", slug="roberto-bolano" + ) + cls.author2 = Author.objects.create( + name="Scott Rosenberg", slug="scott-rosenberg" + ) + cls.book1 = Book.objects.create( + name="2066", slug="2066", pages=800, pubdate=datetime.date(2008, 10, 1) + ) cls.book1.authors.add(cls.author1) cls.book2 = Book.objects.create( - name='Dreaming in Code', slug='dreaming-in-code', pages=300, pubdate=datetime.date(2006, 5, 1) + name="Dreaming in Code", + slug="dreaming-in-code", + pages=300, + pubdate=datetime.date(2006, 5, 1), ) cls.page1 = Page.objects.create( - content='I was once bitten by a moose.', template='generic_views/page_template.html' + content="I was once bitten by a moose.", + template="generic_views/page_template.html", ) def test_simple_object(self): - res = self.client.get('/detail/obj/') + res = self.client.get("/detail/obj/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], {'foo': 'bar'}) - self.assertIsInstance(res.context['view'], View) - self.assertTemplateUsed(res, 'generic_views/detail.html') + self.assertEqual(res.context["object"], {"foo": "bar"}) + self.assertIsInstance(res.context["view"], View) + self.assertTemplateUsed(res, "generic_views/detail.html") def test_detail_by_pk(self): - res = self.client.get('/detail/author/%s/' % self.author1.pk) + res = self.client.get("/detail/author/%s/" % self.author1.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author1) - self.assertEqual(res.context['author'], self.author1) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual(res.context["object"], self.author1) + self.assertEqual(res.context["author"], self.author1) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_detail_missing_object(self): - res = self.client.get('/detail/author/500/') + res = self.client.get("/detail/author/500/") self.assertEqual(res.status_code, 404) def test_detail_object_does_not_exist(self): with self.assertRaises(ObjectDoesNotExist): - self.client.get('/detail/doesnotexist/1/') + self.client.get("/detail/doesnotexist/1/") def test_detail_by_custom_pk(self): - res = self.client.get('/detail/author/bycustompk/%s/' % self.author1.pk) + res = self.client.get("/detail/author/bycustompk/%s/" % self.author1.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author1) - self.assertEqual(res.context['author'], self.author1) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual(res.context["object"], self.author1) + self.assertEqual(res.context["author"], self.author1) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_detail_by_slug(self): - res = self.client.get('/detail/author/byslug/scott-rosenberg/') + res = self.client.get("/detail/author/byslug/scott-rosenberg/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], Author.objects.get(slug='scott-rosenberg')) - self.assertEqual(res.context['author'], Author.objects.get(slug='scott-rosenberg')) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual( + res.context["object"], Author.objects.get(slug="scott-rosenberg") + ) + self.assertEqual( + res.context["author"], Author.objects.get(slug="scott-rosenberg") + ) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_detail_by_custom_slug(self): - res = self.client.get('/detail/author/bycustomslug/scott-rosenberg/') + res = self.client.get("/detail/author/bycustomslug/scott-rosenberg/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], Author.objects.get(slug='scott-rosenberg')) - self.assertEqual(res.context['author'], Author.objects.get(slug='scott-rosenberg')) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual( + res.context["object"], Author.objects.get(slug="scott-rosenberg") + ) + self.assertEqual( + res.context["author"], Author.objects.get(slug="scott-rosenberg") + ) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_detail_by_pk_ignore_slug(self): - res = self.client.get('/detail/author/bypkignoreslug/%s-roberto-bolano/' % self.author1.pk) + res = self.client.get( + "/detail/author/bypkignoreslug/%s-roberto-bolano/" % self.author1.pk + ) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author1) - self.assertEqual(res.context['author'], self.author1) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual(res.context["object"], self.author1) + self.assertEqual(res.context["author"], self.author1) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_detail_by_pk_ignore_slug_mismatch(self): - res = self.client.get('/detail/author/bypkignoreslug/%s-scott-rosenberg/' % self.author1.pk) + res = self.client.get( + "/detail/author/bypkignoreslug/%s-scott-rosenberg/" % self.author1.pk + ) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author1) - self.assertEqual(res.context['author'], self.author1) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual(res.context["object"], self.author1) + self.assertEqual(res.context["author"], self.author1) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_detail_by_pk_and_slug(self): - res = self.client.get('/detail/author/bypkandslug/%s-roberto-bolano/' % self.author1.pk) + res = self.client.get( + "/detail/author/bypkandslug/%s-roberto-bolano/" % self.author1.pk + ) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author1) - self.assertEqual(res.context['author'], self.author1) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual(res.context["object"], self.author1) + self.assertEqual(res.context["author"], self.author1) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_detail_by_pk_and_slug_mismatch_404(self): - res = self.client.get('/detail/author/bypkandslug/%s-scott-rosenberg/' % self.author1.pk) + res = self.client.get( + "/detail/author/bypkandslug/%s-scott-rosenberg/" % self.author1.pk + ) self.assertEqual(res.status_code, 404) def test_verbose_name(self): - res = self.client.get('/detail/artist/%s/' % self.artist1.pk) + res = self.client.get("/detail/artist/%s/" % self.artist1.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.artist1) - self.assertEqual(res.context['artist'], self.artist1) - self.assertTemplateUsed(res, 'generic_views/artist_detail.html') + self.assertEqual(res.context["object"], self.artist1) + self.assertEqual(res.context["artist"], self.artist1) + self.assertTemplateUsed(res, "generic_views/artist_detail.html") def test_template_name(self): - res = self.client.get('/detail/author/%s/template_name/' % self.author1.pk) + res = self.client.get("/detail/author/%s/template_name/" % self.author1.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author1) - self.assertEqual(res.context['author'], self.author1) - self.assertTemplateUsed(res, 'generic_views/about.html') + self.assertEqual(res.context["object"], self.author1) + self.assertEqual(res.context["author"], self.author1) + self.assertTemplateUsed(res, "generic_views/about.html") def test_template_name_suffix(self): - res = self.client.get('/detail/author/%s/template_name_suffix/' % self.author1.pk) + res = self.client.get( + "/detail/author/%s/template_name_suffix/" % self.author1.pk + ) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author1) - self.assertEqual(res.context['author'], self.author1) - self.assertTemplateUsed(res, 'generic_views/author_view.html') + self.assertEqual(res.context["object"], self.author1) + self.assertEqual(res.context["author"], self.author1) + self.assertTemplateUsed(res, "generic_views/author_view.html") def test_template_name_field(self): - res = self.client.get('/detail/page/%s/field/' % self.page1.pk) + res = self.client.get("/detail/page/%s/field/" % self.page1.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.page1) - self.assertEqual(res.context['page'], self.page1) - self.assertTemplateUsed(res, 'generic_views/page_template.html') + self.assertEqual(res.context["object"], self.page1) + self.assertEqual(res.context["page"], self.page1) + self.assertTemplateUsed(res, "generic_views/page_template.html") def test_context_object_name(self): - res = self.client.get('/detail/author/%s/context_object_name/' % self.author1.pk) + res = self.client.get( + "/detail/author/%s/context_object_name/" % self.author1.pk + ) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author1) - self.assertEqual(res.context['thingy'], self.author1) - self.assertNotIn('author', res.context) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual(res.context["object"], self.author1) + self.assertEqual(res.context["thingy"], self.author1) + self.assertNotIn("author", res.context) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_duplicated_context_object_name(self): - res = self.client.get('/detail/author/%s/dupe_context_object_name/' % self.author1.pk) + res = self.client.get( + "/detail/author/%s/dupe_context_object_name/" % self.author1.pk + ) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author1) - self.assertNotIn('author', res.context) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual(res.context["object"], self.author1) + self.assertNotIn("author", res.context) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_custom_detail(self): """ @@ -144,45 +175,47 @@ class DetailViewTest(TestCase): SingleObjectMixin.get_context_object_name() always uses the obj parameter instead of self.object. """ - res = self.client.get('/detail/author/%s/custom_detail/' % self.author1.pk) + res = self.client.get("/detail/author/%s/custom_detail/" % self.author1.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['custom_author'], self.author1) - self.assertNotIn('author', res.context) - self.assertNotIn('object', res.context) - self.assertTemplateUsed(res, 'generic_views/author_detail.html') + self.assertEqual(res.context["custom_author"], self.author1) + self.assertNotIn("author", res.context) + self.assertNotIn("object", res.context) + self.assertTemplateUsed(res, "generic_views/author_detail.html") def test_deferred_queryset_template_name(self): class FormContext(SingleObjectTemplateResponseMixin): - request = RequestFactory().get('/') + request = RequestFactory().get("/") model = Author - object = Author.objects.defer('name').get(pk=self.author1.pk) + object = Author.objects.defer("name").get(pk=self.author1.pk) - self.assertEqual(FormContext().get_template_names()[0], 'generic_views/author_detail.html') + self.assertEqual( + FormContext().get_template_names()[0], "generic_views/author_detail.html" + ) def test_deferred_queryset_context_object_name(self): class FormContext(ModelFormMixin): - request = RequestFactory().get('/') + request = RequestFactory().get("/") model = Author - object = Author.objects.defer('name').get(pk=self.author1.pk) - fields = ('name',) + object = Author.objects.defer("name").get(pk=self.author1.pk) + fields = ("name",) form_context_data = FormContext().get_context_data() - self.assertEqual(form_context_data['object'], self.author1) - self.assertEqual(form_context_data['author'], self.author1) + self.assertEqual(form_context_data["object"], self.author1) + self.assertEqual(form_context_data["author"], self.author1) def test_invalid_url(self): with self.assertRaises(AttributeError): - self.client.get('/detail/author/invalid/url/') + self.client.get("/detail/author/invalid/url/") def test_invalid_queryset(self): msg = ( - 'AuthorDetail is missing a QuerySet. Define AuthorDetail.model, ' - 'AuthorDetail.queryset, or override AuthorDetail.get_queryset().' + "AuthorDetail is missing a QuerySet. Define AuthorDetail.model, " + "AuthorDetail.queryset, or override AuthorDetail.get_queryset()." ) with self.assertRaisesMessage(ImproperlyConfigured, msg): - self.client.get('/detail/author/invalid/qs/') + self.client.get("/detail/author/invalid/qs/") def test_non_model_object_with_meta(self): - res = self.client.get('/detail/nonmodel/1/') + res = self.client.get("/detail/nonmodel/1/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'].id, "non_model_1") + self.assertEqual(res.context["object"].id, "non_model_1") diff --git a/tests/generic_views/test_edit.py b/tests/generic_views/test_edit.py index 4292600911..2af8bc2aa7 100644 --- a/tests/generic_views/test_edit.py +++ b/tests/generic_views/test_edit.py @@ -5,7 +5,10 @@ from django.test.client import RequestFactory from django.urls import reverse from django.views.generic.base import View from django.views.generic.edit import ( - CreateView, DeleteView, DeleteViewCustomDeleteWarning, FormMixin, + CreateView, + DeleteView, + DeleteViewCustomDeleteWarning, + FormMixin, ModelFormMixin, ) @@ -18,67 +21,68 @@ class FormMixinTests(SimpleTestCase): request_factory = RequestFactory() def test_initial_data(self): - """ Test instance independence of initial data dict (see #16138) """ + """Test instance independence of initial data dict (see #16138)""" initial_1 = FormMixin().get_initial() - initial_1['foo'] = 'bar' + initial_1["foo"] = "bar" initial_2 = FormMixin().get_initial() self.assertNotEqual(initial_1, initial_2) def test_get_prefix(self): - """ Test prefix can be set (see #18872) """ - test_string = 'test' + """Test prefix can be set (see #18872)""" + test_string = "test" - get_request = self.request_factory.get('/') + get_request = self.request_factory.get("/") class TestFormMixin(FormMixin): request = get_request default_kwargs = TestFormMixin().get_form_kwargs() - self.assertIsNone(default_kwargs.get('prefix')) + self.assertIsNone(default_kwargs.get("prefix")) set_mixin = TestFormMixin() set_mixin.prefix = test_string set_kwargs = set_mixin.get_form_kwargs() - self.assertEqual(test_string, set_kwargs.get('prefix')) + self.assertEqual(test_string, set_kwargs.get("prefix")) def test_get_form(self): class TestFormMixin(FormMixin): - request = self.request_factory.get('/') + request = self.request_factory.get("/") self.assertIsInstance( - TestFormMixin().get_form(forms.Form), forms.Form, - 'get_form() should use provided form class.' + TestFormMixin().get_form(forms.Form), + forms.Form, + "get_form() should use provided form class.", ) class FormClassTestFormMixin(TestFormMixin): form_class = forms.Form self.assertIsInstance( - FormClassTestFormMixin().get_form(), forms.Form, - 'get_form() should fallback to get_form_class() if none is provided.' + FormClassTestFormMixin().get_form(), + forms.Form, + "get_form() should fallback to get_form_class() if none is provided.", ) def test_get_context_data(self): class FormContext(FormMixin): - request = self.request_factory.get('/') + request = self.request_factory.get("/") form_class = forms.Form - self.assertIsInstance(FormContext().get_context_data()['form'], forms.Form) + self.assertIsInstance(FormContext().get_context_data()["form"], forms.Form) -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class BasicFormTests(TestCase): - def test_post_data(self): - res = self.client.post('/contact/', {'name': "Me", 'message': "Hello"}) - self.assertRedirects(res, '/list/authors/') + res = self.client.post("/contact/", {"name": "Me", "message": "Hello"}) + self.assertRedirects(res, "/list/authors/") def test_late_form_validation(self): """ A form can be marked invalid in the form_valid() method (#25548). """ - res = self.client.post('/late-validation/', {'name': "Me", 'message': "Hello"}) - self.assertFalse(res.context['form'].is_valid()) + res = self.client.post("/late-validation/", {"name": "Me", "message": "Hello"}) + self.assertFalse(res.context["form"].is_valid()) class ModelFormMixinTests(SimpleTestCase): @@ -88,110 +92,131 @@ class ModelFormMixinTests(SimpleTestCase): def test_get_form_checks_for_object(self): mixin = ModelFormMixin() - mixin.request = RequestFactory().get('/') - self.assertEqual({'initial': {}, 'prefix': None}, - mixin.get_form_kwargs()) + mixin.request = RequestFactory().get("/") + self.assertEqual({"initial": {}, "prefix": None}, mixin.get_form_kwargs()) -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class CreateViewTests(TestCase): - def test_create(self): - res = self.client.get('/edit/authors/create/') + res = self.client.get("/edit/authors/create/") self.assertEqual(res.status_code, 200) - self.assertIsInstance(res.context['form'], forms.ModelForm) - self.assertIsInstance(res.context['view'], View) - self.assertNotIn('object', res.context) - self.assertNotIn('author', res.context) - self.assertTemplateUsed(res, 'generic_views/author_form.html') + self.assertIsInstance(res.context["form"], forms.ModelForm) + self.assertIsInstance(res.context["view"], View) + self.assertNotIn("object", res.context) + self.assertNotIn("author", res.context) + self.assertTemplateUsed(res, "generic_views/author_form.html") - res = self.client.post('/edit/authors/create/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'}) + res = self.client.post( + "/edit/authors/create/", + {"name": "Randall Munroe", "slug": "randall-munroe"}, + ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/list/authors/') - self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe']) + self.assertRedirects(res, "/list/authors/") + self.assertQuerysetEqual( + Author.objects.values_list("name", flat=True), ["Randall Munroe"] + ) def test_create_invalid(self): - res = self.client.post('/edit/authors/create/', {'name': 'A' * 101, 'slug': 'randall-munroe'}) + res = self.client.post( + "/edit/authors/create/", {"name": "A" * 101, "slug": "randall-munroe"} + ) self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/author_form.html') - self.assertEqual(len(res.context['form'].errors), 1) + self.assertTemplateUsed(res, "generic_views/author_form.html") + self.assertEqual(len(res.context["form"].errors), 1) self.assertEqual(Author.objects.count(), 0) def test_create_with_object_url(self): - res = self.client.post('/edit/artists/create/', {'name': 'Rene Magritte'}) + res = self.client.post("/edit/artists/create/", {"name": "Rene Magritte"}) self.assertEqual(res.status_code, 302) - artist = Artist.objects.get(name='Rene Magritte') - self.assertRedirects(res, '/detail/artist/%d/' % artist.pk) + artist = Artist.objects.get(name="Rene Magritte") + self.assertRedirects(res, "/detail/artist/%d/" % artist.pk) self.assertQuerysetEqual(Artist.objects.all(), [artist]) def test_create_with_redirect(self): - res = self.client.post('/edit/authors/create/redirect/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'}) + res = self.client.post( + "/edit/authors/create/redirect/", + {"name": "Randall Munroe", "slug": "randall-munroe"}, + ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/edit/authors/create/') - self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe']) + self.assertRedirects(res, "/edit/authors/create/") + self.assertQuerysetEqual( + Author.objects.values_list("name", flat=True), ["Randall Munroe"] + ) def test_create_with_interpolated_redirect(self): res = self.client.post( - '/edit/authors/create/interpolate_redirect/', - {'name': 'Randall Munroe', 'slug': 'randall-munroe'} + "/edit/authors/create/interpolate_redirect/", + {"name": "Randall Munroe", "slug": "randall-munroe"}, + ) + self.assertQuerysetEqual( + Author.objects.values_list("name", flat=True), ["Randall Munroe"] ) - self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe']) self.assertEqual(res.status_code, 302) pk = Author.objects.first().pk - self.assertRedirects(res, '/edit/author/%d/update/' % pk) + self.assertRedirects(res, "/edit/author/%d/update/" % pk) # Also test with escaped chars in URL res = self.client.post( - '/edit/authors/create/interpolate_redirect_nonascii/', - {'name': 'John Doe', 'slug': 'john-doe'} + "/edit/authors/create/interpolate_redirect_nonascii/", + {"name": "John Doe", "slug": "john-doe"}, ) self.assertEqual(res.status_code, 302) - pk = Author.objects.get(name='John Doe').pk - self.assertRedirects(res, '/%C3%A9dit/author/{}/update/'.format(pk)) + pk = Author.objects.get(name="John Doe").pk + self.assertRedirects(res, "/%C3%A9dit/author/{}/update/".format(pk)) def test_create_with_special_properties(self): - res = self.client.get('/edit/authors/create/special/') + res = self.client.get("/edit/authors/create/special/") self.assertEqual(res.status_code, 200) - self.assertIsInstance(res.context['form'], views.AuthorForm) - self.assertNotIn('object', res.context) - self.assertNotIn('author', res.context) - self.assertTemplateUsed(res, 'generic_views/form.html') + self.assertIsInstance(res.context["form"], views.AuthorForm) + self.assertNotIn("object", res.context) + self.assertNotIn("author", res.context) + self.assertTemplateUsed(res, "generic_views/form.html") - res = self.client.post('/edit/authors/create/special/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'}) + res = self.client.post( + "/edit/authors/create/special/", + {"name": "Randall Munroe", "slug": "randall-munroe"}, + ) self.assertEqual(res.status_code, 302) - obj = Author.objects.get(slug='randall-munroe') - self.assertRedirects(res, reverse('author_detail', kwargs={'pk': obj.pk})) + obj = Author.objects.get(slug="randall-munroe") + self.assertRedirects(res, reverse("author_detail", kwargs={"pk": obj.pk})) self.assertQuerysetEqual(Author.objects.all(), [obj]) def test_create_without_redirect(self): msg = ( - 'No URL to redirect to. Either provide a url or define a ' - 'get_absolute_url method on the Model.' + "No URL to redirect to. Either provide a url or define a " + "get_absolute_url method on the Model." ) with self.assertRaisesMessage(ImproperlyConfigured, msg): - self.client.post('/edit/authors/create/naive/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'}) + self.client.post( + "/edit/authors/create/naive/", + {"name": "Randall Munroe", "slug": "randall-munroe"}, + ) def test_create_restricted(self): res = self.client.post( - '/edit/authors/create/restricted/', - {'name': 'Randall Munroe', 'slug': 'randall-munroe'} + "/edit/authors/create/restricted/", + {"name": "Randall Munroe", "slug": "randall-munroe"}, ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/accounts/login/?next=/edit/authors/create/restricted/') + self.assertRedirects( + res, "/accounts/login/?next=/edit/authors/create/restricted/" + ) def test_create_view_with_restricted_fields(self): - class MyCreateView(CreateView): model = Author - fields = ['name'] + fields = ["name"] - self.assertEqual(list(MyCreateView().get_form_class().base_fields), ['name']) + self.assertEqual(list(MyCreateView().get_form_class().base_fields), ["name"]) def test_create_view_all_fields(self): class MyCreateView(CreateView): model = Author - fields = '__all__' + fields = "__all__" - self.assertEqual(list(MyCreateView().get_form_class().base_fields), ['name', 'slug']) + self.assertEqual( + list(MyCreateView().get_form_class().base_fields), ["name", "slug"] + ) def test_create_view_without_explicit_fields(self): class MyCreateView(CreateView): @@ -208,226 +233,248 @@ class CreateViewTests(TestCase): class MyCreateView(CreateView): model = Author form_class = AuthorForm - fields = ['name'] + fields = ["name"] message = "Specifying both 'fields' and 'form_class' is not permitted." with self.assertRaisesMessage(ImproperlyConfigured, message): MyCreateView().get_form_class() -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class UpdateViewTests(TestCase): - @classmethod def setUpTestData(cls): cls.author = Author.objects.create( pk=1, # Required for OneAuthorUpdate. - name='Randall Munroe', - slug='randall-munroe', + name="Randall Munroe", + slug="randall-munroe", ) def test_update_post(self): - res = self.client.get('/edit/author/%d/update/' % self.author.pk) + res = self.client.get("/edit/author/%d/update/" % self.author.pk) self.assertEqual(res.status_code, 200) - self.assertIsInstance(res.context['form'], forms.ModelForm) - self.assertEqual(res.context['object'], self.author) - self.assertEqual(res.context['author'], self.author) - self.assertTemplateUsed(res, 'generic_views/author_form.html') - self.assertEqual(res.context['view'].get_form_called_count, 1) + self.assertIsInstance(res.context["form"], forms.ModelForm) + self.assertEqual(res.context["object"], self.author) + self.assertEqual(res.context["author"], self.author) + self.assertTemplateUsed(res, "generic_views/author_form.html") + self.assertEqual(res.context["view"].get_form_called_count, 1) # Modification with both POST and PUT (browser compatible) res = self.client.post( - '/edit/author/%d/update/' % self.author.pk, - {'name': 'Randall Munroe (xkcd)', 'slug': 'randall-munroe'} + "/edit/author/%d/update/" % self.author.pk, + {"name": "Randall Munroe (xkcd)", "slug": "randall-munroe"}, ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/list/authors/') - self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (xkcd)']) + self.assertRedirects(res, "/list/authors/") + self.assertQuerysetEqual( + Author.objects.values_list("name", flat=True), ["Randall Munroe (xkcd)"] + ) def test_update_invalid(self): res = self.client.post( - '/edit/author/%d/update/' % self.author.pk, - {'name': 'A' * 101, 'slug': 'randall-munroe'} + "/edit/author/%d/update/" % self.author.pk, + {"name": "A" * 101, "slug": "randall-munroe"}, ) self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/author_form.html') - self.assertEqual(len(res.context['form'].errors), 1) + self.assertTemplateUsed(res, "generic_views/author_form.html") + self.assertEqual(len(res.context["form"].errors), 1) self.assertQuerysetEqual(Author.objects.all(), [self.author]) - self.assertEqual(res.context['view'].get_form_called_count, 1) + self.assertEqual(res.context["view"].get_form_called_count, 1) def test_update_with_object_url(self): - a = Artist.objects.create(name='Rene Magritte') - res = self.client.post('/edit/artists/%d/update/' % a.pk, {'name': 'Rene Magritte'}) + a = Artist.objects.create(name="Rene Magritte") + res = self.client.post( + "/edit/artists/%d/update/" % a.pk, {"name": "Rene Magritte"} + ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/detail/artist/%d/' % a.pk) + self.assertRedirects(res, "/detail/artist/%d/" % a.pk) self.assertQuerysetEqual(Artist.objects.all(), [a]) def test_update_with_redirect(self): res = self.client.post( - '/edit/author/%d/update/redirect/' % self.author.pk, - {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'} + "/edit/author/%d/update/redirect/" % self.author.pk, + {"name": "Randall Munroe (author of xkcd)", "slug": "randall-munroe"}, ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/edit/authors/create/') - self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (author of xkcd)']) + self.assertRedirects(res, "/edit/authors/create/") + self.assertQuerysetEqual( + Author.objects.values_list("name", flat=True), + ["Randall Munroe (author of xkcd)"], + ) def test_update_with_interpolated_redirect(self): res = self.client.post( - '/edit/author/%d/update/interpolate_redirect/' % self.author.pk, - {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'} + "/edit/author/%d/update/interpolate_redirect/" % self.author.pk, + {"name": "Randall Munroe (author of xkcd)", "slug": "randall-munroe"}, + ) + self.assertQuerysetEqual( + Author.objects.values_list("name", flat=True), + ["Randall Munroe (author of xkcd)"], ) - self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (author of xkcd)']) self.assertEqual(res.status_code, 302) pk = Author.objects.first().pk - self.assertRedirects(res, '/edit/author/%d/update/' % pk) + self.assertRedirects(res, "/edit/author/%d/update/" % pk) # Also test with escaped chars in URL res = self.client.post( - '/edit/author/%d/update/interpolate_redirect_nonascii/' % self.author.pk, - {'name': 'John Doe', 'slug': 'john-doe'} + "/edit/author/%d/update/interpolate_redirect_nonascii/" % self.author.pk, + {"name": "John Doe", "slug": "john-doe"}, ) self.assertEqual(res.status_code, 302) - pk = Author.objects.get(name='John Doe').pk - self.assertRedirects(res, '/%C3%A9dit/author/{}/update/'.format(pk)) + pk = Author.objects.get(name="John Doe").pk + self.assertRedirects(res, "/%C3%A9dit/author/{}/update/".format(pk)) def test_update_with_special_properties(self): - res = self.client.get('/edit/author/%d/update/special/' % self.author.pk) + res = self.client.get("/edit/author/%d/update/special/" % self.author.pk) self.assertEqual(res.status_code, 200) - self.assertIsInstance(res.context['form'], views.AuthorForm) - self.assertEqual(res.context['object'], self.author) - self.assertEqual(res.context['thingy'], self.author) - self.assertNotIn('author', res.context) - self.assertTemplateUsed(res, 'generic_views/form.html') + self.assertIsInstance(res.context["form"], views.AuthorForm) + self.assertEqual(res.context["object"], self.author) + self.assertEqual(res.context["thingy"], self.author) + self.assertNotIn("author", res.context) + self.assertTemplateUsed(res, "generic_views/form.html") res = self.client.post( - '/edit/author/%d/update/special/' % self.author.pk, - {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'} + "/edit/author/%d/update/special/" % self.author.pk, + {"name": "Randall Munroe (author of xkcd)", "slug": "randall-munroe"}, ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/detail/author/%d/' % self.author.pk) - self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (author of xkcd)']) + self.assertRedirects(res, "/detail/author/%d/" % self.author.pk) + self.assertQuerysetEqual( + Author.objects.values_list("name", flat=True), + ["Randall Munroe (author of xkcd)"], + ) def test_update_without_redirect(self): msg = ( - 'No URL to redirect to. Either provide a url or define a ' - 'get_absolute_url method on the Model.' + "No URL to redirect to. Either provide a url or define a " + "get_absolute_url method on the Model." ) with self.assertRaisesMessage(ImproperlyConfigured, msg): self.client.post( - '/edit/author/%d/update/naive/' % self.author.pk, - {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'} + "/edit/author/%d/update/naive/" % self.author.pk, + {"name": "Randall Munroe (author of xkcd)", "slug": "randall-munroe"}, ) def test_update_get_object(self): - res = self.client.get('/edit/author/update/') + res = self.client.get("/edit/author/update/") self.assertEqual(res.status_code, 200) - self.assertIsInstance(res.context['form'], forms.ModelForm) - self.assertIsInstance(res.context['view'], View) - self.assertEqual(res.context['object'], self.author) - self.assertEqual(res.context['author'], self.author) - self.assertTemplateUsed(res, 'generic_views/author_form.html') + self.assertIsInstance(res.context["form"], forms.ModelForm) + self.assertIsInstance(res.context["view"], View) + self.assertEqual(res.context["object"], self.author) + self.assertEqual(res.context["author"], self.author) + self.assertTemplateUsed(res, "generic_views/author_form.html") # Modification with both POST and PUT (browser compatible) - res = self.client.post('/edit/author/update/', {'name': 'Randall Munroe (xkcd)', 'slug': 'randall-munroe'}) + res = self.client.post( + "/edit/author/update/", + {"name": "Randall Munroe (xkcd)", "slug": "randall-munroe"}, + ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/list/authors/') - self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (xkcd)']) + self.assertRedirects(res, "/list/authors/") + self.assertQuerysetEqual( + Author.objects.values_list("name", flat=True), ["Randall Munroe (xkcd)"] + ) -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class DeleteViewTests(TestCase): - @classmethod def setUpTestData(cls): cls.author = Author.objects.create( - name='Randall Munroe', - slug='randall-munroe', + name="Randall Munroe", + slug="randall-munroe", ) def test_delete_by_post(self): - res = self.client.get('/edit/author/%d/delete/' % self.author.pk) + res = self.client.get("/edit/author/%d/delete/" % self.author.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author) - self.assertEqual(res.context['author'], self.author) - self.assertTemplateUsed(res, 'generic_views/author_confirm_delete.html') + self.assertEqual(res.context["object"], self.author) + self.assertEqual(res.context["author"], self.author) + self.assertTemplateUsed(res, "generic_views/author_confirm_delete.html") # Deletion with POST - res = self.client.post('/edit/author/%d/delete/' % self.author.pk) + res = self.client.post("/edit/author/%d/delete/" % self.author.pk) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/list/authors/') + self.assertRedirects(res, "/list/authors/") self.assertQuerysetEqual(Author.objects.all(), []) def test_delete_by_delete(self): # Deletion with browser compatible DELETE method - res = self.client.delete('/edit/author/%d/delete/' % self.author.pk) + res = self.client.delete("/edit/author/%d/delete/" % self.author.pk) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/list/authors/') + self.assertRedirects(res, "/list/authors/") self.assertQuerysetEqual(Author.objects.all(), []) def test_delete_with_redirect(self): - res = self.client.post('/edit/author/%d/delete/redirect/' % self.author.pk) + res = self.client.post("/edit/author/%d/delete/redirect/" % self.author.pk) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/edit/authors/create/') + self.assertRedirects(res, "/edit/authors/create/") self.assertQuerysetEqual(Author.objects.all(), []) def test_delete_with_interpolated_redirect(self): - res = self.client.post('/edit/author/%d/delete/interpolate_redirect/' % self.author.pk) + res = self.client.post( + "/edit/author/%d/delete/interpolate_redirect/" % self.author.pk + ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/edit/authors/create/?deleted=%d' % self.author.pk) + self.assertRedirects(res, "/edit/authors/create/?deleted=%d" % self.author.pk) self.assertQuerysetEqual(Author.objects.all(), []) # Also test with escaped chars in URL - a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'}) - res = self.client.post('/edit/author/{}/delete/interpolate_redirect_nonascii/'.format(a.pk)) + a = Author.objects.create( + **{"name": "Randall Munroe", "slug": "randall-munroe"} + ) + res = self.client.post( + "/edit/author/{}/delete/interpolate_redirect_nonascii/".format(a.pk) + ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/%C3%A9dit/authors/create/?deleted={}'.format(a.pk)) + self.assertRedirects(res, "/%C3%A9dit/authors/create/?deleted={}".format(a.pk)) def test_delete_with_special_properties(self): - res = self.client.get('/edit/author/%d/delete/special/' % self.author.pk) + res = self.client.get("/edit/author/%d/delete/special/" % self.author.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author) - self.assertEqual(res.context['thingy'], self.author) - self.assertNotIn('author', res.context) - self.assertTemplateUsed(res, 'generic_views/confirm_delete.html') + self.assertEqual(res.context["object"], self.author) + self.assertEqual(res.context["thingy"], self.author) + self.assertNotIn("author", res.context) + self.assertTemplateUsed(res, "generic_views/confirm_delete.html") - res = self.client.post('/edit/author/%d/delete/special/' % self.author.pk) + res = self.client.post("/edit/author/%d/delete/special/" % self.author.pk) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/list/authors/') + self.assertRedirects(res, "/list/authors/") self.assertQuerysetEqual(Author.objects.all(), []) def test_delete_without_redirect(self): - msg = 'No URL to redirect to. Provide a success_url.' + msg = "No URL to redirect to. Provide a success_url." with self.assertRaisesMessage(ImproperlyConfigured, msg): - self.client.post('/edit/author/%d/delete/naive/' % self.author.pk) + self.client.post("/edit/author/%d/delete/naive/" % self.author.pk) def test_delete_with_form_as_post(self): - res = self.client.get('/edit/author/%d/delete/form/' % self.author.pk) + res = self.client.get("/edit/author/%d/delete/form/" % self.author.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author) - self.assertEqual(res.context['author'], self.author) - self.assertTemplateUsed(res, 'generic_views/author_confirm_delete.html') + self.assertEqual(res.context["object"], self.author) + self.assertEqual(res.context["author"], self.author) + self.assertTemplateUsed(res, "generic_views/author_confirm_delete.html") res = self.client.post( - '/edit/author/%d/delete/form/' % self.author.pk, data={'confirm': True} + "/edit/author/%d/delete/form/" % self.author.pk, data={"confirm": True} ) self.assertEqual(res.status_code, 302) - self.assertRedirects(res, '/list/authors/') + self.assertRedirects(res, "/list/authors/") self.assertSequenceEqual(Author.objects.all(), []) def test_delete_with_form_as_post_with_validation_error(self): - res = self.client.get('/edit/author/%d/delete/form/' % self.author.pk) + res = self.client.get("/edit/author/%d/delete/form/" % self.author.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object'], self.author) - self.assertEqual(res.context['author'], self.author) - self.assertTemplateUsed(res, 'generic_views/author_confirm_delete.html') + self.assertEqual(res.context["object"], self.author) + self.assertEqual(res.context["author"], self.author) + self.assertTemplateUsed(res, "generic_views/author_confirm_delete.html") - res = self.client.post('/edit/author/%d/delete/form/' % self.author.pk) + res = self.client.post("/edit/author/%d/delete/form/" % self.author.pk) self.assertEqual(res.status_code, 200) - self.assertEqual(len(res.context_data['form'].errors), 2) + self.assertEqual(len(res.context_data["form"].errors), 2) self.assertEqual( - res.context_data['form'].errors['__all__'], - ['You must confirm the delete.'], + res.context_data["form"].errors["__all__"], + ["You must confirm the delete."], ) self.assertEqual( - res.context_data['form'].errors['confirm'], - ['This field is required.'], + res.context_data["form"].errors["confirm"], + ["This field is required."], ) # RemovedInDjango50Warning. @@ -440,10 +487,10 @@ class DeleteViewTests(TestCase): pass msg = ( - 'DeleteView uses FormMixin to handle POST requests. As a ' - 'consequence, any custom deletion logic in ' - 'AuthorDeleteView.delete() handler should be moved to ' - 'form_valid().' + "DeleteView uses FormMixin to handle POST requests. As a " + "consequence, any custom deletion logic in " + "AuthorDeleteView.delete() handler should be moved to " + "form_valid()." ) with self.assertWarnsMessage(DeleteViewCustomDeleteWarning, msg): AuthorDeleteView() diff --git a/tests/generic_views/test_list.py b/tests/generic_views/test_list.py index 259e850232..25f6553a8a 100644 --- a/tests/generic_views/test_list.py +++ b/tests/generic_views/test_list.py @@ -7,205 +7,213 @@ from django.views.generic.base import View from .models import Artist, Author, Book, Page -@override_settings(ROOT_URLCONF='generic_views.urls') +@override_settings(ROOT_URLCONF="generic_views.urls") class ListViewTests(TestCase): - @classmethod def setUpTestData(cls): - cls.artist1 = Artist.objects.create(name='Rene Magritte') - cls.author1 = Author.objects.create(name='Roberto Bolaño', slug='roberto-bolano') - cls.author2 = Author.objects.create(name='Scott Rosenberg', slug='scott-rosenberg') - cls.book1 = Book.objects.create(name='2066', slug='2066', pages=800, pubdate=datetime.date(2008, 10, 1)) + cls.artist1 = Artist.objects.create(name="Rene Magritte") + cls.author1 = Author.objects.create( + name="Roberto Bolaño", slug="roberto-bolano" + ) + cls.author2 = Author.objects.create( + name="Scott Rosenberg", slug="scott-rosenberg" + ) + cls.book1 = Book.objects.create( + name="2066", slug="2066", pages=800, pubdate=datetime.date(2008, 10, 1) + ) cls.book1.authors.add(cls.author1) cls.book2 = Book.objects.create( - name='Dreaming in Code', slug='dreaming-in-code', pages=300, pubdate=datetime.date(2006, 5, 1) + name="Dreaming in Code", + slug="dreaming-in-code", + pages=300, + pubdate=datetime.date(2006, 5, 1), ) cls.page1 = Page.objects.create( - content='I was once bitten by a moose.', template='generic_views/page_template.html' + content="I was once bitten by a moose.", + template="generic_views/page_template.html", ) def test_items(self): - res = self.client.get('/list/dict/') + res = self.client.get("/list/dict/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/list.html') - self.assertEqual(res.context['object_list'][0]['first'], 'John') + self.assertTemplateUsed(res, "generic_views/list.html") + self.assertEqual(res.context["object_list"][0]["first"], "John") def test_queryset(self): - res = self.client.get('/list/authors/') + res = self.client.get("/list/authors/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/author_list.html') - self.assertEqual(list(res.context['object_list']), list(Author.objects.all())) - self.assertIsInstance(res.context['view'], View) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertIsNone(res.context['paginator']) - self.assertIsNone(res.context['page_obj']) - self.assertFalse(res.context['is_paginated']) + self.assertTemplateUsed(res, "generic_views/author_list.html") + self.assertEqual(list(res.context["object_list"]), list(Author.objects.all())) + self.assertIsInstance(res.context["view"], View) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertIsNone(res.context["paginator"]) + self.assertIsNone(res.context["page_obj"]) + self.assertFalse(res.context["is_paginated"]) def test_paginated_queryset(self): self._make_authors(100) - res = self.client.get('/list/authors/paginated/') + res = self.client.get("/list/authors/paginated/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/author_list.html') - self.assertEqual(len(res.context['object_list']), 30) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertTrue(res.context['is_paginated']) - self.assertEqual(res.context['page_obj'].number, 1) - self.assertEqual(res.context['paginator'].num_pages, 4) - self.assertEqual(res.context['author_list'][0].name, 'Author 00') - self.assertEqual(list(res.context['author_list'])[-1].name, 'Author 29') + self.assertTemplateUsed(res, "generic_views/author_list.html") + self.assertEqual(len(res.context["object_list"]), 30) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertTrue(res.context["is_paginated"]) + self.assertEqual(res.context["page_obj"].number, 1) + self.assertEqual(res.context["paginator"].num_pages, 4) + self.assertEqual(res.context["author_list"][0].name, "Author 00") + self.assertEqual(list(res.context["author_list"])[-1].name, "Author 29") def test_paginated_queryset_shortdata(self): # Short datasets also result in a paginated view. - res = self.client.get('/list/authors/paginated/') + res = self.client.get("/list/authors/paginated/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/author_list.html') - self.assertEqual(list(res.context['object_list']), list(Author.objects.all())) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertEqual(res.context['page_obj'].number, 1) - self.assertEqual(res.context['paginator'].num_pages, 1) - self.assertFalse(res.context['is_paginated']) + self.assertTemplateUsed(res, "generic_views/author_list.html") + self.assertEqual(list(res.context["object_list"]), list(Author.objects.all())) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertEqual(res.context["page_obj"].number, 1) + self.assertEqual(res.context["paginator"].num_pages, 1) + self.assertFalse(res.context["is_paginated"]) def test_paginated_get_page_by_query_string(self): self._make_authors(100) - res = self.client.get('/list/authors/paginated/', {'page': '2'}) + res = self.client.get("/list/authors/paginated/", {"page": "2"}) self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/author_list.html') - self.assertEqual(len(res.context['object_list']), 30) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertEqual(res.context['author_list'][0].name, 'Author 30') - self.assertEqual(res.context['page_obj'].number, 2) + self.assertTemplateUsed(res, "generic_views/author_list.html") + self.assertEqual(len(res.context["object_list"]), 30) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertEqual(res.context["author_list"][0].name, "Author 30") + self.assertEqual(res.context["page_obj"].number, 2) def test_paginated_get_last_page_by_query_string(self): self._make_authors(100) - res = self.client.get('/list/authors/paginated/', {'page': 'last'}) + res = self.client.get("/list/authors/paginated/", {"page": "last"}) self.assertEqual(res.status_code, 200) - self.assertEqual(len(res.context['object_list']), 10) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertEqual(res.context['author_list'][0].name, 'Author 90') - self.assertEqual(res.context['page_obj'].number, 4) + self.assertEqual(len(res.context["object_list"]), 10) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertEqual(res.context["author_list"][0].name, "Author 90") + self.assertEqual(res.context["page_obj"].number, 4) def test_paginated_get_page_by_urlvar(self): self._make_authors(100) - res = self.client.get('/list/authors/paginated/3/') + res = self.client.get("/list/authors/paginated/3/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/author_list.html') - self.assertEqual(len(res.context['object_list']), 30) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertEqual(res.context['author_list'][0].name, 'Author 60') - self.assertEqual(res.context['page_obj'].number, 3) + self.assertTemplateUsed(res, "generic_views/author_list.html") + self.assertEqual(len(res.context["object_list"]), 30) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertEqual(res.context["author_list"][0].name, "Author 60") + self.assertEqual(res.context["page_obj"].number, 3) def test_paginated_page_out_of_range(self): self._make_authors(100) - res = self.client.get('/list/authors/paginated/42/') + res = self.client.get("/list/authors/paginated/42/") self.assertEqual(res.status_code, 404) def test_paginated_invalid_page(self): self._make_authors(100) - res = self.client.get('/list/authors/paginated/?page=frog') + res = self.client.get("/list/authors/paginated/?page=frog") self.assertEqual(res.status_code, 404) def test_paginated_custom_paginator_class(self): self._make_authors(7) - res = self.client.get('/list/authors/paginated/custom_class/') + res = self.client.get("/list/authors/paginated/custom_class/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['paginator'].num_pages, 1) + self.assertEqual(res.context["paginator"].num_pages, 1) # Custom pagination allows for 2 orphans on a page size of 5 - self.assertEqual(len(res.context['object_list']), 7) + self.assertEqual(len(res.context["object_list"]), 7) def test_paginated_custom_page_kwarg(self): self._make_authors(100) - res = self.client.get('/list/authors/paginated/custom_page_kwarg/', {'pagina': '2'}) + res = self.client.get( + "/list/authors/paginated/custom_page_kwarg/", {"pagina": "2"} + ) self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/author_list.html') - self.assertEqual(len(res.context['object_list']), 30) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertEqual(res.context['author_list'][0].name, 'Author 30') - self.assertEqual(res.context['page_obj'].number, 2) + self.assertTemplateUsed(res, "generic_views/author_list.html") + self.assertEqual(len(res.context["object_list"]), 30) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertEqual(res.context["author_list"][0].name, "Author 30") + self.assertEqual(res.context["page_obj"].number, 2) def test_paginated_custom_paginator_constructor(self): self._make_authors(7) - res = self.client.get('/list/authors/paginated/custom_constructor/') + res = self.client.get("/list/authors/paginated/custom_constructor/") self.assertEqual(res.status_code, 200) # Custom pagination allows for 2 orphans on a page size of 5 - self.assertEqual(len(res.context['object_list']), 7) + self.assertEqual(len(res.context["object_list"]), 7) def test_paginated_orphaned_queryset(self): self._make_authors(92) - res = self.client.get('/list/authors/paginated-orphaned/') + res = self.client.get("/list/authors/paginated-orphaned/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['page_obj'].number, 1) - res = self.client.get( - '/list/authors/paginated-orphaned/', {'page': 'last'}) + self.assertEqual(res.context["page_obj"].number, 1) + res = self.client.get("/list/authors/paginated-orphaned/", {"page": "last"}) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['page_obj'].number, 3) - res = self.client.get( - '/list/authors/paginated-orphaned/', {'page': '3'}) + self.assertEqual(res.context["page_obj"].number, 3) + res = self.client.get("/list/authors/paginated-orphaned/", {"page": "3"}) self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['page_obj'].number, 3) - res = self.client.get( - '/list/authors/paginated-orphaned/', {'page': '4'}) + self.assertEqual(res.context["page_obj"].number, 3) + res = self.client.get("/list/authors/paginated-orphaned/", {"page": "4"}) self.assertEqual(res.status_code, 404) def test_paginated_non_queryset(self): - res = self.client.get('/list/dict/paginated/') + res = self.client.get("/list/dict/paginated/") self.assertEqual(res.status_code, 200) - self.assertEqual(len(res.context['object_list']), 1) + self.assertEqual(len(res.context["object_list"]), 1) def test_verbose_name(self): - res = self.client.get('/list/artists/') + res = self.client.get("/list/artists/") self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'generic_views/list.html') - self.assertEqual(list(res.context['object_list']), list(Artist.objects.all())) - self.assertIs(res.context['artist_list'], res.context['object_list']) - self.assertIsNone(res.context['paginator']) - self.assertIsNone(res.context['page_obj']) - self.assertFalse(res.context['is_paginated']) + self.assertTemplateUsed(res, "generic_views/list.html") + self.assertEqual(list(res.context["object_list"]), list(Artist.objects.all())) + self.assertIs(res.context["artist_list"], res.context["object_list"]) + self.assertIsNone(res.context["paginator"]) + self.assertIsNone(res.context["page_obj"]) + self.assertFalse(res.context["is_paginated"]) def test_allow_empty_false(self): - res = self.client.get('/list/authors/notempty/') + res = self.client.get("/list/authors/notempty/") self.assertEqual(res.status_code, 200) Author.objects.all().delete() - res = self.client.get('/list/authors/notempty/') + res = self.client.get("/list/authors/notempty/") self.assertEqual(res.status_code, 404) def test_template_name(self): - res = self.client.get('/list/authors/template_name/') + res = self.client.get("/list/authors/template_name/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['object_list']), list(Author.objects.all())) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertTemplateUsed(res, 'generic_views/list.html') + self.assertEqual(list(res.context["object_list"]), list(Author.objects.all())) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertTemplateUsed(res, "generic_views/list.html") def test_template_name_suffix(self): - res = self.client.get('/list/authors/template_name_suffix/') + res = self.client.get("/list/authors/template_name_suffix/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['object_list']), list(Author.objects.all())) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertTemplateUsed(res, 'generic_views/author_objects.html') + self.assertEqual(list(res.context["object_list"]), list(Author.objects.all())) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertTemplateUsed(res, "generic_views/author_objects.html") def test_context_object_name(self): - res = self.client.get('/list/authors/context_object_name/') + res = self.client.get("/list/authors/context_object_name/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['object_list']), list(Author.objects.all())) - self.assertNotIn('authors', res.context) - self.assertIs(res.context['author_list'], res.context['object_list']) - self.assertTemplateUsed(res, 'generic_views/author_list.html') + self.assertEqual(list(res.context["object_list"]), list(Author.objects.all())) + self.assertNotIn("authors", res.context) + self.assertIs(res.context["author_list"], res.context["object_list"]) + self.assertTemplateUsed(res, "generic_views/author_list.html") def test_duplicate_context_object_name(self): - res = self.client.get('/list/authors/dupe_context_object_name/') + res = self.client.get("/list/authors/dupe_context_object_name/") self.assertEqual(res.status_code, 200) - self.assertEqual(list(res.context['object_list']), list(Author.objects.all())) - self.assertNotIn('authors', res.context) - self.assertNotIn('author_list', res.context) - self.assertTemplateUsed(res, 'generic_views/author_list.html') + self.assertEqual(list(res.context["object_list"]), list(Author.objects.all())) + self.assertNotIn("authors", res.context) + self.assertNotIn("author_list", res.context) + self.assertTemplateUsed(res, "generic_views/author_list.html") def test_missing_items(self): msg = ( - 'AuthorList is missing a QuerySet. Define AuthorList.model, ' - 'AuthorList.queryset, or override AuthorList.get_queryset().' + "AuthorList is missing a QuerySet. Define AuthorList.model, " + "AuthorList.queryset, or override AuthorList.get_queryset()." ) with self.assertRaisesMessage(ImproperlyConfigured, msg): - self.client.get('/list/authors/invalid/') + self.client.get("/list/authors/invalid/") def test_invalid_get_queryset(self): msg = ( @@ -213,42 +221,46 @@ class ListViewTests(TestCase): "attribute or a get_queryset() method that returns a QuerySet." ) with self.assertRaisesMessage(ImproperlyConfigured, msg): - self.client.get('/list/authors/get_queryset/') + self.client.get("/list/authors/get_queryset/") def test_paginated_list_view_does_not_load_entire_table(self): # Regression test for #17535 self._make_authors(3) # 1 query for authors with self.assertNumQueries(1): - self.client.get('/list/authors/notempty/') + self.client.get("/list/authors/notempty/") # same as above + 1 query to test if authors exist + 1 query for pagination with self.assertNumQueries(3): - self.client.get('/list/authors/notempty/paginated/') + self.client.get("/list/authors/notempty/paginated/") def test_explicitly_ordered_list_view(self): - Book.objects.create(name="Zebras for Dummies", pages=800, pubdate=datetime.date(2006, 9, 1)) - res = self.client.get('/list/books/sorted/') + Book.objects.create( + name="Zebras for Dummies", pages=800, pubdate=datetime.date(2006, 9, 1) + ) + res = self.client.get("/list/books/sorted/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object_list'][0].name, '2066') - self.assertEqual(res.context['object_list'][1].name, 'Dreaming in Code') - self.assertEqual(res.context['object_list'][2].name, 'Zebras for Dummies') + self.assertEqual(res.context["object_list"][0].name, "2066") + self.assertEqual(res.context["object_list"][1].name, "Dreaming in Code") + self.assertEqual(res.context["object_list"][2].name, "Zebras for Dummies") - res = self.client.get('/list/books/sortedbypagesandnamedec/') + res = self.client.get("/list/books/sortedbypagesandnamedec/") self.assertEqual(res.status_code, 200) - self.assertEqual(res.context['object_list'][0].name, 'Dreaming in Code') - self.assertEqual(res.context['object_list'][1].name, 'Zebras for Dummies') - self.assertEqual(res.context['object_list'][2].name, '2066') + self.assertEqual(res.context["object_list"][0].name, "Dreaming in Code") + self.assertEqual(res.context["object_list"][1].name, "Zebras for Dummies") + self.assertEqual(res.context["object_list"][2].name, "2066") @override_settings(DEBUG=True) def test_paginated_list_view_returns_useful_message_on_invalid_page(self): # test for #19240 # tests that source exception's message is included in page self._make_authors(1) - res = self.client.get('/list/authors/paginated/2/') + res = self.client.get("/list/authors/paginated/2/") self.assertEqual(res.status_code, 404) - self.assertEqual(res.context.get('reason'), "Invalid page (2): That page contains no results") + self.assertEqual( + res.context.get("reason"), "Invalid page (2): That page contains no results" + ) def _make_authors(self, n): Author.objects.all().delete() for i in range(n): - Author.objects.create(name='Author %02i' % i, slug='a%s' % i) + Author.objects.create(name="Author %02i" % i, slug="a%s" % i) diff --git a/tests/generic_views/urls.py b/tests/generic_views/urls.py index 940f82d5d0..2d5301d15e 100644 --- a/tests/generic_views/urls.py +++ b/tests/generic_views/urls.py @@ -9,233 +9,371 @@ from .models import Book urlpatterns = [ # TemplateView - path('template/no_template/', TemplateView.as_view()), - path('template/login_required/', login_required(TemplateView.as_view())), - path('template/simple/<foo>/', TemplateView.as_view(template_name='generic_views/about.html')), - path('template/custom/<foo>/', views.CustomTemplateView.as_view(template_name='generic_views/about.html')), + path("template/no_template/", TemplateView.as_view()), + path("template/login_required/", login_required(TemplateView.as_view())), path( - 'template/content_type/', - TemplateView.as_view(template_name='generic_views/robots.txt', content_type='text/plain'), + "template/simple/<foo>/", + TemplateView.as_view(template_name="generic_views/about.html"), ), path( - 'template/cached/<foo>/', - cache_page(2.0)(TemplateView.as_view(template_name='generic_views/about.html')), + "template/custom/<foo>/", + views.CustomTemplateView.as_view(template_name="generic_views/about.html"), ), path( - 'template/extra_context/', - TemplateView.as_view(template_name='generic_views/about.html', extra_context={'title': 'Title'}), + "template/content_type/", + TemplateView.as_view( + template_name="generic_views/robots.txt", content_type="text/plain" + ), + ), + path( + "template/cached/<foo>/", + cache_page(2.0)(TemplateView.as_view(template_name="generic_views/about.html")), + ), + path( + "template/extra_context/", + TemplateView.as_view( + template_name="generic_views/about.html", extra_context={"title": "Title"} + ), ), - # DetailView - path('detail/obj/', views.ObjectDetail.as_view()), - path('detail/artist/<int:pk>/', views.ArtistDetail.as_view(), name='artist_detail'), - path('detail/author/<int:pk>/', views.AuthorDetail.as_view(), name='author_detail'), - path('detail/author/bycustompk/<foo>/', views.AuthorDetail.as_view(pk_url_kwarg='foo')), - path('detail/author/byslug/<slug>/', views.AuthorDetail.as_view()), - path('detail/author/bycustomslug/<foo>/', views.AuthorDetail.as_view(slug_url_kwarg='foo')), - path('detail/author/bypkignoreslug/<int:pk>-<slug>/', views.AuthorDetail.as_view()), - path('detail/author/bypkandslug/<int:pk>-<slug>/', views.AuthorDetail.as_view(query_pk_and_slug=True)), - path('detail/author/<int:pk>/template_name_suffix/', views.AuthorDetail.as_view(template_name_suffix='_view')), - path( - 'detail/author/<int:pk>/template_name/', - views.AuthorDetail.as_view(template_name='generic_views/about.html'), - ), - path('detail/author/<int:pk>/context_object_name/', views.AuthorDetail.as_view(context_object_name='thingy')), - path('detail/author/<int:pk>/custom_detail/', views.AuthorCustomDetail.as_view()), - path('detail/author/<int:pk>/dupe_context_object_name/', views.AuthorDetail.as_view(context_object_name='object')), - path('detail/page/<int:pk>/field/', views.PageDetail.as_view()), - path(r'detail/author/invalid/url/', views.AuthorDetail.as_view()), - path('detail/author/invalid/qs/', views.AuthorDetail.as_view(queryset=None)), - path('detail/nonmodel/1/', views.NonModelDetail.as_view()), - path('detail/doesnotexist/<pk>/', views.ObjectDoesNotExistDetail.as_view()), + path("detail/obj/", views.ObjectDetail.as_view()), + path("detail/artist/<int:pk>/", views.ArtistDetail.as_view(), name="artist_detail"), + path("detail/author/<int:pk>/", views.AuthorDetail.as_view(), name="author_detail"), + path( + "detail/author/bycustompk/<foo>/", + views.AuthorDetail.as_view(pk_url_kwarg="foo"), + ), + path("detail/author/byslug/<slug>/", views.AuthorDetail.as_view()), + path( + "detail/author/bycustomslug/<foo>/", + views.AuthorDetail.as_view(slug_url_kwarg="foo"), + ), + path("detail/author/bypkignoreslug/<int:pk>-<slug>/", views.AuthorDetail.as_view()), + path( + "detail/author/bypkandslug/<int:pk>-<slug>/", + views.AuthorDetail.as_view(query_pk_and_slug=True), + ), + path( + "detail/author/<int:pk>/template_name_suffix/", + views.AuthorDetail.as_view(template_name_suffix="_view"), + ), + path( + "detail/author/<int:pk>/template_name/", + views.AuthorDetail.as_view(template_name="generic_views/about.html"), + ), + path( + "detail/author/<int:pk>/context_object_name/", + views.AuthorDetail.as_view(context_object_name="thingy"), + ), + path("detail/author/<int:pk>/custom_detail/", views.AuthorCustomDetail.as_view()), + path( + "detail/author/<int:pk>/dupe_context_object_name/", + views.AuthorDetail.as_view(context_object_name="object"), + ), + path("detail/page/<int:pk>/field/", views.PageDetail.as_view()), + path(r"detail/author/invalid/url/", views.AuthorDetail.as_view()), + path("detail/author/invalid/qs/", views.AuthorDetail.as_view(queryset=None)), + path("detail/nonmodel/1/", views.NonModelDetail.as_view()), + path("detail/doesnotexist/<pk>/", views.ObjectDoesNotExistDetail.as_view()), # FormView - path('contact/', views.ContactView.as_view()), - path('late-validation/', views.LateValidationView.as_view()), - + path("contact/", views.ContactView.as_view()), + path("late-validation/", views.LateValidationView.as_view()), # Create/UpdateView - path('edit/artists/create/', views.ArtistCreate.as_view()), - path('edit/artists/<int:pk>/update/', views.ArtistUpdate.as_view()), - - path('edit/authors/create/naive/', views.NaiveAuthorCreate.as_view()), - path('edit/authors/create/redirect/', views.NaiveAuthorCreate.as_view(success_url='/edit/authors/create/')), + path("edit/artists/create/", views.ArtistCreate.as_view()), + path("edit/artists/<int:pk>/update/", views.ArtistUpdate.as_view()), + path("edit/authors/create/naive/", views.NaiveAuthorCreate.as_view()), path( - 'edit/authors/create/interpolate_redirect/', - views.NaiveAuthorCreate.as_view(success_url='/edit/author/{id}/update/'), + "edit/authors/create/redirect/", + views.NaiveAuthorCreate.as_view(success_url="/edit/authors/create/"), ), path( - 'edit/authors/create/interpolate_redirect_nonascii/', - views.NaiveAuthorCreate.as_view(success_url='/%C3%A9dit/author/{id}/update/'), + "edit/authors/create/interpolate_redirect/", + views.NaiveAuthorCreate.as_view(success_url="/edit/author/{id}/update/"), ), - path('edit/authors/create/restricted/', views.AuthorCreateRestricted.as_view()), - re_path('^[eé]dit/authors/create/$', views.AuthorCreate.as_view()), - path('edit/authors/create/special/', views.SpecializedAuthorCreate.as_view()), - - path('edit/author/<int:pk>/update/naive/', views.NaiveAuthorUpdate.as_view()), path( - 'edit/author/<int:pk>/update/redirect/', - views.NaiveAuthorUpdate.as_view(success_url='/edit/authors/create/') + "edit/authors/create/interpolate_redirect_nonascii/", + views.NaiveAuthorCreate.as_view(success_url="/%C3%A9dit/author/{id}/update/"), ), + path("edit/authors/create/restricted/", views.AuthorCreateRestricted.as_view()), + re_path("^[eé]dit/authors/create/$", views.AuthorCreate.as_view()), + path("edit/authors/create/special/", views.SpecializedAuthorCreate.as_view()), + path("edit/author/<int:pk>/update/naive/", views.NaiveAuthorUpdate.as_view()), path( - 'edit/author/<int:pk>/update/interpolate_redirect/', - views.NaiveAuthorUpdate.as_view(success_url='/edit/author/{id}/update/') + "edit/author/<int:pk>/update/redirect/", + views.NaiveAuthorUpdate.as_view(success_url="/edit/authors/create/"), ), path( - 'edit/author/<int:pk>/update/interpolate_redirect_nonascii/', - views.NaiveAuthorUpdate.as_view(success_url='/%C3%A9dit/author/{id}/update/'), + "edit/author/<int:pk>/update/interpolate_redirect/", + views.NaiveAuthorUpdate.as_view(success_url="/edit/author/{id}/update/"), ), - re_path('^[eé]dit/author/(?P<pk>[0-9]+)/update/$', views.AuthorUpdate.as_view()), - path('edit/author/update/', views.OneAuthorUpdate.as_view()), - path('edit/author/<int:pk>/update/special/', views.SpecializedAuthorUpdate.as_view()), - path('edit/author/<int:pk>/delete/naive/', views.NaiveAuthorDelete.as_view()), path( - 'edit/author/<int:pk>/delete/redirect/', - views.NaiveAuthorDelete.as_view(success_url='/edit/authors/create/'), + "edit/author/<int:pk>/update/interpolate_redirect_nonascii/", + views.NaiveAuthorUpdate.as_view(success_url="/%C3%A9dit/author/{id}/update/"), ), + re_path("^[eé]dit/author/(?P<pk>[0-9]+)/update/$", views.AuthorUpdate.as_view()), + path("edit/author/update/", views.OneAuthorUpdate.as_view()), path( - 'edit/author/<int:pk>/delete/interpolate_redirect/', - views.NaiveAuthorDelete.as_view(success_url='/edit/authors/create/?deleted={id}') + "edit/author/<int:pk>/update/special/", views.SpecializedAuthorUpdate.as_view() ), + path("edit/author/<int:pk>/delete/naive/", views.NaiveAuthorDelete.as_view()), path( - 'edit/author/<int:pk>/delete/interpolate_redirect_nonascii/', - views.NaiveAuthorDelete.as_view(success_url='/%C3%A9dit/authors/create/?deleted={id}') + "edit/author/<int:pk>/delete/redirect/", + views.NaiveAuthorDelete.as_view(success_url="/edit/authors/create/"), ), - path('edit/author/<int:pk>/delete/', views.AuthorDelete.as_view()), - path('edit/author/<int:pk>/delete/special/', views.SpecializedAuthorDelete.as_view()), - path('edit/author/<int:pk>/delete/form/', views.AuthorDeleteFormView.as_view()), - + path( + "edit/author/<int:pk>/delete/interpolate_redirect/", + views.NaiveAuthorDelete.as_view( + success_url="/edit/authors/create/?deleted={id}" + ), + ), + path( + "edit/author/<int:pk>/delete/interpolate_redirect_nonascii/", + views.NaiveAuthorDelete.as_view( + success_url="/%C3%A9dit/authors/create/?deleted={id}" + ), + ), + path("edit/author/<int:pk>/delete/", views.AuthorDelete.as_view()), + path( + "edit/author/<int:pk>/delete/special/", views.SpecializedAuthorDelete.as_view() + ), + path("edit/author/<int:pk>/delete/form/", views.AuthorDeleteFormView.as_view()), # ArchiveIndexView - path('dates/books/', views.BookArchive.as_view()), - path('dates/books/context_object_name/', views.BookArchive.as_view(context_object_name='thingies')), - path('dates/books/allow_empty/', views.BookArchive.as_view(allow_empty=True)), - path('dates/books/template_name/', views.BookArchive.as_view(template_name='generic_views/list.html')), - path('dates/books/template_name_suffix/', views.BookArchive.as_view(template_name_suffix='_detail')), - path('dates/books/invalid/', views.BookArchive.as_view(queryset=None)), - path('dates/books/paginated/', views.BookArchive.as_view(paginate_by=10)), - path('dates/books/reverse/', views.BookArchive.as_view(queryset=Book.objects.order_by('pubdate'))), - path('dates/books/by_month/', views.BookArchive.as_view(date_list_period='month')), - path('dates/booksignings/', views.BookSigningArchive.as_view()), - path('dates/books/sortedbyname/', views.BookArchive.as_view(ordering='name')), - path('dates/books/sortedbynamedec/', views.BookArchive.as_view(ordering='-name')), - path('dates/books/without_date_field/', views.BookArchiveWithoutDateField.as_view()), - - + path("dates/books/", views.BookArchive.as_view()), + path( + "dates/books/context_object_name/", + views.BookArchive.as_view(context_object_name="thingies"), + ), + path("dates/books/allow_empty/", views.BookArchive.as_view(allow_empty=True)), + path( + "dates/books/template_name/", + views.BookArchive.as_view(template_name="generic_views/list.html"), + ), + path( + "dates/books/template_name_suffix/", + views.BookArchive.as_view(template_name_suffix="_detail"), + ), + path("dates/books/invalid/", views.BookArchive.as_view(queryset=None)), + path("dates/books/paginated/", views.BookArchive.as_view(paginate_by=10)), + path( + "dates/books/reverse/", + views.BookArchive.as_view(queryset=Book.objects.order_by("pubdate")), + ), + path("dates/books/by_month/", views.BookArchive.as_view(date_list_period="month")), + path("dates/booksignings/", views.BookSigningArchive.as_view()), + path("dates/books/sortedbyname/", views.BookArchive.as_view(ordering="name")), + path("dates/books/sortedbynamedec/", views.BookArchive.as_view(ordering="-name")), + path( + "dates/books/without_date_field/", views.BookArchiveWithoutDateField.as_view() + ), # ListView - path('list/dict/', views.DictList.as_view()), - path('list/dict/paginated/', views.DictList.as_view(paginate_by=1)), - path('list/artists/', views.ArtistList.as_view(), name='artists_list'), - path('list/authors/', views.AuthorList.as_view(), name='authors_list'), - path('list/authors/paginated/', views.AuthorList.as_view(paginate_by=30)), - path('list/authors/paginated/<int:page>/', views.AuthorList.as_view(paginate_by=30)), - path('list/authors/paginated-orphaned/', views.AuthorList.as_view(paginate_by=30, paginate_orphans=2)), - path('list/authors/notempty/', views.AuthorList.as_view(allow_empty=False)), - path('list/authors/notempty/paginated/', views.AuthorList.as_view(allow_empty=False, paginate_by=2)), - path('list/authors/template_name/', views.AuthorList.as_view(template_name='generic_views/list.html')), - path('list/authors/template_name_suffix/', views.AuthorList.as_view(template_name_suffix='_objects')), - path('list/authors/context_object_name/', views.AuthorList.as_view(context_object_name='author_list')), - path('list/authors/dupe_context_object_name/', views.AuthorList.as_view(context_object_name='object_list')), - path('list/authors/invalid/', views.AuthorList.as_view(queryset=None)), - path( - 'list/authors/get_queryset/', + path("list/dict/", views.DictList.as_view()), + path("list/dict/paginated/", views.DictList.as_view(paginate_by=1)), + path("list/artists/", views.ArtistList.as_view(), name="artists_list"), + path("list/authors/", views.AuthorList.as_view(), name="authors_list"), + path("list/authors/paginated/", views.AuthorList.as_view(paginate_by=30)), + path( + "list/authors/paginated/<int:page>/", views.AuthorList.as_view(paginate_by=30) + ), + path( + "list/authors/paginated-orphaned/", + views.AuthorList.as_view(paginate_by=30, paginate_orphans=2), + ), + path("list/authors/notempty/", views.AuthorList.as_view(allow_empty=False)), + path( + "list/authors/notempty/paginated/", + views.AuthorList.as_view(allow_empty=False, paginate_by=2), + ), + path( + "list/authors/template_name/", + views.AuthorList.as_view(template_name="generic_views/list.html"), + ), + path( + "list/authors/template_name_suffix/", + views.AuthorList.as_view(template_name_suffix="_objects"), + ), + path( + "list/authors/context_object_name/", + views.AuthorList.as_view(context_object_name="author_list"), + ), + path( + "list/authors/dupe_context_object_name/", + views.AuthorList.as_view(context_object_name="object_list"), + ), + path("list/authors/invalid/", views.AuthorList.as_view(queryset=None)), + path( + "list/authors/get_queryset/", views.AuthorListGetQuerysetReturnsNone.as_view(), ), path( - 'list/authors/paginated/custom_class/', + "list/authors/paginated/custom_class/", views.AuthorList.as_view(paginate_by=5, paginator_class=views.CustomPaginator), ), - path('list/authors/paginated/custom_page_kwarg/', views.AuthorList.as_view(paginate_by=30, page_kwarg='pagina')), - path('list/authors/paginated/custom_constructor/', views.AuthorListCustomPaginator.as_view()), - path('list/books/sorted/', views.BookList.as_view(ordering='name')), - path('list/books/sortedbypagesandnamedec/', views.BookList.as_view(ordering=('pages', '-name'))), - + path( + "list/authors/paginated/custom_page_kwarg/", + views.AuthorList.as_view(paginate_by=30, page_kwarg="pagina"), + ), + path( + "list/authors/paginated/custom_constructor/", + views.AuthorListCustomPaginator.as_view(), + ), + path("list/books/sorted/", views.BookList.as_view(ordering="name")), + path( + "list/books/sortedbypagesandnamedec/", + views.BookList.as_view(ordering=("pages", "-name")), + ), # YearArchiveView # Mixing keyword and positional captures below is intentional; the views # ought to be able to accept either. - path('dates/books/<int:year>/', views.BookYearArchive.as_view()), - path('dates/books/<int:year>/make_object_list/', views.BookYearArchive.as_view(make_object_list=True)), - path('dates/books/<int:year>/allow_empty/', views.BookYearArchive.as_view(allow_empty=True)), - path('dates/books/<int:year>/allow_future/', views.BookYearArchive.as_view(allow_future=True)), - path('dates/books/<int:year>/paginated/', views.BookYearArchive.as_view(make_object_list=True, paginate_by=30)), + path("dates/books/<int:year>/", views.BookYearArchive.as_view()), path( - 'dates/books/<int:year>/sortedbyname/', - views.BookYearArchive.as_view(make_object_list=True, ordering='name'), + "dates/books/<int:year>/make_object_list/", + views.BookYearArchive.as_view(make_object_list=True), ), path( - 'dates/books/<int:year>/sortedbypageandnamedec/', - views.BookYearArchive.as_view(make_object_list=True, ordering=('pages', '-name')), + "dates/books/<int:year>/allow_empty/", + views.BookYearArchive.as_view(allow_empty=True), ), - path('dates/books/no_year/', views.BookYearArchive.as_view()), - path('dates/books/<int:year>/reverse/', views.BookYearArchive.as_view(queryset=Book.objects.order_by('pubdate'))), - path('dates/booksignings/<int:year>/', views.BookSigningYearArchive.as_view()), - + path( + "dates/books/<int:year>/allow_future/", + views.BookYearArchive.as_view(allow_future=True), + ), + path( + "dates/books/<int:year>/paginated/", + views.BookYearArchive.as_view(make_object_list=True, paginate_by=30), + ), + path( + "dates/books/<int:year>/sortedbyname/", + views.BookYearArchive.as_view(make_object_list=True, ordering="name"), + ), + path( + "dates/books/<int:year>/sortedbypageandnamedec/", + views.BookYearArchive.as_view( + make_object_list=True, ordering=("pages", "-name") + ), + ), + path("dates/books/no_year/", views.BookYearArchive.as_view()), + path( + "dates/books/<int:year>/reverse/", + views.BookYearArchive.as_view(queryset=Book.objects.order_by("pubdate")), + ), + path("dates/booksignings/<int:year>/", views.BookSigningYearArchive.as_view()), # MonthArchiveView - path('dates/books/<int:year>/<int:month>/', views.BookMonthArchive.as_view(month_format='%m')), - path('dates/books/<int:year>/<month>/', views.BookMonthArchive.as_view()), - path('dates/books/without_month/<int:year>/', views.BookMonthArchive.as_view()), - path('dates/books/<int:year>/<month>/allow_empty/', views.BookMonthArchive.as_view(allow_empty=True)), - path('dates/books/<int:year>/<month>/allow_future/', views.BookMonthArchive.as_view(allow_future=True)), - path('dates/books/<int:year>/<month>/paginated/', views.BookMonthArchive.as_view(paginate_by=30)), - path('dates/books/<int:year>/no_month/', views.BookMonthArchive.as_view()), - path('dates/booksignings/<int:year>/<month>/', views.BookSigningMonthArchive.as_view()), - + path( + "dates/books/<int:year>/<int:month>/", + views.BookMonthArchive.as_view(month_format="%m"), + ), + path("dates/books/<int:year>/<month>/", views.BookMonthArchive.as_view()), + path("dates/books/without_month/<int:year>/", views.BookMonthArchive.as_view()), + path( + "dates/books/<int:year>/<month>/allow_empty/", + views.BookMonthArchive.as_view(allow_empty=True), + ), + path( + "dates/books/<int:year>/<month>/allow_future/", + views.BookMonthArchive.as_view(allow_future=True), + ), + path( + "dates/books/<int:year>/<month>/paginated/", + views.BookMonthArchive.as_view(paginate_by=30), + ), + path("dates/books/<int:year>/no_month/", views.BookMonthArchive.as_view()), + path( + "dates/booksignings/<int:year>/<month>/", + views.BookSigningMonthArchive.as_view(), + ), # WeekArchiveView - path('dates/books/<int:year>/week/<int:week>/', views.BookWeekArchive.as_view()), - path('dates/books/<int:year>/week/<int:week>/allow_empty/', views.BookWeekArchive.as_view(allow_empty=True)), - path('dates/books/<int:year>/week/<int:week>/allow_future/', views.BookWeekArchive.as_view(allow_future=True)), - path('dates/books/<int:year>/week/<int:week>/paginated/', views.BookWeekArchive.as_view(paginate_by=30)), - path('dates/books/<int:year>/week/no_week/', views.BookWeekArchive.as_view()), - path('dates/books/<int:year>/week/<int:week>/monday/', views.BookWeekArchive.as_view(week_format='%W')), + path("dates/books/<int:year>/week/<int:week>/", views.BookWeekArchive.as_view()), path( - 'dates/books/<int:year>/week/<int:week>/unknown_week_format/', - views.BookWeekArchive.as_view(week_format='%T'), + "dates/books/<int:year>/week/<int:week>/allow_empty/", + views.BookWeekArchive.as_view(allow_empty=True), ), path( - 'dates/books/<int:year>/week/<int:week>/iso_format/', - views.BookWeekArchive.as_view(year_format='%G', week_format='%V'), + "dates/books/<int:year>/week/<int:week>/allow_future/", + views.BookWeekArchive.as_view(allow_future=True), ), path( - 'dates/books/<int:year>/week/<int:week>/invalid_iso_week_year_format/', - views.BookWeekArchive.as_view(week_format='%V'), + "dates/books/<int:year>/week/<int:week>/paginated/", + views.BookWeekArchive.as_view(paginate_by=30), + ), + path("dates/books/<int:year>/week/no_week/", views.BookWeekArchive.as_view()), + path( + "dates/books/<int:year>/week/<int:week>/monday/", + views.BookWeekArchive.as_view(week_format="%W"), + ), + path( + "dates/books/<int:year>/week/<int:week>/unknown_week_format/", + views.BookWeekArchive.as_view(week_format="%T"), + ), + path( + "dates/books/<int:year>/week/<int:week>/iso_format/", + views.BookWeekArchive.as_view(year_format="%G", week_format="%V"), + ), + path( + "dates/books/<int:year>/week/<int:week>/invalid_iso_week_year_format/", + views.BookWeekArchive.as_view(week_format="%V"), + ), + path( + "dates/booksignings/<int:year>/week/<int:week>/", + views.BookSigningWeekArchive.as_view(), ), - path('dates/booksignings/<int:year>/week/<int:week>/', views.BookSigningWeekArchive.as_view()), - # DayArchiveView - path('dates/books/<int:year>/<int:month>/<int:day>/', views.BookDayArchive.as_view(month_format='%m')), - path('dates/books/<int:year>/<month>/<int:day>/', views.BookDayArchive.as_view()), - path('dates/books/<int:year>/<month>/<int:day>/allow_empty/', views.BookDayArchive.as_view(allow_empty=True)), - path('dates/books/<int:year>/<month>/<int:day>/allow_future/', views.BookDayArchive.as_view(allow_future=True)), path( - 'dates/books/<int:year>/<month>/<int:day>/allow_empty_and_future/', + "dates/books/<int:year>/<int:month>/<int:day>/", + views.BookDayArchive.as_view(month_format="%m"), + ), + path("dates/books/<int:year>/<month>/<int:day>/", views.BookDayArchive.as_view()), + path( + "dates/books/<int:year>/<month>/<int:day>/allow_empty/", + views.BookDayArchive.as_view(allow_empty=True), + ), + path( + "dates/books/<int:year>/<month>/<int:day>/allow_future/", + views.BookDayArchive.as_view(allow_future=True), + ), + path( + "dates/books/<int:year>/<month>/<int:day>/allow_empty_and_future/", views.BookDayArchive.as_view(allow_empty=True, allow_future=True), ), - path('dates/books/<int:year>/<month>/<int:day>/paginated/', views.BookDayArchive.as_view(paginate_by=True)), - path('dates/books/<int:year>/<month>/no_day/', views.BookDayArchive.as_view()), - path('dates/booksignings/<int:year>/<month>/<int:day>/', views.BookSigningDayArchive.as_view()), - + path( + "dates/books/<int:year>/<month>/<int:day>/paginated/", + views.BookDayArchive.as_view(paginate_by=True), + ), + path("dates/books/<int:year>/<month>/no_day/", views.BookDayArchive.as_view()), + path( + "dates/booksignings/<int:year>/<month>/<int:day>/", + views.BookSigningDayArchive.as_view(), + ), # TodayArchiveView - path('dates/books/today/', views.BookTodayArchive.as_view()), - path('dates/books/today/allow_empty/', views.BookTodayArchive.as_view(allow_empty=True)), - path('dates/booksignings/today/', views.BookSigningTodayArchive.as_view()), - + path("dates/books/today/", views.BookTodayArchive.as_view()), + path( + "dates/books/today/allow_empty/", + views.BookTodayArchive.as_view(allow_empty=True), + ), + path("dates/booksignings/today/", views.BookSigningTodayArchive.as_view()), # DateDetailView - path('dates/books/<int:year>/<int:month>/<day>/<int:pk>/', views.BookDetail.as_view(month_format='%m')), - path('dates/books/<int:year>/<month>/<day>/<int:pk>/', views.BookDetail.as_view()), path( - 'dates/books/<int:year>/<month>/<int:day>/<int:pk>/allow_future/', + "dates/books/<int:year>/<int:month>/<day>/<int:pk>/", + views.BookDetail.as_view(month_format="%m"), + ), + path("dates/books/<int:year>/<month>/<day>/<int:pk>/", views.BookDetail.as_view()), + path( + "dates/books/<int:year>/<month>/<int:day>/<int:pk>/allow_future/", views.BookDetail.as_view(allow_future=True), ), - path('dates/books/<int:year>/<month>/<int:day>/nopk/', views.BookDetail.as_view()), - - path('dates/books/<int:year>/<month>/<int:day>/byslug/<slug:slug>/', views.BookDetail.as_view()), - + path("dates/books/<int:year>/<month>/<int:day>/nopk/", views.BookDetail.as_view()), path( - 'dates/books/get_object_custom_queryset/<int:year>/<month>/<int:day>/<int:pk>/', + "dates/books/<int:year>/<month>/<int:day>/byslug/<slug:slug>/", + views.BookDetail.as_view(), + ), + path( + "dates/books/get_object_custom_queryset/<int:year>/<month>/<int:day>/<int:pk>/", views.BookDetailGetObjectCustomQueryset.as_view(), ), - - path('dates/booksignings/<int:year>/<month>/<int:day>/<int:pk>/', views.BookSigningDetail.as_view()), - + path( + "dates/booksignings/<int:year>/<month>/<int:day>/<int:pk>/", + views.BookSigningDetail.as_view(), + ), # Useful for testing redirects - path('accounts/login/', auth_views.LoginView.as_view()), - - path('BaseDateListViewTest/', dates.BaseDateListView.as_view()), + path("accounts/login/", auth_views.LoginView.as_view()), + path("BaseDateListViewTest/", dates.BaseDateListView.as_view()), ] diff --git a/tests/generic_views/views.py b/tests/generic_views/views.py index 8f3de97388..5c4c9739d2 100644 --- a/tests/generic_views/views.py +++ b/tests/generic_views/views.py @@ -9,19 +9,19 @@ from .models import Artist, Author, Book, BookSigning, Page class CustomTemplateView(generic.TemplateView): - template_name = 'generic_views/about.html' + template_name = "generic_views/about.html" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context.update({'key': 'value'}) + context.update({"key": "value"}) return context class ObjectDetail(generic.DetailView): - template_name = 'generic_views/detail.html' + template_name = "generic_views/detail.html" def get_object(self): - return {'foo': 'bar'} + return {"foo": "bar"} class ArtistDetail(generic.DetailView): @@ -33,32 +33,30 @@ class AuthorDetail(generic.DetailView): class AuthorCustomDetail(generic.DetailView): - template_name = 'generic_views/author_detail.html' + template_name = "generic_views/author_detail.html" queryset = Author.objects.all() def get(self, request, *args, **kwargs): # Ensures get_context_object_name() doesn't reference self.object. author = self.get_object() - context = {'custom_' + self.get_context_object_name(author): author} + context = {"custom_" + self.get_context_object_name(author): author} return self.render_to_response(context) class PageDetail(generic.DetailView): queryset = Page.objects.all() - template_name_field = 'template' + template_name_field = "template" class DictList(generic.ListView): """A ListView that doesn't use a model.""" - queryset = [ - {'first': 'John', 'last': 'Lennon'}, - {'first': 'Yoko', 'last': 'Ono'} - ] - template_name = 'generic_views/list.html' + + queryset = [{"first": "John", "last": "Lennon"}, {"first": "Yoko", "last": "Ono"}] + template_name = "generic_views/list.html" class ArtistList(generic.ListView): - template_name = 'generic_views/list.html' + template_name = "generic_views/list.html" queryset = Artist.objects.all() @@ -77,33 +75,47 @@ class BookList(generic.ListView): class CustomPaginator(Paginator): def __init__(self, queryset, page_size, orphans=0, allow_empty_first_page=True): - super().__init__(queryset, page_size, orphans=2, allow_empty_first_page=allow_empty_first_page) + super().__init__( + queryset, + page_size, + orphans=2, + allow_empty_first_page=allow_empty_first_page, + ) class AuthorListCustomPaginator(AuthorList): paginate_by = 5 - def get_paginator(self, queryset, page_size, orphans=0, allow_empty_first_page=True): - return super().get_paginator(queryset, page_size, orphans=2, allow_empty_first_page=allow_empty_first_page) + def get_paginator( + self, queryset, page_size, orphans=0, allow_empty_first_page=True + ): + return super().get_paginator( + queryset, + page_size, + orphans=2, + allow_empty_first_page=allow_empty_first_page, + ) class ContactView(generic.FormView): form_class = ContactForm - success_url = reverse_lazy('authors_list') - template_name = 'generic_views/form.html' + success_url = reverse_lazy("authors_list") + template_name = "generic_views/form.html" class ArtistCreate(generic.CreateView): model = Artist - fields = '__all__' + fields = "__all__" class NaiveAuthorCreate(generic.CreateView): queryset = Author.objects.all() - fields = '__all__' + fields = "__all__" -class TemplateResponseWithoutTemplate(generic.detail.SingleObjectTemplateResponseMixin, generic.View): +class TemplateResponseWithoutTemplate( + generic.detail.SingleObjectTemplateResponseMixin, generic.View +): # we don't define the usual template_name here def __init__(self): @@ -113,18 +125,18 @@ class TemplateResponseWithoutTemplate(generic.detail.SingleObjectTemplateRespons class AuthorCreate(generic.CreateView): model = Author - success_url = '/list/authors/' - fields = '__all__' + success_url = "/list/authors/" + fields = "__all__" class SpecializedAuthorCreate(generic.CreateView): model = Author form_class = AuthorForm - template_name = 'generic_views/form.html' - context_object_name = 'thingy' + template_name = "generic_views/form.html" + context_object_name = "thingy" def get_success_url(self): - return reverse('author_detail', args=[self.object.id]) + return reverse("author_detail", args=[self.object.id]) class AuthorCreateRestricted(AuthorCreate): @@ -133,19 +145,19 @@ class AuthorCreateRestricted(AuthorCreate): class ArtistUpdate(generic.UpdateView): model = Artist - fields = '__all__' + fields = "__all__" class NaiveAuthorUpdate(generic.UpdateView): queryset = Author.objects.all() - fields = '__all__' + fields = "__all__" class AuthorUpdate(generic.UpdateView): get_form_called_count = 0 # Used to ensure get_form() is called once. model = Author - success_url = '/list/authors/' - fields = '__all__' + success_url = "/list/authors/" + fields = "__all__" def get_form(self, *args, **kwargs): self.get_form_called_count += 1 @@ -153,8 +165,8 @@ class AuthorUpdate(generic.UpdateView): class OneAuthorUpdate(generic.UpdateView): - success_url = '/list/authors/' - fields = '__all__' + success_url = "/list/authors/" + fields = "__all__" def get_object(self): return Author.objects.get(pk=1) @@ -163,11 +175,11 @@ class OneAuthorUpdate(generic.UpdateView): class SpecializedAuthorUpdate(generic.UpdateView): model = Author form_class = AuthorForm - template_name = 'generic_views/form.html' - context_object_name = 'thingy' + template_name = "generic_views/form.html" + context_object_name = "thingy" def get_success_url(self): - return reverse('author_detail', args=[self.object.id]) + return reverse("author_detail", args=[self.object.id]) class NaiveAuthorDelete(generic.DeleteView): @@ -176,7 +188,7 @@ class NaiveAuthorDelete(generic.DeleteView): class AuthorDelete(generic.DeleteView): model = Author - success_url = '/list/authors/' + success_url = "/list/authors/" class AuthorDeleteFormView(generic.DeleteView): @@ -184,19 +196,19 @@ class AuthorDeleteFormView(generic.DeleteView): form_class = ConfirmDeleteForm def get_success_url(self): - return reverse('authors_list') + return reverse("authors_list") class SpecializedAuthorDelete(generic.DeleteView): queryset = Author.objects.all() - template_name = 'generic_views/confirm_delete.html' - context_object_name = 'thingy' - success_url = reverse_lazy('authors_list') + template_name = "generic_views/confirm_delete.html" + context_object_name = "thingy" + success_url = reverse_lazy("authors_list") class BookConfig: queryset = Book.objects.all() - date_field = 'pubdate' + date_field = "pubdate" class BookArchive(BookConfig, generic.ArchiveIndexView): @@ -228,7 +240,7 @@ class BookDetail(BookConfig, generic.DateDetailView): class AuthorGetQuerySetFormView(generic.edit.ModelFormMixin): - fields = '__all__' + fields = "__all__" def get_queryset(self): return Author.objects.all() @@ -236,13 +248,13 @@ class AuthorGetQuerySetFormView(generic.edit.ModelFormMixin): class BookDetailGetObjectCustomQueryset(BookDetail): def get_object(self, queryset=None): - return super().get_object(queryset=Book.objects.filter(pk=self.kwargs['pk'])) + return super().get_object(queryset=Book.objects.filter(pk=self.kwargs["pk"])) class CustomMultipleObjectMixinView(generic.list.MultipleObjectMixin, generic.View): queryset = [ - {'name': 'John'}, - {'name': 'Yoko'}, + {"name": "John"}, + {"name": "Yoko"}, ] def get(self, request): @@ -251,13 +263,13 @@ class CustomMultipleObjectMixinView(generic.list.MultipleObjectMixin, generic.Vi class CustomContextView(generic.detail.SingleObjectMixin, generic.View): model = Book - object = Book(name='dummy') + object = Book(name="dummy") def get_object(self): return Book(name="dummy") def get_context_data(self, **kwargs): - context = {'custom_key': 'custom_value'} + context = {"custom_key": "custom_value"} context.update(kwargs) return super().get_context_data(**context) @@ -272,11 +284,11 @@ class CustomSingleObjectView(generic.detail.SingleObjectMixin, generic.View): class BookSigningConfig: model = BookSigning - date_field = 'event_date' + date_field = "event_date" # use the same templates as for books def get_template_names(self): - return ['generic_views/book%s.html' % self.template_name_suffix] + return ["generic_views/book%s.html" % self.template_name_suffix] class BookSigningArchive(BookSigningConfig, generic.ArchiveIndexView): @@ -308,7 +320,7 @@ class BookArchiveWithoutDateField(generic.ArchiveIndexView): class BookSigningDetail(BookSigningConfig, generic.DateDetailView): - context_object_name = 'book' + context_object_name = "book" class NonModel: @@ -319,7 +331,7 @@ class NonModel: class NonModelDetail(generic.DetailView): - template_name = 'generic_views/detail.html' + template_name = "generic_views/detail.html" model = NonModel def get_object(self, queryset=None): @@ -333,9 +345,9 @@ class ObjectDoesNotExistDetail(generic.DetailView): class LateValidationView(generic.FormView): form_class = ContactForm - success_url = reverse_lazy('authors_list') - template_name = 'generic_views/form.html' + success_url = reverse_lazy("authors_list") + template_name = "generic_views/form.html" def form_valid(self, form): - form.add_error(None, 'There is an error') + form.add_error(None, "There is an error") return self.form_invalid(form) |