Permalink
Browse files

Merge branch 'master' into soc2011/form-rendering

  • Loading branch information...
2 parents 9cf96a2 + 8713873 commit 8c0e4c6a8bc68a2235ceca4eb223e6a5a26f8b77 @gregmuellegger committed Jan 28, 2012
@@ -307,11 +307,14 @@ def load_all_installed_template_libraries():
# Load/register all template tag libraries from installed apps.
for module_name in template.get_templatetags_modules():
mod = import_module(module_name)
- libraries = [
- os.path.splitext(p)[0]
- for p in os.listdir(os.path.dirname(mod.__file__))
- if p.endswith('.py') and p[0].isalpha()
- ]
+ try:
+ libraries = [
+ os.path.splitext(p)[0]
+ for p in os.listdir(os.path.dirname(mod.__file__))
+ if p.endswith('.py') and p[0].isalpha()
+ ]
+ except OSError:
+ libraries = []
for library_name in libraries:
try:
lib = template.get_library(library_name)
@@ -0,0 +1 @@
+# Empty models.py to allow for specifying databrowse as a test label.
@@ -73,7 +73,7 @@ def __init__(self):
self.registry = {} # model_class -> databrowse_class
self.root_url = None
- def register(self, model_or_iterable, databrowse_class=None, **options):
+ def register(self, *model_list, **options):
"""
Registers the given model(s) with the given databrowse site.
@@ -84,23 +84,19 @@ def register(self, model_or_iterable, databrowse_class=None, **options):
If a model is already registered, this will raise AlreadyRegistered.
"""
- databrowse_class = databrowse_class or DefaultModelDatabrowse
- if issubclass(model_or_iterable, models.Model):
- model_or_iterable = [model_or_iterable]
- for model in model_or_iterable:
+ databrowse_class = options.pop('databrowse_class', DefaultModelDatabrowse)
+ for model in model_list:
if model in self.registry:
raise AlreadyRegistered('The model %s is already registered' % model.__name__)
self.registry[model] = databrowse_class
- def unregister(self, model_or_iterable):
+ def unregister(self, *model_list):
"""
Unregisters the given model(s).
If a model isn't already registered, this will raise NotRegistered.
"""
- if issubclass(model_or_iterable, models.Model):
- model_or_iterable = [model_or_iterable]
- for model in model_or_iterable:
+ for model in model_list:
if model not in self.registry:
raise NotRegistered('The model %s is not registered' % model.__name__)
del self.registry[model]
@@ -0,0 +1,58 @@
+from django.contrib import databrowse
+from django.db import models
+from django.test import TestCase
+
+
+class SomeModel(models.Model):
+ some_field = models.CharField(max_length=50)
+
+ def __unicode__(self):
+ return self.some_field
+
+
+class SomeOtherModel(models.Model):
+ some_other_field = models.CharField(max_length=50)
+
+ def __unicode__(self):
+ return self.some_other_field
+
+
+class YetAnotherModel(models.Model):
+ yet_another_field = models.CharField(max_length=50)
+
+ def __unicode__(self):
+ return self.yet_another_field
+
+
+class DatabrowseTests(TestCase):
+
+ def test_databrowse_register_unregister(self):
+ databrowse.site.register(SomeModel)
+ self.assertTrue(SomeModel in databrowse.site.registry)
+ databrowse.site.register(SomeOtherModel, YetAnotherModel)
+ self.assertTrue(SomeOtherModel in databrowse.site.registry)
+ self.assertTrue(YetAnotherModel in databrowse.site.registry)
+
+ self.assertRaisesMessage(
+ databrowse.sites.AlreadyRegistered,
+ 'The model SomeModel is already registered',
+ databrowse.site.register, SomeModel, SomeOtherModel
+ )
+
+ databrowse.site.unregister(SomeOtherModel)
+ self.assertFalse(SomeOtherModel in databrowse.site.registry)
+ databrowse.site.unregister(SomeModel, YetAnotherModel)
+ self.assertFalse(SomeModel in databrowse.site.registry)
+ self.assertFalse(YetAnotherModel in databrowse.site.registry)
+
+ self.assertRaisesMessage(
+ databrowse.sites.NotRegistered,
+ 'The model SomeModel is not registered',
+ databrowse.site.unregister, SomeModel, SomeOtherModel
+ )
+
+ self.assertRaisesMessage(
+ databrowse.sites.AlreadyRegistered,
+ 'The model SomeModel is already registered',
+ databrowse.site.register, SomeModel, SomeModel
+ )
@@ -1,6 +1,7 @@
from django import forms
-from django.utils.translation import ugettext_lazy as _
+from django.conf import settings
from django.contrib.flatpages.models import FlatPage
+from django.utils.translation import ugettext, ugettext_lazy as _
class FlatpageForm(forms.ModelForm):
url = forms.RegexField(label=_("URL"), max_length=100, regex=r'^[-\w/\.~]+$',
@@ -12,6 +13,16 @@ class FlatpageForm(forms.ModelForm):
class Meta:
model = FlatPage
+ def clean_url(self):
+ url = self.cleaned_data['url']
+ if not url.startswith('/'):
+ raise forms.ValidationError(ugettext("URL is missing a leading slash."))
+ if (settings.APPEND_SLASH and
+ 'django.middleware.common.CommonMiddleware' in settings.MIDDLEWARE_CLASSES and
+ not url.endswith('/')):
+ raise forms.ValidationError(ugettext("URL is missing a trailing slash."))
+ return url
+
def clean(self):
url = self.cleaned_data.get('url', None)
sites = self.cleaned_data.get('sites', None)
@@ -1,7 +1,11 @@
+from __future__ import with_statement
+
from django.conf import settings
from django.contrib.flatpages.forms import FlatpageForm
from django.contrib.flatpages.models import FlatPage
from django.test import TestCase
+from django.test.utils import override_settings
+from django.utils import translation
class FlatpageAdminFormTests(TestCase):
def setUp(self):
@@ -23,9 +27,29 @@ def test_flatpage_admin_form_url_validation(self):
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_requires_leading_slash(self):
+ form = FlatpageForm(data=dict(url='no_leading_slash/', **self.form_data))
+ with translation.override('en'):
+ self.assertFalse(form.is_valid())
+ self.assertEqual(form.errors['url'], ["URL is missing a leading slash."])
+
+ @override_settings(APPEND_SLASH=True,
+ MIDDLEWARE_CLASSES=('django.middleware.common.CommonMiddleware',))
+ def test_flatpage_requires_trailing_slash_with_append_slash(self):
+ form = FlatpageForm(data=dict(url='/no_trailing_slash', **self.form_data))
+ with translation.override('en'):
+ self.assertFalse(form.is_valid())
+ self.assertEqual(form.errors['url'], ["URL is missing a trailing slash."])
+
+ @override_settings(APPEND_SLASH=False,
+ MIDDLEWARE_CLASSES=('django.middleware.common.CommonMiddleware',))
+ def test_flatpage_doesnt_requires_trailing_slash_without_append_slash(self):
+ form = FlatpageForm(data=dict(url='/no_trailing_slash', **self.form_data))
+ self.assertTrue(form.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)
+ data = dict(url='/myflatpage1/', **self.form_data)
FlatpageForm(data=data).save()
@@ -35,7 +59,7 @@ def test_flatpage_admin_form_url_uniqueness_validation(self):
self.assertEqual(
f.errors,
- {'__all__': [u'Flatpage with url /myflatpage1 already exists for site example.com']})
+ {'__all__': [u'Flatpage with url /myflatpage1/ already exists for site example.com']})
def test_flatpage_admin_form_edit(self):
"""
@@ -44,10 +68,10 @@ def test_flatpage_admin_form_edit(self):
"""
existing = FlatPage.objects.create(
- url="/myflatpage1", title="Some page", content="The content")
+ url="/myflatpage1/", title="Some page", content="The content")
existing.sites.add(settings.SITE_ID)
- data = dict(url='/myflatpage1', **self.form_data)
+ data = dict(url='/myflatpage1/', **self.form_data)
f = FlatpageForm(data=data, instance=existing)
View
@@ -204,22 +204,18 @@ def create_token(self, token_string, in_tag):
otherwise it should be treated as a literal string.
"""
if in_tag:
+ # The [2:-2] ranges below strip off *_TAG_START and *_TAG_END.
+ # We could do len(BLOCK_TAG_START) to be more "correct", but we've
+ # hard-coded the 2s here for performance. And it's not like
+ # the TAG_START values are going to change anytime, anyway.
if token_string.startswith(VARIABLE_TAG_START):
- token = Token(TOKEN_VAR,
- token_string[
- len(VARIABLE_TAG_START):-len(VARIABLE_TAG_END)
- ].strip())
+ token = Token(TOKEN_VAR, token_string[2:-2].strip())
elif token_string.startswith(BLOCK_TAG_START):
- token = Token(TOKEN_BLOCK,
- token_string[
- len(BLOCK_TAG_START):-len(BLOCK_TAG_END)
- ].strip())
+ token = Token(TOKEN_BLOCK, token_string[2:-2].strip())
elif token_string.startswith(COMMENT_TAG_START):
content = ''
if token_string.find(TRANSLATOR_COMMENT_MARK):
- content = token_string[
- len(COMMENT_TAG_START):-len(COMMENT_TAG_END)
- ].strip()
+ content = token_string[2:-2].strip()
token = Token(TOKEN_COMMENT, content)
else:
token = Token(TOKEN_TEXT, token_string)
@@ -241,15 +237,16 @@ def parse(self, parse_until=None):
nodelist = self.create_nodelist()
while self.tokens:
token = self.next_token()
- if token.token_type == TOKEN_TEXT:
+ # Use the raw values here for TOKEN_* for a tiny performance boost.
+ if token.token_type == 0: # TOKEN_TEXT
self.extend_nodelist(nodelist, TextNode(token.contents), token)
- elif token.token_type == TOKEN_VAR:
+ elif token.token_type == 1: # TOKEN_VAR
if not token.contents:
self.empty_variable(token)
filter_expression = self.compile_filter(token.contents)
var_node = self.create_variable_node(filter_expression)
self.extend_nodelist(nodelist, var_node, token)
- elif token.token_type == TOKEN_BLOCK:
+ elif token.token_type == 2: # TOKEN_BLOCK
try:
command = token.contents.split()[0]
except IndexError:
@@ -241,9 +241,6 @@ def addCleanup(self, function, *args, **kwargs):
Cleanup items are called even if setUp fails (unlike tearDown)."""
self._cleanups.append((function, args, kwargs))
- def setUp(self):
- "Hook method for setting up the test fixture before exercising it."
-
@classmethod
def setUpClass(cls):
"Hook method for setting up class fixture before running tests in the class."
@@ -252,9 +249,6 @@ def setUpClass(cls):
def tearDownClass(cls):
"Hook method for deconstructing the class fixture after running all tests in the class."
- def tearDown(self):
- "Hook method for deconstructing the test fixture after testing it."
-
def countTestCases(self):
return 1
@@ -33,13 +33,18 @@ How to use Databrowse
2. Register a number of models with the Databrowse site::
from django.contrib import databrowse
- from myapp.models import SomeModel, SomeOtherModel
+ from myapp.models import SomeModel, SomeOtherModel, YetAnotherModel
databrowse.site.register(SomeModel)
- databrowse.site.register(SomeOtherModel)
+ databrowse.site.register(SomeOtherModel, YetAnotherModel)
Note that you should register the model *classes*, not instances.
+ .. versionchanged:: 1.4
+
+ Since Django 1.4, it is possible to register several models in the same
+ call to :func:`~databrowse.site.register`.
+
It doesn't matter where you put this, as long as it gets executed at some
point. A good place for it is in your :doc:`URLconf file
</topics/http/urls>` (``urls.py``).
@@ -264,7 +264,12 @@ def test_naive_datetime(self):
@requires_tz_support
def test_datetime_from_date(self):
dt = datetime.date(2011, 9, 1)
- Event.objects.create(dt=dt)
+ with warnings.catch_warnings(record=True) as recorded:
+ warnings.simplefilter('always')
+ Event.objects.create(dt=dt)
+ self.assertEqual(len(recorded), 1)
+ msg = str(recorded[0].message)
+ self.assertTrue(msg.startswith("DateTimeField received a naive datetime"))
event = Event.objects.get()
self.assertEqual(event.dt, datetime.datetime(2011, 9, 1, tzinfo=EAT))
View
@@ -4,9 +4,13 @@
import subprocess
import sys
import tempfile
+import warnings
from django import contrib
+# databrowse is deprecated, but we still want to run its tests
+warnings.filterwarnings('ignore', "The Databrowse contrib app is deprecated",
+ PendingDeprecationWarning, 'django.contrib.databrowse')
CONTRIB_DIR_NAME = 'django.contrib'
MODEL_TESTS_DIR_NAME = 'modeltests'
@@ -34,6 +38,7 @@
'django.contrib.comments',
'django.contrib.admin',
'django.contrib.admindocs',
+ 'django.contrib.databrowse',
'django.contrib.staticfiles',
'django.contrib.humanize',
'regressiontests.staticfiles_tests',

0 comments on commit 8c0e4c6

Please sign in to comment.