summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAdrian Holovaty <adrian@holovaty.com>2007-03-25 21:49:00 +0000
committerAdrian Holovaty <adrian@holovaty.com>2007-03-25 21:49:00 +0000
commit132cf258cbdce8bac1d7a3d713c3927f43ead1ed (patch)
tree2ce01dc4a7dd0374e085f706379d181e0b286507 /tests
parent25c15b17a86fa95b5374b9ef6366450b28a28b7a (diff)
newforms-admin: Merged to [4823]
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@4824 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.py2
-rw-r--r--tests/modeltests/fixtures/models.py2
-rw-r--r--tests/modeltests/generic_relations/models.py2
-rw-r--r--tests/modeltests/get_object_or_404/models.py8
-rw-r--r--tests/modeltests/get_or_create/models.py2
-rw-r--r--tests/modeltests/m2m_and_m2o/models.py2
-rw-r--r--tests/modeltests/m2m_recursive/models.py2
-rw-r--r--tests/modeltests/manipulators/models.py2
-rw-r--r--tests/modeltests/model_forms/models.py2
-rw-r--r--tests/modeltests/pagination/models.py2
-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.py40
-rw-r--r--tests/modeltests/test_client/urls.py1
-rw-r--r--tests/modeltests/test_client/views.py34
-rw-r--r--tests/modeltests/validation/models.py2
-rw-r--r--tests/regressiontests/defaultfilters/tests.py6
-rw-r--r--tests/regressiontests/forms/tests.py323
-rw-r--r--tests/regressiontests/serializers_regress/models.py19
-rw-r--r--tests/regressiontests/serializers_regress/tests.py20
21 files changed, 457 insertions, 20 deletions
diff --git a/tests/modeltests/empty/models.py b/tests/modeltests/empty/models.py
index 0e5d572504..2493b53837 100644
--- a/tests/modeltests/empty/models.py
+++ b/tests/modeltests/empty/models.py
@@ -1,5 +1,5 @@
"""
-Empty model tests
+39. 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 da4cd38974..8e803d00d8 100644
--- a/tests/modeltests/field_defaults/models.py
+++ b/tests/modeltests/field_defaults/models.py
@@ -1,5 +1,5 @@
"""
-31. Callable defaults
+32. Callable defaults
You can pass callable objects as the ``default`` parameter to a field. When
the object is created without an explicit value passed in, Django will call
diff --git a/tests/modeltests/fixtures/models.py b/tests/modeltests/fixtures/models.py
index afef6a7389..c75e6723fd 100644
--- a/tests/modeltests/fixtures/models.py
+++ b/tests/modeltests/fixtures/models.py
@@ -1,5 +1,5 @@
"""
-39. Fixtures.
+37. Fixtures.
Fixtures are a way of loading data into the database in bulk. Fixure data
can be stored in any serializable format (including JSON and XML). Fixtures
diff --git a/tests/modeltests/generic_relations/models.py b/tests/modeltests/generic_relations/models.py
index 2bfb55e618..2b2f64165f 100644
--- a/tests/modeltests/generic_relations/models.py
+++ b/tests/modeltests/generic_relations/models.py
@@ -1,5 +1,5 @@
"""
-33. Generic relations
+34. Generic relations
Generic relations let an object have a foreign key to any object through a
content-type/object-id field. A generic foreign key can point to any object,
diff --git a/tests/modeltests/get_object_or_404/models.py b/tests/modeltests/get_object_or_404/models.py
index 79bcc6f52c..2ad459669f 100644
--- a/tests/modeltests/get_object_or_404/models.py
+++ b/tests/modeltests/get_object_or_404/models.py
@@ -1,5 +1,5 @@
"""
-34. DB-API Shortcuts
+35. DB-API Shortcuts
get_object_or_404 is a shortcut function to be used in view functions for
performing a get() lookup and raising a Http404 exception if a DoesNotExist
@@ -44,7 +44,7 @@ __test__ = {'API_TESTS':"""
>>> get_object_or_404(Article, title="Foo")
Traceback (most recent call last):
...
-Http404
+Http404: No Article matches the given query.
# Create an Article.
>>> article = Article.objects.create(title="Run away!")
@@ -63,7 +63,7 @@ Http404
>>> get_object_or_404(a.article_set, title__contains="Camelot")
Traceback (most recent call last):
...
-Http404
+Http404: No Article matches the given query.
# Custom managers can be used too.
>>> get_object_or_404(Article.by_a_sir, title="Run away!")
@@ -77,7 +77,7 @@ Http404
>>> get_list_or_404(a.article_set, title__icontains='Shrubbery')
Traceback (most recent call last):
...
-Http404
+Http404: No Article matches the given query.
# Custom managers can be used too.
>>> get_list_or_404(Article.by_a_sir, title__icontains="Run")
diff --git a/tests/modeltests/get_or_create/models.py b/tests/modeltests/get_or_create/models.py
index b4f39ceded..f974a82dee 100644
--- a/tests/modeltests/get_or_create/models.py
+++ b/tests/modeltests/get_or_create/models.py
@@ -1,5 +1,5 @@
"""
-32. get_or_create()
+33. get_or_create()
get_or_create() does what it says: it tries to look up an object with the given
parameters. If an object isn't found, it creates one with the given parameters.
diff --git a/tests/modeltests/m2m_and_m2o/models.py b/tests/modeltests/m2m_and_m2o/models.py
index 7fc66ed5a0..09affb002f 100644
--- a/tests/modeltests/m2m_and_m2o/models.py
+++ b/tests/modeltests/m2m_and_m2o/models.py
@@ -1,5 +1,5 @@
"""
-28. Many-to-many and many-to-one relationships to the same table
+29. Many-to-many and many-to-one relationships to the same table
Make sure to set ``related_name`` if you use relationships to the same table.
"""
diff --git a/tests/modeltests/m2m_recursive/models.py b/tests/modeltests/m2m_recursive/models.py
index 9f31cf92c0..15c713a759 100644
--- a/tests/modeltests/m2m_recursive/models.py
+++ b/tests/modeltests/m2m_recursive/models.py
@@ -1,5 +1,5 @@
"""
-27. Many-to-many relationships between the same two tables
+28. Many-to-many relationships between the same two tables
In this example, A Person can have many friends, who are also people. Friendship is a
symmetrical relationship - if I am your friend, you are my friend.
diff --git a/tests/modeltests/manipulators/models.py b/tests/modeltests/manipulators/models.py
index e5b8be55b5..1a44cfe7f4 100644
--- a/tests/modeltests/manipulators/models.py
+++ b/tests/modeltests/manipulators/models.py
@@ -1,5 +1,5 @@
"""
-26. Default manipulators
+27. Default manipulators
Each model gets an AddManipulator and ChangeManipulator by default.
"""
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py
index e64174a23f..d91f1d2d45 100644
--- a/tests/modeltests/model_forms/models.py
+++ b/tests/modeltests/model_forms/models.py
@@ -1,5 +1,5 @@
"""
-34. Generating HTML forms from models
+36. Generating HTML forms from models
Django provides shortcuts for creating Form objects from a model class and a
model instance.
diff --git a/tests/modeltests/pagination/models.py b/tests/modeltests/pagination/models.py
index 3319b5cafa..94deb885f5 100644
--- a/tests/modeltests/pagination/models.py
+++ b/tests/modeltests/pagination/models.py
@@ -1,5 +1,5 @@
"""
-29. Object pagination
+30. Object pagination
Django provides a framework for paginating a list of objects in a few lines
of code. This is often useful for dividing search results or long lists of
diff --git a/tests/modeltests/select_related/models.py b/tests/modeltests/select_related/models.py
index 8a19267870..cd34bd1d84 100644
--- a/tests/modeltests/select_related/models.py
+++ b/tests/modeltests/select_related/models.py
@@ -1,5 +1,5 @@
"""
-XXX. Tests for ``select_related()``
+40. 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 e86546c6fe..339303fc0a 100644
--- a/tests/modeltests/serializers/models.py
+++ b/tests/modeltests/serializers/models.py
@@ -1,5 +1,5 @@
"""
-XXX. Serialization
+41. 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 a3a9749162..44ddffb55f 100644
--- a/tests/modeltests/test_client/models.py
+++ b/tests/modeltests/test_client/models.py
@@ -1,5 +1,5 @@
"""
-39. Testing using the Test Client
+38. Testing using the Test Client
The test client is a class that can act like a simple
browser for testing purposes.
@@ -81,7 +81,43 @@ class ClientTest(TestCase):
# Check that the response was a 302 (redirect)
self.assertEqual(response.status_code, 302)
-
+
+ def test_valid_form(self):
+ "POST valid data to a form"
+ post_data = {
+ 'text': 'Hello World',
+ 'email': 'foo@example.com',
+ 'value': 37,
+ 'single': 'b',
+ 'multi': ('b','c','e')
+ }
+ response = self.client.post('/test_client/form_view/', post_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.template.name, "Valid POST Template")
+
+ def test_incomplete_data_form(self):
+ "POST incomplete data to a form"
+ post_data = {
+ 'text': 'Hello World',
+ 'value': 37
+ }
+ response = self.client.post('/test_client/form_view/', post_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.template.name, "Invalid POST Template")
+
+ def test_form_error(self):
+ "POST erroneous data to a form"
+ post_data = {
+ 'text': 'Hello World',
+ 'email': 'not an email address',
+ 'value': 37,
+ 'single': 'b',
+ 'multi': ('b','c','e')
+ }
+ response = self.client.post('/test_client/form_view/', post_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.template.name, "Invalid POST Template")
+
def test_unknown_page(self):
"GET an invalid URL"
response = self.client.get('/test_client/unknown_view/')
diff --git a/tests/modeltests/test_client/urls.py b/tests/modeltests/test_client/urls.py
index 0bef1e9b71..707ecc186d 100644
--- a/tests/modeltests/test_client/urls.py
+++ b/tests/modeltests/test_client/urls.py
@@ -6,6 +6,7 @@ urlpatterns = patterns('',
(r'^post_view/$', views.post_view),
(r'^raw_post_view/$', views.raw_post_view),
(r'^redirect_view/$', views.redirect_view),
+ (r'^form_view/$', views.form_view),
(r'^login_protected_view/$', views.login_protected_view),
(r'^session_view/$', views.session_view),
(r'^broken_view/$', views.broken_view)
diff --git a/tests/modeltests/test_client/views.py b/tests/modeltests/test_client/views.py
index 653e9a10e9..36ec144cf6 100644
--- a/tests/modeltests/test_client/views.py
+++ b/tests/modeltests/test_client/views.py
@@ -2,6 +2,8 @@ from xml.dom.minidom import parseString
from django.template import Context, Template
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.decorators import login_required
+from django.newforms.forms import Form
+from django.newforms import fields
def get_view(request):
"A simple view that expects a GET request, and returns a rendered template"
@@ -45,7 +47,39 @@ def raw_post_view(request):
def redirect_view(request):
"A view that redirects all requests to the GET view"
return HttpResponseRedirect('/test_client/get_view/')
+
+TestChoices = (
+ ('a', 'First Choice'),
+ ('b', 'Second Choice'),
+ ('c', 'Third Choice'),
+ ('d', 'Fourth Choice'),
+ ('e', 'Fifth Choice')
+)
+
+class TestForm(Form):
+ text = fields.CharField()
+ email = fields.EmailField()
+ value = fields.IntegerField()
+ single = fields.ChoiceField(choices=TestChoices)
+ multi = fields.MultipleChoiceField(choices=TestChoices)
+
+def form_view(request):
+ "A view that tests a simple form"
+ if request.method == 'POST':
+ form = TestForm(request.POST)
+ if form.is_valid():
+ t = Template('Valid POST data.', name='Valid POST Template')
+ c = Context()
+ else:
+ t = Template('Invalid POST data. {{ form.errors }}', name='Invalid POST Template')
+ c = Context({'form': form})
+ else:
+ form = TestForm()
+ t = Template('Viewing base form. {{ form }}.', name='Form GET Template')
+ c = Context({'form': form})
+ return HttpResponse(t.render(c))
+
def login_protected_view(request):
"A simple view that is login protected."
t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
diff --git a/tests/modeltests/validation/models.py b/tests/modeltests/validation/models.py
index 1066faca4f..b31f981aac 100644
--- a/tests/modeltests/validation/models.py
+++ b/tests/modeltests/validation/models.py
@@ -1,5 +1,5 @@
"""
-30. Validation
+31. Validation
This is an experimental feature!
diff --git a/tests/regressiontests/defaultfilters/tests.py b/tests/regressiontests/defaultfilters/tests.py
index c850806052..db3f7fab2a 100644
--- a/tests/regressiontests/defaultfilters/tests.py
+++ b/tests/regressiontests/defaultfilters/tests.py
@@ -133,6 +133,12 @@ u'\xcb'
>>> wordwrap('this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14)
"this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid"
+>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',14)
+'this is a\nshort\nparagraph of\ntext.\n But this\nline should be\nindented'
+
+>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',15)
+'this is a short\nparagraph of\ntext.\n But this line\nshould be\nindented'
+
>>> ljust('test', 10)
'test '
diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
index a9ce8d23b3..f805a221aa 100644
--- a/tests/regressiontests/forms/tests.py
+++ b/tests/regressiontests/forms/tests.py
@@ -3556,6 +3556,329 @@ u''
>>> f.clean('')
u''
+# FRZipCodeField #############################################################
+
+FRZipCodeField validates that the data is a valid FR zipcode.
+>>> from django.contrib.localflavor.fr.forms import FRZipCodeField
+>>> f = FRZipCodeField()
+>>> f.clean('75001')
+u'75001'
+>>> f.clean('93200')
+u'93200'
+>>> f.clean('2A200')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a zip code in the format XXXXX.']
+>>> f.clean('980001')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a zip code in the format XXXXX.']
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = FRZipCodeField(required=False)
+>>> f.clean('75001')
+u'75001'
+>>> f.clean('93200')
+u'93200'
+>>> f.clean('2A200')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a zip code in the format XXXXX.']
+>>> f.clean('980001')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a zip code in the format XXXXX.']
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+
+
+# FRPhoneNumberField ##########################################################
+
+FRPhoneNumberField validates that the data is a valid french phone number.
+It's normalized to 0X XX XX XX XX format. Dots are valid too.
+>>> from django.contrib.localflavor.fr.forms import FRPhoneNumberField
+>>> f = FRPhoneNumberField()
+>>> f.clean('01 55 44 58 64')
+u'01 55 44 58 64'
+>>> f.clean('0155445864')
+u'01 55 44 58 64'
+>>> f.clean('01 5544 5864')
+u'01 55 44 58 64'
+>>> f.clean('01 55.44.58.64')
+u'01 55 44 58 64'
+>>> f.clean('01.55.44.58.64')
+u'01 55 44 58 64'
+>>> f.clean('01,55,44,58,64')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.']
+>>> f.clean('555 015 544')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.']
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = FRPhoneNumberField(required=False)
+>>> f.clean('01 55 44 58 64')
+u'01 55 44 58 64'
+>>> f.clean('0155445864')
+u'01 55 44 58 64'
+>>> f.clean('01 5544 5864')
+u'01 55 44 58 64'
+>>> f.clean('01 55.44.58.64')
+u'01 55 44 58 64'
+>>> f.clean('01.55.44.58.64')
+u'01 55 44 58 64'
+>>> f.clean('01,55,44,58,64')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.']
+>>> f.clean('555 015 544')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.']
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+
+# FRDepartmentSelect ###############################################################
+
+FRDepartmentSelect is a Select widget that uses a list of french departments
+including DOM TOM
+>>> from django.contrib.localflavor.fr.forms import FRDepartmentSelect
+>>> w = FRDepartmentSelect()
+>>> print w.render('dep', 'Paris')
+<select name="dep">
+<option value="01">01 - Ain</option>
+<option value="02">02 - Aisne</option>
+<option value="03">03 - Allier</option>
+<option value="04">04 - Alpes-de-Haute-Provence</option>
+<option value="05">05 - Hautes-Alpes</option>
+<option value="06">06 - Alpes-Maritimes</option>
+<option value="07">07 - Ardeche</option>
+<option value="08">08 - Ardennes</option>
+<option value="09">09 - Ariege</option>
+<option value="10">10 - Aube</option>
+<option value="11">11 - Aude</option>
+<option value="12">12 - Aveyron</option>
+<option value="13">13 - Bouches-du-Rhone</option>
+<option value="14">14 - Calvados</option>
+<option value="15">15 - Cantal</option>
+<option value="16">16 - Charente</option>
+<option value="17">17 - Charente-Maritime</option>
+<option value="18">18 - Cher</option>
+<option value="19">19 - Correze</option>
+<option value="21">21 - Cote-d&#39;Or</option>
+<option value="22">22 - Cotes-d&#39;Armor</option>
+<option value="23">23 - Creuse</option>
+<option value="24">24 - Dordogne</option>
+<option value="25">25 - Doubs</option>
+<option value="26">26 - Drome</option>
+<option value="27">27 - Eure</option>
+<option value="28">28 - Eure-et-Loire</option>
+<option value="29">29 - Finistere</option>
+<option value="2A">2A - Corse-du-Sud</option>
+<option value="2B">2B - Haute-Corse</option>
+<option value="30">30 - Gard</option>
+<option value="31">31 - Haute-Garonne</option>
+<option value="32">32 - Gers</option>
+<option value="33">33 - Gironde</option>
+<option value="34">34 - Herault</option>
+<option value="35">35 - Ille-et-Vilaine</option>
+<option value="36">36 - Indre</option>
+<option value="37">37 - Indre-et-Loire</option>
+<option value="38">38 - Isere</option>
+<option value="39">39 - Jura</option>
+<option value="40">40 - Landes</option>
+<option value="41">41 - Loir-et-Cher</option>
+<option value="42">42 - Loire</option>
+<option value="43">43 - Haute-Loire</option>
+<option value="44">44 - Loire-Atlantique</option>
+<option value="45">45 - Loiret</option>
+<option value="46">46 - Lot</option>
+<option value="47">47 - Lot-et-Garonne</option>
+<option value="48">48 - Lozere</option>
+<option value="49">49 - Maine-et-Loire</option>
+<option value="50">50 - Manche</option>
+<option value="51">51 - Marne</option>
+<option value="52">52 - Haute-Marne</option>
+<option value="53">53 - Mayenne</option>
+<option value="54">54 - Meurthe-et-Moselle</option>
+<option value="55">55 - Meuse</option>
+<option value="56">56 - Morbihan</option>
+<option value="57">57 - Moselle</option>
+<option value="58">58 - Nievre</option>
+<option value="59">59 - Nord</option>
+<option value="60">60 - Oise</option>
+<option value="61">61 - Orne</option>
+<option value="62">62 - Pas-de-Calais</option>
+<option value="63">63 - Puy-de-Dome</option>
+<option value="64">64 - Pyrenees-Atlantiques</option>
+<option value="65">65 - Hautes-Pyrenees</option>
+<option value="66">66 - Pyrenees-Orientales</option>
+<option value="67">67 - Bas-Rhin</option>
+<option value="68">68 - Haut-Rhin</option>
+<option value="69">69 - Rhone</option>
+<option value="70">70 - Haute-Saone</option>
+<option value="71">71 - Saone-et-Loire</option>
+<option value="72">72 - Sarthe</option>
+<option value="73">73 - Savoie</option>
+<option value="74">74 - Haute-Savoie</option>
+<option value="75">75 - Paris</option>
+<option value="76">76 - Seine-Maritime</option>
+<option value="77">77 - Seine-et-Marne</option>
+<option value="78">78 - Yvelines</option>
+<option value="79">79 - Deux-Sevres</option>
+<option value="80">80 - Somme</option>
+<option value="81">81 - Tarn</option>
+<option value="82">82 - Tarn-et-Garonne</option>
+<option value="83">83 - Var</option>
+<option value="84">84 - Vaucluse</option>
+<option value="85">85 - Vendee</option>
+<option value="86">86 - Vienne</option>
+<option value="87">87 - Haute-Vienne</option>
+<option value="88">88 - Vosges</option>
+<option value="89">89 - Yonne</option>
+<option value="90">90 - Territoire de Belfort</option>
+<option value="91">91 - Essonne</option>
+<option value="92">92 - Hauts-de-Seine</option>
+<option value="93">93 - Seine-Saint-Denis</option>
+<option value="94">94 - Val-de-Marne</option>
+<option value="95">95 - Val-d&#39;Oise</option>
+<option value="2A">2A - Corse du sud</option>
+<option value="2B">2B - Haute Corse</option>
+<option value="971">971 - Guadeloupe</option>
+<option value="972">972 - Martinique</option>
+<option value="973">973 - Guyane</option>
+<option value="974">974 - La Reunion</option>
+<option value="975">975 - Saint-Pierre-et-Miquelon</option>
+<option value="976">976 - Mayotte</option>
+<option value="984">984 - Terres Australes et Antarctiques</option>
+<option value="986">986 - Wallis et Futuna</option>
+<option value="987">987 - Polynesie Francaise</option>
+<option value="988">988 - Nouvelle-Caledonie</option>
+</select>
+
+# JPPostalCodeField ###############################################################
+
+A form field that validates its input is a Japanese postcode.
+
+Accepts 7 digits(with/out hyphen).
+>>> from django.contrib.localflavor.jp.forms import JPPostalCodeField
+>>> f = JPPostalCodeField()
+>>> f.clean('251-0032')
+u'2510032'
+>>> f.clean('2510032')
+u'2510032'
+>>> f.clean('2510-032')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('251a0032')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('a51-0032')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('25100321')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = JPPostalCodeField(required=False)
+>>> f.clean('251-0032')
+u'2510032'
+>>> f.clean('2510032')
+u'2510032'
+>>> f.clean('2510-032')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
+>>> f.clean('')
+u''
+>>> f.clean(None)
+u''
+
+# JPPrefectureSelect ###############################################################
+
+A Select widget that uses a list of Japanese prefectures as its choices.
+>>> from django.contrib.localflavor.jp.forms import JPPrefectureSelect
+>>> w = JPPrefectureSelect()
+>>> print w.render('prefecture', 'kanagawa')
+<select name="prefecture">
+<option value="hokkaido">Hokkaido</option>
+<option value="aomori">Aomori</option>
+<option value="iwate">Iwate</option>
+<option value="miyagi">Miyagi</option>
+<option value="akita">Akita</option>
+<option value="yamagata">Yamagata</option>
+<option value="fukushima">Fukushima</option>
+<option value="ibaraki">Ibaraki</option>
+<option value="tochigi">Tochigi</option>
+<option value="gunma">Gunma</option>
+<option value="saitama">Saitama</option>
+<option value="chiba">Chiba</option>
+<option value="tokyo">Tokyo</option>
+<option value="kanagawa" selected="selected">Kanagawa</option>
+<option value="yamanashi">Yamanashi</option>
+<option value="nagano">Nagano</option>
+<option value="niigata">Niigata</option>
+<option value="toyama">Toyama</option>
+<option value="ishikawa">Ishikawa</option>
+<option value="fukui">Fukui</option>
+<option value="gifu">Gifu</option>
+<option value="shizuoka">Shizuoka</option>
+<option value="aichi">Aichi</option>
+<option value="mie">Mie</option>
+<option value="shiga">Shiga</option>
+<option value="kyoto">Kyoto</option>
+<option value="osaka">Osaka</option>
+<option value="hyogo">Hyogo</option>
+<option value="nara">Nara</option>
+<option value="wakayama">Wakayama</option>
+<option value="tottori">Tottori</option>
+<option value="shimane">Shimane</option>
+<option value="okayama">Okayama</option>
+<option value="hiroshima">Hiroshima</option>
+<option value="yamaguchi">Yamaguchi</option>
+<option value="tokushima">Tokushima</option>
+<option value="kagawa">Kagawa</option>
+<option value="ehime">Ehime</option>
+<option value="kochi">Kochi</option>
+<option value="fukuoka">Fukuoka</option>
+<option value="saga">Saga</option>
+<option value="nagasaki">Nagasaki</option>
+<option value="kumamoto">Kumamoto</option>
+<option value="oita">Oita</option>
+<option value="miyazaki">Miyazaki</option>
+<option value="kagoshima">Kagoshima</option>
+<option value="okinawa">Okinawa</option>
+</select>
+
+
#################################
# Tests of underlying functions #
#################################
diff --git a/tests/regressiontests/serializers_regress/models.py b/tests/regressiontests/serializers_regress/models.py
index b558050022..d3415ac1b9 100644
--- a/tests/regressiontests/serializers_regress/models.py
+++ b/tests/regressiontests/serializers_regress/models.py
@@ -6,7 +6,8 @@ This class sets up a model for each model field type
"""
from django.db import models
-
+from django.contrib.contenttypes.models import ContentType
+
# The following classes are for testing basic data
# marshalling, including NULL values.
@@ -73,6 +74,22 @@ class USStateData(models.Model):
class XMLData(models.Model):
data = models.XMLField(null=True)
+class Tag(models.Model):
+ """A tag on an item."""
+ data = models.SlugField()
+ content_type = models.ForeignKey(ContentType)
+ object_id = models.PositiveIntegerField()
+
+ content_object = models.GenericForeignKey()
+
+ class Meta:
+ ordering = ["data"]
+
+class GenericData(models.Model):
+ data = models.CharField(maxlength=30)
+
+ tags = models.GenericRelation(Tag)
+
# The following test classes are all for validation
# of related objects; in particular, forward, backward,
# and self references.
diff --git a/tests/regressiontests/serializers_regress/tests.py b/tests/regressiontests/serializers_regress/tests.py
index 008ccecc2c..97b3fbacbe 100644
--- a/tests/regressiontests/serializers_regress/tests.py
+++ b/tests/regressiontests/serializers_regress/tests.py
@@ -24,6 +24,14 @@ def data_create(pk, klass, data):
instance.data = data
instance.save()
return instance
+
+def generic_create(pk, klass, data):
+ instance = klass(id=pk)
+ instance.data = data[0]
+ instance.save()
+ for tag in data[1:]:
+ instance.tags.create(data=tag)
+ return instance
def fk_create(pk, klass, data):
instance = klass(id=pk)
@@ -56,6 +64,11 @@ def data_compare(testcase, pk, klass, data):
testcase.assertEqual(data, instance.data,
"Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data)))
+def generic_compare(testcase, pk, klass, data):
+ instance = klass.objects.get(id=pk)
+ testcase.assertEqual(data[0], instance.data)
+ testcase.assertEqual(data[1:], [t.data for t in instance.tags.all()])
+
def fk_compare(testcase, pk, klass, data):
instance = klass.objects.get(id=pk)
testcase.assertEqual(data, instance.data_id)
@@ -76,6 +89,7 @@ def pk_compare(testcase, pk, klass, data):
# actually a pair of functions; one to create
# and one to compare objects of that type
data_obj = (data_create, data_compare)
+generic_obj = (generic_create, generic_compare)
fk_obj = (fk_create, fk_compare)
m2m_obj = (m2m_create, m2m_compare)
o2o_obj = (o2o_create, o2o_compare)
@@ -140,6 +154,9 @@ The end."""),
(data_obj, 190, XMLData, "<foo></foo>"),
(data_obj, 191, XMLData, None),
+ (generic_obj, 200, GenericData, ['Generic Object 1', 'tag1', 'tag2']),
+ (generic_obj, 201, GenericData, ['Generic Object 2', 'tag2', 'tag3']),
+
(data_obj, 300, Anchor, "Anchor 1"),
(data_obj, 301, Anchor, "Anchor 2"),
@@ -222,6 +239,9 @@ def serializerTest(format, self):
transaction.commit()
transaction.leave_transaction_management()
+ # Add the generic tagged objects to the object list
+ objects.extend(Tag.objects.all())
+
# Serialize the test database
serialized_data = serializers.serialize(format, objects, indent=2)