diff options
author | Arthur Koziel <arthur@arthurkoziel.com> | 2010-09-13 00:04:27 +0000 |
---|---|---|
committer | Arthur Koziel <arthur@arthurkoziel.com> | 2010-09-13 00:04:27 +0000 |
commit | dd49269c7db008b2567f50cb03c4d3d9b321daa1 (patch) | |
tree | 326dd25bb045ac016cda7966b43cbdfe1f67d699 /django/contrib/flatpages | |
parent | c9b188c4ec939abbe48dae5a371276742e64b6b8 (diff) | |
download | django-soc2010/app-loading.tar.gz |
[soc2010/app-loading] merged trunkarchive/soc2010/app-loadingsoc2010/app-loading
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2010/app-loading@13818 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/contrib/flatpages')
-rw-r--r-- | django/contrib/flatpages/admin.py | 4 | ||||
-rw-r--r-- | django/contrib/flatpages/fixtures/sample_flatpages.json | 63 | ||||
-rw-r--r-- | django/contrib/flatpages/templatetags/__init__.py | 0 | ||||
-rw-r--r-- | django/contrib/flatpages/templatetags/flatpages.py | 99 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/__init__.py | 5 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/csrf.py | 76 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/forms.py | 22 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/middleware.py | 67 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/templates/404.html | 1 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/templates/flatpages/default.html | 10 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/templates/registration/login.html | 0 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/templatetags.py | 134 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/urls.py | 8 | ||||
-rw-r--r-- | django/contrib/flatpages/tests/views.py | 72 | ||||
-rw-r--r-- | django/contrib/flatpages/views.py | 14 |
15 files changed, 571 insertions, 4 deletions
diff --git a/django/contrib/flatpages/admin.py b/django/contrib/flatpages/admin.py index b6fdba3d53..1b377e967b 100644 --- a/django/contrib/flatpages/admin.py +++ b/django/contrib/flatpages/admin.py @@ -5,11 +5,11 @@ from django.utils.translation import ugettext_lazy as _ class FlatpageForm(forms.ModelForm): - url = forms.RegexField(label=_("URL"), max_length=100, regex=r'^[-\w/]+$', + url = forms.RegexField(label=_("URL"), max_length=100, regex=r'^[-\w/\.~]+$', help_text = _("Example: '/about/contact/'. Make sure to have leading" " and trailing slashes."), error_message = _("This value must contain only letters, numbers," - " underscores, dashes or slashes.")) + " dots, underscores, dashes, slashes or tildes.")) class Meta: model = FlatPage diff --git a/django/contrib/flatpages/fixtures/sample_flatpages.json b/django/contrib/flatpages/fixtures/sample_flatpages.json new file mode 100644 index 0000000000..885af1eb60 --- /dev/null +++ b/django/contrib/flatpages/fixtures/sample_flatpages.json @@ -0,0 +1,63 @@ +[ + { + "pk": 1, + "model": "flatpages.flatpage", + "fields": { + "registration_required": false, + "title": "A Flatpage", + "url": "/flatpage/", + "template_name": "", + "sites": [ + 1 + ], + "content": "Isn't it flat!", + "enable_comments": false + } + }, + { + "pk": 2, + "model": "flatpages.flatpage", + "fields": { + "registration_required": false, + "title": "A Nested Flatpage", + "url": "/location/flatpage/", + "template_name": "", + "sites": [ + 1 + ], + "content": "Isn't it flat and deep!", + "enable_comments": false + } + }, + + { + "pk": 101, + "model": "flatpages.flatpage", + "fields": { + "registration_required": true, + "title": "Sekrit Flatpage", + "url": "/sekrit/", + "template_name": "", + "sites": [ + 1 + ], + "content": "Isn't it sekrit!", + "enable_comments": false + } + }, + { + "pk": 102, + "model": "flatpages.flatpage", + "fields": { + "registration_required": true, + "title": "Sekrit Nested Flatpage", + "url": "/location/sekrit/", + "template_name": "", + "sites": [ + 1 + ], + "content": "Isn't it sekrit and deep!", + "enable_comments": false + } + } +]
\ No newline at end of file diff --git a/django/contrib/flatpages/templatetags/__init__.py b/django/contrib/flatpages/templatetags/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/django/contrib/flatpages/templatetags/__init__.py diff --git a/django/contrib/flatpages/templatetags/flatpages.py b/django/contrib/flatpages/templatetags/flatpages.py new file mode 100644 index 0000000000..5c76699b79 --- /dev/null +++ b/django/contrib/flatpages/templatetags/flatpages.py @@ -0,0 +1,99 @@ +from django import template +from django.contrib.flatpages.models import FlatPage +from django.utils.translation import ugettext as _ +from django.conf import settings + + +register = template.Library() + + +class FlatpageNode(template.Node): + def __init__(self, context_name, starts_with=None, user=None): + self.context_name = context_name + if starts_with: + self.starts_with = template.Variable(starts_with) + else: + self.starts_with = None + if user: + self.user = template.Variable(user) + else: + self.user = None + + def render(self, context): + flatpages = FlatPage.objects.filter(sites__id=settings.SITE_ID) + # If a prefix was specified, add a filter + if self.starts_with: + flatpages = flatpages.filter( + url__startswith=self.starts_with.resolve(context)) + + # If the provided user is not authenticated, or no user + # was provided, filter the list to only public flatpages. + if self.user: + user = self.user.resolve(context) + if not user.is_authenticated(): + flatpages = flatpages.filter(registration_required=False) + else: + flatpages = flatpages.filter(registration_required=False) + + context[self.context_name] = flatpages + return '' + + +def get_flatpages(parser, token): + """ + Retrieves all flatpage objects available for the current site and + visible to the specific user (or visible to all users if no user is + specified). Populates the template context with them in a variable + whose name is defined by the ``as`` clause. + + An optional ``for`` clause can be used to control the user whose + permissions are to be used in determining which flatpages are visible. + + An optional argument, ``starts_with``, can be applied to limit the + returned flatpages to those beginning with a particular base URL. + This argument can be passed as a variable or a string, as it resolves + from the template context. + + Syntax:: + + {% get_flatpages ['url_starts_with'] [for user] as context_name %} + + Example usage:: + + {% get_flatpages as flatpages %} + {% get_flatpages for someuser as flatpages %} + {% get_flatpages '/about/' as about_pages %} + {% get_flatpages prefix as about_pages %} + {% get_flatpages '/about/' for someuser as about_pages %} + """ + bits = token.split_contents() + syntax_message = _("%(tag_name)s expects a syntax of %(tag_name)s " + "['url_starts_with'] [for user] as context_name" % + dict(tag_name=bits[0])) + # Must have at 3-6 bits in the tag + if len(bits) >= 3 and len(bits) <= 6: + + # If there's an even number of bits, there's no prefix + if len(bits) % 2 == 0: + prefix = bits[1] + else: + prefix = None + + # The very last bit must be the context name + if bits[-2] != 'as': + raise template.TemplateSyntaxError(syntax_message) + context_name = bits[-1] + + # If there are 5 or 6 bits, there is a user defined + if len(bits) >= 5: + if bits[-4] != 'for': + raise template.TemplateSyntaxError(syntax_message) + user = bits[-3] + else: + user = None + + return FlatpageNode(context_name, starts_with=prefix, user=user) + else: + raise template.TemplateSyntaxError(syntax_message) + +register.tag('get_flatpages', get_flatpages) diff --git a/django/contrib/flatpages/tests/__init__.py b/django/contrib/flatpages/tests/__init__.py new file mode 100644 index 0000000000..5dd5e89dca --- /dev/null +++ b/django/contrib/flatpages/tests/__init__.py @@ -0,0 +1,5 @@ +from django.contrib.flatpages.tests.csrf import * +from django.contrib.flatpages.tests.forms import * +from django.contrib.flatpages.tests.middleware import * +from django.contrib.flatpages.tests.templatetags import * +from django.contrib.flatpages.tests.views import * diff --git a/django/contrib/flatpages/tests/csrf.py b/django/contrib/flatpages/tests/csrf.py new file mode 100644 index 0000000000..b65ee382a6 --- /dev/null +++ b/django/contrib/flatpages/tests/csrf.py @@ -0,0 +1,76 @@ +import os +from django.conf import settings +from django.contrib.auth.models import User +from django.test import TestCase, Client + +class FlatpageCSRFTests(TestCase): + fixtures = ['sample_flatpages'] + urls = 'django.contrib.flatpages.tests.urls' + + def setUp(self): + self.client = Client(enforce_csrf_checks=True) + self.old_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES + flatpage_middleware_class = 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' + csrf_middleware_class = 'django.middleware.csrf.CsrfViewMiddleware' + if csrf_middleware_class not in settings.MIDDLEWARE_CLASSES: + settings.MIDDLEWARE_CLASSES += (csrf_middleware_class,) + if flatpage_middleware_class not in settings.MIDDLEWARE_CLASSES: + settings.MIDDLEWARE_CLASSES += (flatpage_middleware_class,) + self.old_TEMPLATE_DIRS = settings.TEMPLATE_DIRS + settings.TEMPLATE_DIRS = ( + os.path.join( + os.path.dirname(__file__), + 'templates' + ), + ) + + def tearDown(self): + settings.MIDDLEWARE_CLASSES = self.old_MIDDLEWARE_CLASSES + settings.TEMPLATE_DIRS = self.old_TEMPLATE_DIRS + + def test_view_flatpage(self): + "A flatpage can be served through a view, even when the middleware is in use" + response = self.client.get('/flatpage_root/flatpage/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it flat!</p>") + + def test_view_non_existent_flatpage(self): + "A non-existent flatpage raises 404 when served through a view, even when the middleware is in use" + response = self.client.get('/flatpage_root/no_such_flatpage/') + self.assertEquals(response.status_code, 404) + + def test_view_authenticated_flatpage(self): + "A flatpage served through a view can require authentication" + response = self.client.get('/flatpage_root/sekrit/') + self.assertRedirects(response, '/accounts/login/?next=/flatpage_root/sekrit/') + User.objects.create_user('testuser', 'test@example.com', 's3krit') + self.client.login(username='testuser',password='s3krit') + response = self.client.get('/flatpage_root/sekrit/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it sekrit!</p>") + + def test_fallback_flatpage(self): + "A flatpage can be served by the fallback middlware" + response = self.client.get('/flatpage/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it flat!</p>") + + def test_fallback_non_existent_flatpage(self): + "A non-existent flatpage raises a 404 when served by the fallback middlware" + response = self.client.get('/no_such_flatpage/') + self.assertEquals(response.status_code, 404) + + def test_post_view_flatpage(self): + "POSTing to a flatpage served through a view will raise a CSRF error if no token is provided (Refs #14156)" + response = self.client.post('/flatpage_root/flatpage/') + self.assertEquals(response.status_code, 403) + + def test_post_fallback_flatpage(self): + "POSTing to a flatpage served by the middleware will raise a CSRF error if no token is provided (Refs #14156)" + response = self.client.post('/flatpage/') + self.assertEquals(response.status_code, 403) + + def test_post_unknown_page(self): + "POSTing to an unknown page isn't caught as a 403 CSRF error" + response = self.client.post('/no_such_page/') + self.assertEquals(response.status_code, 404) diff --git a/django/contrib/flatpages/tests/forms.py b/django/contrib/flatpages/tests/forms.py new file mode 100644 index 0000000000..969d347b39 --- /dev/null +++ b/django/contrib/flatpages/tests/forms.py @@ -0,0 +1,22 @@ +from django.contrib.flatpages.admin import FlatpageForm +from django.test import TestCase + +class FlatpageAdminFormTests(TestCase): + def setUp(self): + self.form_data = { + 'title': "A test page", + 'content': "This is a test", + 'sites': [1], + } + + def test_flatpage_admin_form_url_validation(self): + "The flatpage admin form validates correctly validates urls" + self.assertTrue(FlatpageForm(data=dict(url='/new_flatpage/', **self.form_data)).is_valid()) + self.assertTrue(FlatpageForm(data=dict(url='/some.special~chars/', **self.form_data)).is_valid()) + self.assertTrue(FlatpageForm(data=dict(url='/some.very_special~chars-here/', **self.form_data)).is_valid()) + + self.assertFalse(FlatpageForm(data=dict(url='/a space/', **self.form_data)).is_valid()) + self.assertFalse(FlatpageForm(data=dict(url='/a % char/', **self.form_data)).is_valid()) + self.assertFalse(FlatpageForm(data=dict(url='/a ! char/', **self.form_data)).is_valid()) + self.assertFalse(FlatpageForm(data=dict(url='/a & char/', **self.form_data)).is_valid()) + self.assertFalse(FlatpageForm(data=dict(url='/a ? char/', **self.form_data)).is_valid()) diff --git a/django/contrib/flatpages/tests/middleware.py b/django/contrib/flatpages/tests/middleware.py new file mode 100644 index 0000000000..bedaffc8ac --- /dev/null +++ b/django/contrib/flatpages/tests/middleware.py @@ -0,0 +1,67 @@ +import os +from django.conf import settings +from django.contrib.auth.models import User +from django.test import TestCase + +class FlatpageMiddlewareTests(TestCase): + fixtures = ['sample_flatpages'] + urls = 'django.contrib.flatpages.tests.urls' + + def setUp(self): + self.old_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES + flatpage_middleware_class = 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' + if flatpage_middleware_class not in settings.MIDDLEWARE_CLASSES: + settings.MIDDLEWARE_CLASSES += (flatpage_middleware_class,) + self.old_TEMPLATE_DIRS = settings.TEMPLATE_DIRS + settings.TEMPLATE_DIRS = ( + os.path.join( + os.path.dirname(__file__), + 'templates' + ), + ) + + def tearDown(self): + settings.MIDDLEWARE_CLASSES = self.old_MIDDLEWARE_CLASSES + settings.TEMPLATE_DIRS = self.old_TEMPLATE_DIRS + + def test_view_flatpage(self): + "A flatpage can be served through a view, even when the middleware is in use" + response = self.client.get('/flatpage_root/flatpage/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it flat!</p>") + + def test_view_non_existent_flatpage(self): + "A non-existent flatpage raises 404 when served through a view, even when the middleware is in use" + response = self.client.get('/flatpage_root/no_such_flatpage/') + self.assertEquals(response.status_code, 404) + + def test_view_authenticated_flatpage(self): + "A flatpage served through a view can require authentication" + response = self.client.get('/flatpage_root/sekrit/') + self.assertRedirects(response, '/accounts/login/?next=/flatpage_root/sekrit/') + User.objects.create_user('testuser', 'test@example.com', 's3krit') + self.client.login(username='testuser',password='s3krit') + response = self.client.get('/flatpage_root/sekrit/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it sekrit!</p>") + + def test_fallback_flatpage(self): + "A flatpage can be served by the fallback middlware" + response = self.client.get('/flatpage/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it flat!</p>") + + def test_fallback_non_existent_flatpage(self): + "A non-existent flatpage raises a 404 when served by the fallback middlware" + response = self.client.get('/no_such_flatpage/') + self.assertEquals(response.status_code, 404) + + def test_fallback_authenticated_flatpage(self): + "A flatpage served by the middleware can require authentication" + response = self.client.get('/sekrit/') + self.assertRedirects(response, '/accounts/login/?next=/sekrit/') + User.objects.create_user('testuser', 'test@example.com', 's3krit') + self.client.login(username='testuser',password='s3krit') + response = self.client.get('/sekrit/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it sekrit!</p>") diff --git a/django/contrib/flatpages/tests/templates/404.html b/django/contrib/flatpages/tests/templates/404.html new file mode 100644 index 0000000000..5fd5f3cf3b --- /dev/null +++ b/django/contrib/flatpages/tests/templates/404.html @@ -0,0 +1 @@ +<h1>Oh Noes!</h1>
\ No newline at end of file diff --git a/django/contrib/flatpages/tests/templates/flatpages/default.html b/django/contrib/flatpages/tests/templates/flatpages/default.html new file mode 100644 index 0000000000..1410e17adf --- /dev/null +++ b/django/contrib/flatpages/tests/templates/flatpages/default.html @@ -0,0 +1,10 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" + "http://www.w3.org/TR/REC-html40/loose.dtd"> +<html> +<head> +<title>{{ flatpage.title }}</title> +</head> +<body> +<p>{{ flatpage.content }}</p> +</body> +</html> diff --git a/django/contrib/flatpages/tests/templates/registration/login.html b/django/contrib/flatpages/tests/templates/registration/login.html new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/django/contrib/flatpages/tests/templates/registration/login.html diff --git a/django/contrib/flatpages/tests/templatetags.py b/django/contrib/flatpages/tests/templatetags.py new file mode 100644 index 0000000000..9f42381c29 --- /dev/null +++ b/django/contrib/flatpages/tests/templatetags.py @@ -0,0 +1,134 @@ +import os +from django.conf import settings +from django.contrib.auth.models import AnonymousUser, User +from django.template import Template, Context, TemplateSyntaxError +from django.test import TestCase + +class FlatpageTemplateTagTests(TestCase): + fixtures = ['sample_flatpages'] + urls = 'django.contrib.flatpages.tests.urls' + + def setUp(self): + self.old_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES + flatpage_middleware_class = 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' + if flatpage_middleware_class not in settings.MIDDLEWARE_CLASSES: + settings.MIDDLEWARE_CLASSES += (flatpage_middleware_class,) + self.old_TEMPLATE_DIRS = settings.TEMPLATE_DIRS + settings.TEMPLATE_DIRS = ( + os.path.join( + os.path.dirname(__file__), + 'templates' + ), + ) + self.me = User.objects.create_user('testuser', 'test@example.com', 's3krit') + + def tearDown(self): + settings.MIDDLEWARE_CLASSES = self.old_MIDDLEWARE_CLASSES + settings.TEMPLATE_DIRS = self.old_TEMPLATE_DIRS + + def test_get_flatpages_tag(self): + "The flatpage template tag retrives unregistered prefixed flatpages by default" + out = Template( + "{% load flatpages %}" + "{% get_flatpages as flatpages %}" + "{% for page in flatpages %}" + "{{ page.title }}," + "{% endfor %}" + ).render(Context()) + self.assertEquals(out, "A Flatpage,A Nested Flatpage,") + + def test_get_flatpages_tag_for_anon_user(self): + "The flatpage template tag retrives unregistered flatpages for an anonymous user" + out = Template( + "{% load flatpages %}" + "{% get_flatpages for anonuser as flatpages %}" + "{% for page in flatpages %}" + "{{ page.title }}," + "{% endfor %}" + ).render(Context({ + 'anonuser': AnonymousUser() + })) + self.assertEquals(out, "A Flatpage,A Nested Flatpage,") + + def test_get_flatpages_tag_for_user(self): + "The flatpage template tag retrives all flatpages for an authenticated user" + out = Template( + "{% load flatpages %}" + "{% get_flatpages for me as flatpages %}" + "{% for page in flatpages %}" + "{{ page.title }}," + "{% endfor %}" + ).render(Context({ + 'me': self.me + })) + self.assertEquals(out, "A Flatpage,A Nested Flatpage,Sekrit Nested Flatpage,Sekrit Flatpage,") + + def test_get_flatpages_with_prefix(self): + "The flatpage template tag retrives unregistered prefixed flatpages by default" + out = Template( + "{% load flatpages %}" + "{% get_flatpages '/location/' as location_flatpages %}" + "{% for page in location_flatpages %}" + "{{ page.title }}," + "{% endfor %}" + ).render(Context()) + self.assertEquals(out, "A Nested Flatpage,") + + def test_get_flatpages_with_prefix_for_anon_user(self): + "The flatpage template tag retrives unregistered prefixed flatpages for an anonymous user" + out = Template( + "{% load flatpages %}" + "{% get_flatpages '/location/' for anonuser as location_flatpages %}" + "{% for page in location_flatpages %}" + "{{ page.title }}," + "{% endfor %}" + ).render(Context({ + 'anonuser': AnonymousUser() + })) + self.assertEquals(out, "A Nested Flatpage,") + + def test_get_flatpages_with_prefix_for_user(self): + "The flatpage template tag retrive prefixed flatpages for an authenticated user" + out = Template( + "{% load flatpages %}" + "{% get_flatpages '/location/' for me as location_flatpages %}" + "{% for page in location_flatpages %}" + "{{ page.title }}," + "{% endfor %}" + ).render(Context({ + 'me': self.me + })) + self.assertEquals(out, "A Nested Flatpage,Sekrit Nested Flatpage,") + + def test_get_flatpages_with_variable_prefix(self): + "The prefix for the flatpage template tag can be a template variable" + out = Template( + "{% load flatpages %}" + "{% get_flatpages location_prefix as location_flatpages %}" + "{% for page in location_flatpages %}" + "{{ page.title }}," + "{% endfor %}" + ).render(Context({ + 'location_prefix': '/location/' + })) + self.assertEquals(out, "A Nested Flatpage,") + + def test_parsing_errors(self): + "There are various ways that the flatpages template tag won't parse" + render = lambda t: Template(t).render(Context()) + + self.assertRaises(TemplateSyntaxError, render, + "{% load flatpages %}{% get_flatpages %}") + self.assertRaises(TemplateSyntaxError, render, + "{% load flatpages %}{% get_flatpages as %}") + self.assertRaises(TemplateSyntaxError, render, + "{% load flatpages %}{% get_flatpages cheesecake flatpages %}") + self.assertRaises(TemplateSyntaxError, render, + "{% load flatpages %}{% get_flatpages as flatpages asdf%}") + self.assertRaises(TemplateSyntaxError, render, + "{% load flatpages %}{% get_flatpages cheesecake user as flatpages %}") + self.assertRaises(TemplateSyntaxError, render, + "{% load flatpages %}{% get_flatpages for user as flatpages asdf%}") + self.assertRaises(TemplateSyntaxError, render, + "{% load flatpages %}{% get_flatpages prefix for user as flatpages asdf%}") + diff --git a/django/contrib/flatpages/tests/urls.py b/django/contrib/flatpages/tests/urls.py new file mode 100644 index 0000000000..3cffd09d0f --- /dev/null +++ b/django/contrib/flatpages/tests/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls.defaults import * + +# special urls for flatpage test cases +urlpatterns = patterns('', + (r'^flatpage_root', include('django.contrib.flatpages.urls')), + (r'^accounts/', include('django.contrib.auth.urls')), +) + diff --git a/django/contrib/flatpages/tests/views.py b/django/contrib/flatpages/tests/views.py new file mode 100644 index 0000000000..89bdde2d92 --- /dev/null +++ b/django/contrib/flatpages/tests/views.py @@ -0,0 +1,72 @@ +import os +from django.conf import settings +from django.contrib.auth.models import User +from django.contrib.flatpages.models import FlatPage +from django.test import TestCase + +class FlatpageViewTests(TestCase): + fixtures = ['sample_flatpages'] + urls = 'django.contrib.flatpages.tests.urls' + + def setUp(self): + self.old_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES + flatpage_middleware_class = 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' + if flatpage_middleware_class in settings.MIDDLEWARE_CLASSES: + settings.MIDDLEWARE_CLASSES = tuple(m for m in settings.MIDDLEWARE_CLASSES if m != flatpage_middleware_class) + self.old_TEMPLATE_DIRS = settings.TEMPLATE_DIRS + settings.TEMPLATE_DIRS = ( + os.path.join( + os.path.dirname(__file__), + 'templates' + ), + ) + + def tearDown(self): + settings.MIDDLEWARE_CLASSES = self.old_MIDDLEWARE_CLASSES + settings.TEMPLATE_DIRS = self.old_TEMPLATE_DIRS + + def test_view_flatpage(self): + "A flatpage can be served through a view" + response = self.client.get('/flatpage_root/flatpage/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it flat!</p>") + + def test_view_non_existent_flatpage(self): + "A non-existent flatpage raises 404 when served through a view" + response = self.client.get('/flatpage_root/no_such_flatpage/') + self.assertEquals(response.status_code, 404) + + def test_view_authenticated_flatpage(self): + "A flatpage served through a view can require authentication" + response = self.client.get('/flatpage_root/sekrit/') + self.assertRedirects(response, '/accounts/login/?next=/flatpage_root/sekrit/') + User.objects.create_user('testuser', 'test@example.com', 's3krit') + self.client.login(username='testuser',password='s3krit') + response = self.client.get('/flatpage_root/sekrit/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it sekrit!</p>") + + def test_fallback_flatpage(self): + "A fallback flatpage won't be served if the middleware is disabled" + response = self.client.get('/flatpage/') + self.assertEquals(response.status_code, 404) + + def test_fallback_non_existent_flatpage(self): + "A non-existent flatpage won't be served if the fallback middlware is disabled" + response = self.client.get('/no_such_flatpage/') + self.assertEquals(response.status_code, 404) + + def test_view_flatpage_special_chars(self): + "A flatpage with special chars in the URL can be served through a view" + fp = FlatPage.objects.create( + url="/some.very_special~chars-here/", + title="A very special page", + content="Isn't it special!", + enable_comments=False, + registration_required=False, + ) + fp.sites.add(1) + + response = self.client.get('/flatpage_root/some.very_special~chars-here/') + self.assertEquals(response.status_code, 200) + self.assertContains(response, "<p>Isn't it special!</p>") diff --git a/django/contrib/flatpages/views.py b/django/contrib/flatpages/views.py index 336600328d..88ef4da65e 100644 --- a/django/contrib/flatpages/views.py +++ b/django/contrib/flatpages/views.py @@ -13,10 +13,13 @@ DEFAULT_TEMPLATE = 'flatpages/default.html' # when a 404 is raised, which often means CsrfViewMiddleware.process_view # has not been called even if CsrfViewMiddleware is installed. So we need # to use @csrf_protect, in case the template needs {% csrf_token %}. -@csrf_protect +# However, we can't just wrap this view; if no matching flatpage exists, +# or a redirect is required for authentication, the 404 needs to be returned +# without any CSRF checks. Therefore, we only +# CSRF protect the internal implementation. def flatpage(request, url): """ - Flat page view. + Public interface to the flat page view. Models: `flatpages.flatpages` Templates: Uses the template defined by the ``template_name`` field, @@ -30,6 +33,13 @@ def flatpage(request, url): if not url.startswith('/'): url = "/" + url f = get_object_or_404(FlatPage, url__exact=url, sites__id__exact=settings.SITE_ID) + return render_flatpage(request, f) + +@csrf_protect +def render_flatpage(request, f): + """ + Internal interface to the flat page view. + """ # If registration is required for accessing this page, and the user isn't # logged in, redirect to the login page. if f.registration_required and not request.user.is_authenticated(): |