summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2007-12-03 02:59:56 +0000
committerMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2007-12-03 02:59:56 +0000
commit07ddd56872e70e76e13eb0b118c7b6503d5d821f (patch)
treee1e2eb0ab912b1b26246b4736ad114cc4541ad9c /tests
parent79653a414857e4f93918051843afbc1f7c9a7f99 (diff)
queryset-refactor: Merged from trunk up to [6856].
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6857 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
-rw-r--r--tests/modeltests/empty/models.py2
-rw-r--r--tests/modeltests/field_defaults/models.py5
-rw-r--r--tests/modeltests/get_object_or_404/models.py2
-rw-r--r--tests/modeltests/invalid_models/models.py6
-rw-r--r--tests/modeltests/model_forms/models.py314
-rw-r--r--tests/modeltests/select_related/models.py2
-rw-r--r--tests/modeltests/serializers/models.py2
-rw-r--r--tests/modeltests/test_client/models.py2
-rw-r--r--tests/modeltests/user_commands/models.py4
-rw-r--r--tests/regressiontests/cache/tests.py2
-rw-r--r--tests/regressiontests/forms/localflavor/za.py40
-rw-r--r--tests/regressiontests/forms/tests.py2
-rw-r--r--tests/regressiontests/i18n/tests.py15
-rw-r--r--tests/regressiontests/middleware/__init__.py0
-rw-r--r--tests/regressiontests/middleware/tests.py93
-rw-r--r--tests/regressiontests/middleware/urls.py7
-rw-r--r--tests/regressiontests/string_lookup/models.py8
-rw-r--r--tests/regressiontests/templates/context.py18
-rw-r--r--tests/regressiontests/templates/tests.py2
-rw-r--r--tests/regressiontests/templates/unicode.py10
-rw-r--r--tests/regressiontests/views/views.py2
-rwxr-xr-xtests/runtests.py3
-rw-r--r--tests/urls.py3
23 files changed, 383 insertions, 161 deletions
diff --git a/tests/modeltests/empty/models.py b/tests/modeltests/empty/models.py
index 2493b53837..d57087134e 100644
--- a/tests/modeltests/empty/models.py
+++ b/tests/modeltests/empty/models.py
@@ -1,5 +1,5 @@
"""
-39. Empty model tests
+40. Empty model tests
These test that things behave sensibly for the rare corner-case of a model with
no fields.
diff --git a/tests/modeltests/field_defaults/models.py b/tests/modeltests/field_defaults/models.py
index 1132f1ca41..fe80cce406 100644
--- a/tests/modeltests/field_defaults/models.py
+++ b/tests/modeltests/field_defaults/models.py
@@ -48,4 +48,9 @@ u'Default headline'
>>> d = now - a.pub_date
>>> d.seconds < 5
True
+
+# make sure that SafeUnicode fields work
+>>> from django.utils.safestring import SafeUnicode
+>>> a.headline = SafeUnicode(u'SafeUnicode Headline')
+>>> a.save()
"""}
diff --git a/tests/modeltests/get_object_or_404/models.py b/tests/modeltests/get_object_or_404/models.py
index bd800317d3..d9f276b024 100644
--- a/tests/modeltests/get_object_or_404/models.py
+++ b/tests/modeltests/get_object_or_404/models.py
@@ -78,7 +78,7 @@ Http404: No Article matches the given query.
>>> get_object_or_404(Author.objects.all())
Traceback (most recent call last):
...
-AssertionError: get() returned more than one Author -- it returned ...! Lookup parameters were {}
+MultipleObjectsReturned: get() returned more than one Author -- it returned ...! Lookup parameters were {}
# Using an EmptyQuerySet raises a Http404 error.
>>> get_object_or_404(Article.objects.none(), title__contains="Run")
diff --git a/tests/modeltests/invalid_models/models.py b/tests/modeltests/invalid_models/models.py
index b746af6dba..8a480a2381 100644
--- a/tests/modeltests/invalid_models/models.py
+++ b/tests/modeltests/invalid_models/models.py
@@ -108,6 +108,10 @@ class Car(models.Model):
colour = models.CharField(max_length=5)
model = models.ForeignKey(Model)
+class MissingRelations(models.Model):
+ rel1 = models.ForeignKey("Rel1")
+ rel2 = models.ManyToManyField("Rel2")
+
model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "max_length" attribute.
invalid_models.fielderrors: "decimalfield": DecimalFields require a "decimal_places" attribute.
invalid_models.fielderrors: "decimalfield": DecimalFields require a "max_digits" attribute.
@@ -191,4 +195,6 @@ invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with related
invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_4'.
invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_3' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'm2m_3'.
invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_4' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'm2m_4'.
+invalid_models.missingrelations: 'rel2' has m2m relation with model Rel2, which has not been installed
+invalid_models.missingrelations: 'rel1' has relation with model Rel1, which has not been installed
"""
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py
index 9b0126ff4f..cd92956270 100644
--- a/tests/modeltests/model_forms/models.py
+++ b/tests/modeltests/model_forms/models.py
@@ -1,25 +1,10 @@
"""
-36. Generating HTML forms from models
+XX. Generating HTML forms from models
-Django provides shortcuts for creating Form objects from a model class and a
-model instance.
-
-The function django.newforms.form_for_model() takes a model class and returns
-a Form that is tied to the model. This Form works just like any other Form,
-with one additional method: save(). The save() method creates an instance
-of the model and returns that newly created instance. It saves the instance to
-the database if save(commit=True), which is default. If you pass
-commit=False, then you'll get the object without committing the changes to the
-database.
-
-The function django.newforms.form_for_instance() takes a model instance and
-returns a Form that is tied to the instance. This form works just like any
-other Form, with one additional method: save(). The save()
-method updates the model instance. It also takes a commit=True parameter.
-
-The function django.newforms.save_instance() takes a bound form instance and a
-model instance and saves the form's cleaned_data into the instance. It also takes
-a commit=True parameter.
+This is mostly just a reworking of the form_for_model/form_for_instance tests
+to use ModelForm. As such, the text may not make sense in all cases, and the
+examples are probably a poor fit for the ModelForm syntax. In other words,
+most of these tests should be rewritten.
"""
from django.db import models
@@ -30,23 +15,6 @@ ARTICLE_STATUS = (
(3, 'Live'),
)
-STEERING_TYPE = (
- ('left', 'Left steering wheel'),
- ('right', 'Right steering wheel'),
-)
-
-FUEL_TYPE = (
- ('gas', 'Gasoline'),
- ('diesel', 'Diesel'),
- ('other', 'Other'),
-)
-
-TRANSMISSION_TYPE = (
- ('at', 'Automatic'),
- ('mt', 'Manual'),
- ('cvt', 'CVT'),
-)
-
class Category(models.Model):
name = models.CharField(max_length=20)
slug = models.SlugField(max_length=20)
@@ -87,21 +55,119 @@ class PhoneNumber(models.Model):
def __unicode__(self):
return self.phone
-class Car(models.Model):
- name = models.CharField(max_length=50)
- steering = models.CharField(max_length=5, choices=STEERING_TYPE, default='left')
- fuel = models.CharField(max_length=10, choices=FUEL_TYPE)
- transmission = models.CharField(max_length=3, choices=TRANSMISSION_TYPE, blank=True, help_text='Leave empty if not applicable.')
-
__test__ = {'API_TESTS': """
->>> from django.newforms import form_for_model, form_for_instance, save_instance, BaseForm, Form, CharField
+>>> from django import newforms as forms
+>>> from django.newforms.models import ModelForm
+
+The bare bones, absolutely nothing custom, basic case.
+
+>>> class CategoryForm(ModelForm):
+... class Meta:
+... model = Category
+>>> CategoryForm.base_fields.keys()
+['name', 'slug', 'url']
+
+
+Extra fields.
+
+>>> class CategoryForm(ModelForm):
+... some_extra_field = forms.BooleanField()
+...
+... class Meta:
+... model = Category
+
+>>> CategoryForm.base_fields.keys()
+['name', 'slug', 'url', 'some_extra_field']
+
+
+Replacing a field.
+
+>>> class CategoryForm(ModelForm):
+... url = forms.BooleanField()
+...
+... class Meta:
+... model = Category
+
+>>> CategoryForm.base_fields['url'].__class__
+<class 'django.newforms.fields.BooleanField'>
+
+
+Using 'fields'.
+
+>>> class CategoryForm(ModelForm):
+...
+... class Meta:
+... model = Category
+... fields = ['url']
+
+>>> CategoryForm.base_fields.keys()
+['url']
+
+
+Using 'exclude'
+
+>>> class CategoryForm(ModelForm):
+...
+... class Meta:
+... model = Category
+... exclude = ['url']
+
+>>> CategoryForm.base_fields.keys()
+['name', 'slug']
+
+
+Using 'fields' *and* 'exclude'. Not sure why you'd want to do this, but uh,
+"be liberal in what you accept" and all.
+
+>>> class CategoryForm(ModelForm):
+...
+... class Meta:
+... model = Category
+... fields = ['name', 'url']
+... exclude = ['url']
+
+>>> CategoryForm.base_fields.keys()
+['name']
+
+Don't allow more than one 'model' definition in the inheritance hierarchy.
+Technically, it would generate a valid form, but the fact that the resulting
+save method won't deal with multiple objects is likely to trip up people not
+familiar with the mechanics.
+
+>>> class CategoryForm(ModelForm):
+... class Meta:
+... model = Category
+
+>>> class BadForm(CategoryForm):
+... class Meta:
+... model = Article
+Traceback (most recent call last):
+...
+ImproperlyConfigured: BadForm defines more than one model.
+
+>>> class ArticleForm(ModelForm):
+... class Meta:
+... model = Article
+
+>>> class BadForm(ArticleForm, CategoryForm):
+... pass
+Traceback (most recent call last):
+...
+ImproperlyConfigured: BadForm's base classes define more than one model.
+
+
+# Old form_for_x tests #######################################################
+
+>>> from django.newforms import ModelForm, CharField
>>> import datetime
>>> Category.objects.all()
[]
->>> CategoryForm = form_for_model(Category)
->>> f = CategoryForm()
+>>> class CategoryForm(ModelForm):
+... class Meta:
+... model = Category
+>>> f = CategoryForm(Category())
>>> print f
<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr>
@@ -113,13 +179,13 @@ __test__ = {'API_TESTS': """
>>> print f['name']
<input id="id_name" type="text" name="name" maxlength="20" />
->>> f = CategoryForm(auto_id=False)
+>>> f = CategoryForm(Category(), auto_id=False)
>>> print f.as_ul()
<li>Name: <input type="text" name="name" maxlength="20" /></li>
<li>Slug: <input type="text" name="slug" maxlength="20" /></li>
<li>The URL: <input type="text" name="url" maxlength="40" /></li>
->>> f = CategoryForm({'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'})
+>>> f = CategoryForm(Category(), {'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'})
>>> f.is_valid()
True
>>> f.cleaned_data
@@ -130,7 +196,7 @@ True
>>> Category.objects.all()
[<Category: Entertainment>]
->>> f = CategoryForm({'name': "It's a test", 'slug': 'its-test', 'url': 'test'})
+>>> f = CategoryForm(Category(), {'name': "It's a test", 'slug': 'its-test', 'url': 'test'})
>>> f.is_valid()
True
>>> f.cleaned_data
@@ -144,7 +210,7 @@ True
If you call save() with commit=False, then it will return an object that
hasn't yet been saved to the database. In this case, it's up to you to call
save() on the resulting model instance.
->>> f = CategoryForm({'name': 'Third test', 'slug': 'third-test', 'url': 'third'})
+>>> f = CategoryForm(Category(), {'name': 'Third test', 'slug': 'third-test', 'url': 'third'})
>>> f.is_valid()
True
>>> f.cleaned_data
@@ -159,7 +225,7 @@ True
[<Category: Entertainment>, <Category: It's a test>, <Category: Third test>]
If you call save() with invalid data, you'll get a ValueError.
->>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'})
+>>> f = CategoryForm(Category(), {'name': '', 'slug': '', 'url': 'foo'})
>>> f.errors
{'name': [u'This field is required.'], 'slug': [u'This field is required.']}
>>> f.cleaned_data
@@ -170,7 +236,7 @@ AttributeError: 'CategoryForm' object has no attribute 'cleaned_data'
Traceback (most recent call last):
...
ValueError: The Category could not be created because the data didn't validate.
->>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'})
+>>> f = CategoryForm(Category(), {'name': '', 'slug': '', 'url': 'foo'})
>>> f.save()
Traceback (most recent call last):
...
@@ -184,8 +250,10 @@ Create a couple of Writers.
ManyToManyFields are represented by a MultipleChoiceField, ForeignKeys and any
fields with the 'choices' attribute are represented by a ChoiceField.
->>> ArticleForm = form_for_model(Article)
->>> f = ArticleForm(auto_id=False)
+>>> class ArticleForm(ModelForm):
+... class Meta:
+... model = Article
+>>> f = ArticleForm(Article(), auto_id=False)
>>> print f
<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr>
@@ -214,28 +282,23 @@ model created with such a form, you need to ensure that the fields
that are _not_ on the form have default values, or are allowed to have
a value of None. If a field isn't specified on a form, the object created
from the form can't provide a value for that field!
->>> PartialArticleForm = form_for_model(Article, fields=('headline','pub_date'))
->>> f = PartialArticleForm(auto_id=False)
+>>> class PartialArticleForm(ModelForm):
+... class Meta:
+... model = Article
+... fields = ('headline','pub_date')
+>>> f = PartialArticleForm(Article(), auto_id=False)
>>> print f
<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
-You can pass a custom Form class to form_for_model. Make sure it's a
-subclass of BaseForm, not Form.
->>> class CustomForm(BaseForm):
-... def say_hello(self):
-... print 'hello'
->>> CategoryForm = form_for_model(Category, form=CustomForm)
->>> f = CategoryForm()
->>> f.say_hello()
-hello
-
Use form_for_instance to create a Form from a model instance. The difference
between this Form and one created via form_for_model is that the object's
current values are inserted as 'initial' data in each Field.
>>> w = Writer.objects.get(name='Mike Royko')
->>> RoykoForm = form_for_instance(w)
->>> f = RoykoForm(auto_id=False)
+>>> class RoykoForm(ModelForm):
+... class Meta:
+... model = Writer
+>>> f = RoykoForm(w, auto_id=False)
>>> print f
<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr>
@@ -243,8 +306,10 @@ current values are inserted as 'initial' data in each Field.
>>> art.save()
>>> art.id
1
->>> TestArticleForm = form_for_instance(art)
->>> f = TestArticleForm(auto_id=False)
+>>> class TestArticleForm(ModelForm):
+... class Meta:
+... model = Article
+>>> f = TestArticleForm(art, auto_id=False)
>>> print f.as_ul()
<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li>
@@ -266,7 +331,7 @@ current values are inserted as 'initial' data in each Field.
<option value="2">It&#39;s a test</option>
<option value="3">Third test</option>
</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li>
->>> f = TestArticleForm({'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'})
+>>> f = TestArticleForm(art, {'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'})
>>> f.is_valid()
True
>>> test_art = f.save()
@@ -278,8 +343,11 @@ u'Test headline'
You can create a form over a subset of the available fields
by specifying a 'fields' argument to form_for_instance.
->>> PartialArticleForm = form_for_instance(art, fields=('headline', 'slug', 'pub_date'))
->>> f = PartialArticleForm({'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False)
+>>> class PartialArticleForm(ModelForm):
+... class Meta:
+... model = Article
+... fields=('headline', 'slug', 'pub_date')
+>>> f = PartialArticleForm(art, {'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False)
>>> print f.as_ul()
<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
@@ -299,8 +367,10 @@ Add some categories and test the many-to-many form output.
>>> new_art.categories.add(Category.objects.get(name='Entertainment'))
>>> new_art.categories.all()
[<Category: Entertainment>]
->>> TestArticleForm = form_for_instance(new_art)
->>> f = TestArticleForm(auto_id=False)
+>>> class TestArticleForm(ModelForm):
+... class Meta:
+... model = Article
+>>> f = TestArticleForm(new_art, auto_id=False)
>>> print f.as_ul()
<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
@@ -323,7 +393,7 @@ Add some categories and test the many-to-many form output.
<option value="3">Third test</option>
</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li>
->>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
+>>> f = TestArticleForm(new_art, {'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
... 'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']})
>>> new_art = f.save()
>>> new_art.id
@@ -333,7 +403,7 @@ Add some categories and test the many-to-many form output.
[<Category: Entertainment>, <Category: It's a test>]
Now, submit form data with no categories. This deletes the existing categories.
->>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
+>>> f = TestArticleForm(new_art, {'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
... 'writer': u'1', 'article': u'Hello.'})
>>> new_art = f.save()
>>> new_art.id
@@ -343,8 +413,10 @@ Now, submit form data with no categories. This deletes the existing categories.
[]
Create a new article, with categories, via the form.
->>> ArticleForm = form_for_model(Article)
->>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
+>>> class ArticleForm(ModelForm):
+... class Meta:
+... model = Article
+>>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
>>> new_art = f.save()
>>> new_art.id
@@ -354,8 +426,10 @@ Create a new article, with categories, via the form.
[<Category: Entertainment>, <Category: It's a test>]
Create a new article, with no categories, via the form.
->>> ArticleForm = form_for_model(Article)
->>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
+>>> class ArticleForm(ModelForm):
+... class Meta:
+... model = Article
+>>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
... 'writer': u'1', 'article': u'Test.'})
>>> new_art = f.save()
>>> new_art.id
@@ -366,8 +440,10 @@ Create a new article, with no categories, via the form.
Create a new article, with categories, via the form, but use commit=False.
The m2m data won't be saved until save_m2m() is invoked on the form.
->>> ArticleForm = form_for_model(Article)
->>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01',
+>>> class ArticleForm(ModelForm):
+... class Meta:
+... model = Article
+>>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01',
... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
>>> new_art = f.save(commit=False)
@@ -386,10 +462,10 @@ The m2m data won't be saved until save_m2m() is invoked on the form.
>>> new_art.categories.order_by('name')
[<Category: Entertainment>, <Category: It's a test>]
-Here, we define a custom Form. Because it happens to have the same fields as
-the Category model, we can use save_instance() to apply its changes to an
+Here, we define a custom ModelForm. Because it happens to have the same fields as
+the Category model, we can just call the form's save() to apply its changes to an
existing Category instance.
->>> class ShortCategory(Form):
+>>> class ShortCategory(ModelForm):
... name = CharField(max_length=5)
... slug = CharField(max_length=5)
... url = CharField(max_length=3)
@@ -398,8 +474,8 @@ existing Category instance.
<Category: Third test>
>>> cat.id
3
->>> sc = ShortCategory({'name': 'Third', 'slug': 'third', 'url': '3rd'})
->>> save_instance(sc, cat)
+>>> form = ShortCategory(cat, {'name': 'Third', 'slug': 'third', 'url': '3rd'})
+>>> form.save()
<Category: Third>
>>> Category.objects.get(id=3)
<Category: Third>
@@ -407,8 +483,10 @@ existing Category instance.
Here, we demonstrate that choices for a ForeignKey ChoiceField are determined
at runtime, based on the data in the database when the form is displayed, not
the data in the database when the form is instantiated.
->>> ArticleForm = form_for_model(Article)
->>> f = ArticleForm(auto_id=False)
+>>> class ArticleForm(ModelForm):
+... class Meta:
+... model = Article
+>>> f = ArticleForm(Article(), auto_id=False)
>>> print f.as_ul()
<li>Headline: <input type="text" name="headline" maxlength="50" /></li>
<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
@@ -609,60 +687,12 @@ ValidationError: [u'Select a valid choice. 4 is not one of the available choices
# PhoneNumberField ############################################################
->>> PhoneNumberForm = form_for_model(PhoneNumber)
->>> f = PhoneNumberForm({'phone': '(312) 555-1212', 'description': 'Assistance'})
+>>> class PhoneNumberForm(ModelForm):
+... class Meta:
+... model = PhoneNumber
+>>> f = PhoneNumberForm(PhoneNumber(), {'phone': '(312) 555-1212', 'description': 'Assistance'})
>>> f.is_valid()
True
>>> f.cleaned_data
{'phone': u'312-555-1212', 'description': u'Assistance'}
-
-# form_for_* blank choices ####################################################
-
-Show the form for a new Car. Note that steering field doesn't include the blank choice,
-because the field is obligatory and has an explicit default.
->>> CarForm = form_for_model(Car)
->>> f = CarForm(auto_id=False)
->>> print f
-<tr><th>Name:</th><td><input type="text" name="name" maxlength="50" /></td></tr>
-<tr><th>Steering:</th><td><select name="steering">
-<option value="left" selected="selected">Left steering wheel</option>
-<option value="right">Right steering wheel</option>
-</select></td></tr>
-<tr><th>Fuel:</th><td><select name="fuel">
-<option value="" selected="selected">---------</option>
-<option value="gas">Gasoline</option>
-<option value="diesel">Diesel</option>
-<option value="other">Other</option>
-</select></td></tr>
-<tr><th>Transmission:</th><td><select name="transmission">
-<option value="" selected="selected">---------</option>
-<option value="at">Automatic</option>
-<option value="mt">Manual</option>
-<option value="cvt">CVT</option>
-</select><br />Leave empty if not applicable.</td></tr>
-
-Create a Car, and display the form for modifying it. Note that now the fuel
-selector doesn't include the blank choice as well, since the field is
-obligatory and can not be changed to be blank.
->>> honda = Car(name='Honda Accord Wagon', steering='right', fuel='gas', transmission='at')
->>> honda.save()
->>> HondaForm = form_for_instance(honda)
->>> f = HondaForm(auto_id=False)
->>> print f
-<tr><th>Name:</th><td><input type="text" name="name" value="Honda Accord Wagon" maxlength="50" /></td></tr>
-<tr><th>Steering:</th><td><select name="steering">
-<option value="left">Left steering wheel</option>
-<option value="right" selected="selected">Right steering wheel</option>
-</select></td></tr>
-<tr><th>Fuel:</th><td><select name="fuel">
-<option value="gas" selected="selected">Gasoline</option>
-<option value="diesel">Diesel</option>
-<option value="other">Other</option>
-</select></td></tr>
-<tr><th>Transmission:</th><td><select name="transmission">
-<option value="">---------</option>
-<option value="at" selected="selected">Automatic</option>
-<option value="mt">Manual</option>
-<option value="cvt">CVT</option>
-</select><br />Leave empty if not applicable.</td></tr>
"""}
diff --git a/tests/modeltests/select_related/models.py b/tests/modeltests/select_related/models.py
index a52cc986a4..09877eb9b0 100644
--- a/tests/modeltests/select_related/models.py
+++ b/tests/modeltests/select_related/models.py
@@ -1,5 +1,5 @@
"""
-40. Tests for select_related()
+41. Tests for select_related()
``select_related()`` follows all relationships and pre-caches any foreign key
values so that complex trees can be fetched in a single query. However, this
diff --git a/tests/modeltests/serializers/models.py b/tests/modeltests/serializers/models.py
index a2388223f0..1c7dbabfd1 100644
--- a/tests/modeltests/serializers/models.py
+++ b/tests/modeltests/serializers/models.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
-41. Serialization
+42. Serialization
``django.core.serializers`` provides interfaces to converting Django querysets
to and from "flat" data (i.e. strings).
diff --git a/tests/modeltests/test_client/models.py b/tests/modeltests/test_client/models.py
index c7aaaff67d..1a6e1bdc18 100644
--- a/tests/modeltests/test_client/models.py
+++ b/tests/modeltests/test_client/models.py
@@ -1,6 +1,6 @@
# coding: utf-8
"""
-38. Testing using the Test Client
+39. Testing using the Test Client
The test client is a class that can act like a simple
browser for testing purposes.
diff --git a/tests/modeltests/user_commands/models.py b/tests/modeltests/user_commands/models.py
index 5f96806dac..6db4b049df 100644
--- a/tests/modeltests/user_commands/models.py
+++ b/tests/modeltests/user_commands/models.py
@@ -1,5 +1,5 @@
"""
-37. User-registered management commands
+38. User-registered management commands
The manage.py utility provides a number of useful commands for managing a
Django project. If you want to add a utility command of your own, you can.
@@ -27,4 +27,4 @@ Traceback (most recent call last):
CommandError: Unknown command: 'explode'
-"""} \ No newline at end of file
+"""}
diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py
index e94ea33139..9ac2722b0a 100644
--- a/tests/regressiontests/cache/tests.py
+++ b/tests/regressiontests/cache/tests.py
@@ -72,6 +72,8 @@ class Cache(unittest.TestCase):
'function' : f,
'class' : C,
}
+ cache.set("stuff", stuff)
+ self.assertEqual(cache.get("stuff"), stuff)
def test_expiration(self):
# expiration
diff --git a/tests/regressiontests/forms/localflavor/za.py b/tests/regressiontests/forms/localflavor/za.py
new file mode 100644
index 0000000000..a948964b8d
--- /dev/null
+++ b/tests/regressiontests/forms/localflavor/za.py
@@ -0,0 +1,40 @@
+tests = r"""
+# ZAIDField #################################################################
+
+ZAIDField validates that the date is a valid birthdate and that the value
+has a valid checksum. It allows spaces and dashes, and returns a plain
+string of digits.
+>>> from django.contrib.localflavor.za.forms import ZAIDField
+>>> f = ZAIDField()
+>>> f.clean('0002290001003')
+'0002290001003'
+>>> f.clean('000229 0001 003')
+'0002290001003'
+>>> f.clean('0102290001001')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a valid South African ID number']
+>>> f.clean('811208')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a valid South African ID number']
+>>> f.clean('0002290001004')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a valid South African ID number']
+
+# ZAPostCodeField ###########################################################
+>>> from django.contrib.localflavor.za.forms import ZAPostCodeField
+>>> f = ZAPostCodeField()
+>>> f.clean('abcd')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a valid South African postal code']
+>>> f.clean('0000')
+u'0000'
+>>> f.clean(' 7530')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a valid South African postal code']
+
+"""
diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
index e646ce8f82..f8c5c486e4 100644
--- a/tests/regressiontests/forms/tests.py
+++ b/tests/regressiontests/forms/tests.py
@@ -21,6 +21,7 @@ from localflavor.pl import tests as localflavor_pl_tests
from localflavor.sk import tests as localflavor_sk_tests
from localflavor.uk import tests as localflavor_uk_tests
from localflavor.us import tests as localflavor_us_tests
+from localflavor.za import tests as localflavor_za_tests
from regressions import tests as regression_tests
from util import tests as util_tests
from widgets import tests as widgets_tests
@@ -48,6 +49,7 @@ __test__ = {
'localflavor_sk_tests': localflavor_sk_tests,
'localflavor_uk_tests': localflavor_uk_tests,
'localflavor_us_tests': localflavor_us_tests,
+ 'localflavor_za_tests': localflavor_za_tests,
'regression_tests': regression_tests,
'util_tests': util_tests,
'widgets_tests': widgets_tests,
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index 2ffc62f90d..94e792cf54 100644
--- a/tests/regressiontests/i18n/tests.py
+++ b/tests/regressiontests/i18n/tests.py
@@ -43,7 +43,7 @@ u'django'
Translating a string requiring no auto-escaping shouldn't change the "safe"
status.
->>> from django.utils.safestring import mark_safe
+>>> from django.utils.safestring import mark_safe, SafeString
>>> s = mark_safe('Password')
>>> type(s)
<class 'django.utils.safestring.SafeString'>
@@ -51,6 +51,19 @@ status.
>>> type(ugettext(s))
<class 'django.utils.safestring.SafeUnicode'>
>>> deactivate()
+
+>>> SafeString('a') + s
+'aPassword'
+>>> s + SafeString('a')
+'Passworda'
+>>> s + mark_safe('a')
+'Passworda'
+>>> mark_safe('a') + s
+'aPassword'
+>>> mark_safe('a') + mark_safe('s')
+'as'
+>>> print s
+Password
"""
__test__ = {
diff --git a/tests/regressiontests/middleware/__init__.py b/tests/regressiontests/middleware/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/middleware/__init__.py
diff --git a/tests/regressiontests/middleware/tests.py b/tests/regressiontests/middleware/tests.py
new file mode 100644
index 0000000000..cb5c29abe1
--- /dev/null
+++ b/tests/regressiontests/middleware/tests.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+
+from django.test import TestCase
+from django.http import HttpRequest
+from django.middleware.common import CommonMiddleware
+from django.conf import settings
+
+class CommonMiddlewareTest(TestCase):
+ def _get_request(self, path):
+ request = HttpRequest()
+ request.META = {
+ 'SERVER_NAME': 'testserver',
+ 'SERVER_PORT': 80,
+ }
+ request.path = "/middleware/%s" % path
+ return request
+
+ def test_append_slash_have_slash(self):
+ """
+ tests that urls with slashes go unmolested
+ """
+ settings.APPEND_SLASH = True
+ request = self._get_request('slash/')
+ self.assertEquals(CommonMiddleware().process_request(request), None)
+
+ def test_append_slash_slashless_resource(self):
+ """
+ tests that matches to explicit slashless urls go unmolested
+ """
+ settings.APPEND_SLASH = True
+ request = self._get_request('noslash')
+ self.assertEquals(CommonMiddleware().process_request(request), None)
+
+ def test_append_slash_slashless_unknown(self):
+ """
+ tests that APPEND_SLASH doesn't redirect to unknown resources
+ """
+ settings.APPEND_SLASH = True
+ request = self._get_request('unknown')
+ self.assertEquals(CommonMiddleware().process_request(request), None)
+
+ def test_append_slash_redirect(self):
+ """
+ tests that APPEND_SLASH redirects slashless urls to a valid pattern
+ """
+ settings.APPEND_SLASH = True
+ request = self._get_request('slash')
+ r = CommonMiddleware().process_request(request)
+ self.assertEquals(r.status_code, 301)
+ self.assertEquals(r['Location'], 'http://testserver/middleware/slash/')
+
+ def test_append_slash_no_redirect_on_POST_in_DEBUG(self):
+ """
+ tests that while in debug mode, an exception is raised with a warning
+ when a failed attempt is made to POST to an url which would normally be
+ redirected to a slashed version
+ """
+ settings.APPEND_SLASH = True
+ settings.DEBUG = True
+ request = self._get_request('slash')
+ request.method = 'POST'
+ self.assertRaises(
+ RuntimeError,
+ CommonMiddleware().process_request,
+ request)
+ try:
+ CommonMiddleware().process_request(request)
+ except RuntimeError, e:
+ self.assertTrue('end in a slash' in str(e))
+
+ def test_append_slash_disabled(self):
+ """
+ tests disabling append slash functionality
+ """
+ settings.APPEND_SLASH = False
+ request = self._get_request('slash')
+ self.assertEquals(CommonMiddleware().process_request(request), None)
+
+ def test_append_slash_quoted(self):
+ """
+ tests that urls which require quoting are redirected to their slash
+ version ok
+ """
+ settings.APPEND_SLASH = True
+ request = self._get_request('needsquoting#')
+ r = CommonMiddleware().process_request(request)
+ self.assertEquals(r.status_code, 301)
+ self.assertEquals(
+ r['Location'],
+ 'http://testserver/middleware/needsquoting%23/')
+
diff --git a/tests/regressiontests/middleware/urls.py b/tests/regressiontests/middleware/urls.py
new file mode 100644
index 0000000000..88a4b37ddc
--- /dev/null
+++ b/tests/regressiontests/middleware/urls.py
@@ -0,0 +1,7 @@
+from django.conf.urls.defaults import patterns
+
+urlpatterns = patterns('',
+ (r'^noslash$', 'view'),
+ (r'^slash/$', 'view'),
+ (r'^needsquoting#/$', 'view'),
+)
diff --git a/tests/regressiontests/string_lookup/models.py b/tests/regressiontests/string_lookup/models.py
index 12ebd0cf07..9deeb18763 100644
--- a/tests/regressiontests/string_lookup/models.py
+++ b/tests/regressiontests/string_lookup/models.py
@@ -18,26 +18,26 @@ class Bar(models.Model):
return "Bar %s" % self.place.name
class Whiz(models.Model):
- name = models.CharField(max_length = 50)
+ name = models.CharField(max_length=50)
def __unicode__(self):
return "Whiz %s" % self.name
class Child(models.Model):
parent = models.OneToOneField('Base')
- name = models.CharField(max_length = 50)
+ name = models.CharField(max_length=50)
def __unicode__(self):
return "Child %s" % self.name
class Base(models.Model):
- name = models.CharField(max_length = 50)
+ name = models.CharField(max_length=50)
def __unicode__(self):
return "Base %s" % self.name
class Article(models.Model):
- name = models.CharField(maxlength = 50)
+ name = models.CharField(max_length=50)
text = models.TextField()
def __str__(self):
diff --git a/tests/regressiontests/templates/context.py b/tests/regressiontests/templates/context.py
new file mode 100644
index 0000000000..d8b0f39abe
--- /dev/null
+++ b/tests/regressiontests/templates/context.py
@@ -0,0 +1,18 @@
+# coding: utf-8
+
+context_tests = r"""
+>>> from django.template import Context
+>>> c = Context({'a': 1, 'b': 'xyzzy'})
+>>> c['a']
+1
+>>> c.push()
+{}
+>>> c['a'] = 2
+>>> c['a']
+2
+>>> c.pop()
+{'a': 2}
+>>> c['a']
+1
+"""
+
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index cbbd88b06c..846023afc9 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -18,11 +18,13 @@ from django.utils.safestring import mark_safe
from django.utils.tzinfo import LocalTimezone
from unicode import unicode_tests
+from context import context_tests
import filters
# Some other tests we would like to run
__test__ = {
'unicode': unicode_tests,
+ 'context': context_tests,
}
#################################
diff --git a/tests/regressiontests/templates/unicode.py b/tests/regressiontests/templates/unicode.py
index efda11c2da..e5f308d202 100644
--- a/tests/regressiontests/templates/unicode.py
+++ b/tests/regressiontests/templates/unicode.py
@@ -3,6 +3,7 @@
unicode_tests = ur"""
Templates can be created from unicode strings.
>>> from django.template import *
+>>> from django.utils.safestring import SafeData
>>> t1 = Template(u'ŠĐĆŽćžšđ {{ var }}')
Templates can also be created from bytestrings. These are assumed by encoded
@@ -24,10 +25,13 @@ Contexts can be constructed from unicode or UTF-8 bytestrings.
>>> c4 = Context({u'var': '\xc4\x90\xc4\x91'})
Since both templates and all four contexts represent the same thing, they all
-render the same (and are returned as unicode objects).
+render the same (and are returned as unicode objects and "safe" objects as
+well, for auto-escaping purposes).
>>> t1.render(c3) == t2.render(c3)
True
->>> type(t1.render(c3))
-<type 'unicode'>
+>>> isinstance(t1.render(c3), unicode)
+True
+>>> isinstance(t1.render(c3), SafeData)
+True
"""
diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
index 9e0bbb2d66..956432e7d5 100644
--- a/tests/regressiontests/views/views.py
+++ b/tests/regressiontests/views/views.py
@@ -1,7 +1,5 @@
from django.http import HttpResponse
-from django.template import RequestContext
def index_page(request):
"""Dummy index page"""
return HttpResponse('<html><body>Dummy page</body></html>')
-
diff --git a/tests/runtests.py b/tests/runtests.py
index 843850074b..2d3b737cec 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -107,8 +107,7 @@ def django_tests(verbosity, interactive, test_labels):
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.common.CommonMiddleware',
)
- if not hasattr(settings, 'SITE_ID'):
- settings.SITE_ID = 1
+ settings.SITE_ID = 1
# Load all the ALWAYS_INSTALLED_APPS.
# (This import statement is intentionally delayed until after we
diff --git a/tests/urls.py b/tests/urls.py
index d7251007c5..174e06969b 100644
--- a/tests/urls.py
+++ b/tests/urls.py
@@ -14,4 +14,7 @@ urlpatterns = patterns('',
# django built-in views
(r'^views/', include('regressiontests.views.urls')),
+
+ # test urlconf for middleware tests
+ (r'^middleware/', include('regressiontests.middleware.urls')),
)