From 3f3010014b33451553c62b005c2ec09a16a9f9ce Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Fri, 7 Oct 2011 15:45:52 +0000 Subject: [PATCH] Fixed #14678 -- Added validation to catch flatpages with the same URL on the same site. Thanks seler for the report, and joni, graham_king, and j4nu5 for work on the patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16937 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/flatpages/admin.py | 14 +------------ django/contrib/flatpages/forms.py | 28 +++++++++++++++++++++++++ django/contrib/flatpages/tests/forms.py | 18 ++++++++++++++-- docs/ref/contrib/flatpages.txt | 8 +++++++ 4 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 django/contrib/flatpages/forms.py diff --git a/django/contrib/flatpages/admin.py b/django/contrib/flatpages/admin.py index 1b377e967b7..13294262f1b 100644 --- a/django/contrib/flatpages/admin.py +++ b/django/contrib/flatpages/admin.py @@ -1,19 +1,7 @@ -from django import forms from django.contrib import admin from django.contrib.flatpages.models import FlatPage from django.utils.translation import ugettext_lazy as _ - - -class FlatpageForm(forms.ModelForm): - 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," - " dots, underscores, dashes, slashes or tildes.")) - - class Meta: - model = FlatPage - +from django.contrib.flatpages.forms import FlatpageForm class FlatPageAdmin(admin.ModelAdmin): form = FlatpageForm diff --git a/django/contrib/flatpages/forms.py b/django/contrib/flatpages/forms.py new file mode 100644 index 00000000000..b2811ff618a --- /dev/null +++ b/django/contrib/flatpages/forms.py @@ -0,0 +1,28 @@ +from django import forms +from django.utils.translation import ugettext_lazy as _ +from django.contrib.flatpages.models import FlatPage + +class FlatpageForm(forms.ModelForm): + 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," + " dots, underscores, dashes, slashes or tildes.")) + + class Meta: + model = FlatPage + + def clean(self): + url = self.cleaned_data.get('url', None) + sites = self.cleaned_data.get('sites', None) + + flatpages_with_same_url = FlatPage.objects.filter(url=url) + + if flatpages_with_same_url.filter(sites__in=sites).exists(): + for site in sites: + if flatpages_with_same_url.filter(sites=site).exists(): + raise forms.ValidationError( + _('Flatpage with url %s already exists for site %s' + % (url, site))) + + return super(FlatpageForm, self).clean() diff --git a/django/contrib/flatpages/tests/forms.py b/django/contrib/flatpages/tests/forms.py index e8ca2b8e5c2..83437ba733d 100644 --- a/django/contrib/flatpages/tests/forms.py +++ b/django/contrib/flatpages/tests/forms.py @@ -1,5 +1,5 @@ from django.conf import settings -from django.contrib.flatpages.admin import FlatpageForm +from django.contrib.flatpages.forms import FlatpageForm from django.test import TestCase class FlatpageAdminFormTests(TestCase): @@ -11,7 +11,7 @@ class FlatpageAdminFormTests(TestCase): } def test_flatpage_admin_form_url_validation(self): - "The flatpage admin form validates correctly validates urls" + "The flatpage admin form 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()) @@ -21,3 +21,17 @@ class FlatpageAdminFormTests(TestCase): 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()) + + def test_flatpage_admin_form_url_uniqueness_validation(self): + "The flatpage admin form correctly enforces url uniqueness among flatpages of the same site" + data = dict(url='/myflatpage1', **self.form_data) + + FlatpageForm(data=data).save() + + f = FlatpageForm(data=data) + + self.assertFalse(f.is_valid()) + + self.assertEqual( + f.errors, + {'__all__': [u'Flatpage with url /myflatpage1 already exists for site example.com']}) diff --git a/docs/ref/contrib/flatpages.txt b/docs/ref/contrib/flatpages.txt index db063f91ad8..4a1f2970cb7 100644 --- a/docs/ref/contrib/flatpages.txt +++ b/docs/ref/contrib/flatpages.txt @@ -148,6 +148,14 @@ Via the Python API .. currentmodule:: django.contrib.flatpages +.. admonition:: Check for duplicate flatpage URLs. + + If you add or modify flatpages via your own code, you will likely want to + check for duplicate flatpage URLs within the same site. The flatpage form + used in the admin performs this validation check, and can be imported from + :class:`django.contrib.flatpages.forms.FlatPageForm` and used in your own + views. + Flatpage templates ==================