diff options
| author | Adrian Holovaty <adrian@holovaty.com> | 2007-03-25 21:49:00 +0000 |
|---|---|---|
| committer | Adrian Holovaty <adrian@holovaty.com> | 2007-03-25 21:49:00 +0000 |
| commit | 132cf258cbdce8bac1d7a3d713c3927f43ead1ed (patch) | |
| tree | 2ce01dc4a7dd0374e085f706379d181e0b286507 /tests | |
| parent | 25c15b17a86fa95b5374b9ef6366450b28a28b7a (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')
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'Or</option> +<option value="22">22 - Cotes-d'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'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) |
