Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #16198 -- Ported the model_forms doctests. Our long national ni…

…ghtmare is over. Oh, and we have always been at war with doctests. Thanks to Peter van Kampen and Gregor Müllegger for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16358 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit aa5506d6f69180820db8f1811b4c8780d39a5733 1 parent 4dac088
Russell Keith-Magee authored
1  AUTHORS
@@ -262,6 +262,7 @@ answer newbie questions, and generally made Django that much better:
262 262
     junzhang.jn@gmail.com
263 263
     Xia Kai <http://blog.xiaket.org/>
264 264
     Antti Kaihola <http://djangopeople.net/akaihola/>
  265
+    Peter van Kampen
265 266
     Bahadır Kandemir <bahadir@pardus.org.tr>
266 267
     Karderio <karderio@gmail.com>
267 268
     Nagy Károly <charlie@rendszergazda.com>
44  tests/modeltests/model_forms/mforms.py
... ...
@@ -1,44 +0,0 @@
1  
-from django import forms
2  
-from django.forms import ModelForm
3  
-
4  
-from models import (Product, Price, Book, DerivedBook, ExplicitPK, Post,
5  
-        DerivedPost, Writer, FlexibleDatePost)
6  
-
7  
-class ProductForm(ModelForm):
8  
-    class Meta:
9  
-        model = Product
10  
-
11  
-class PriceForm(ModelForm):
12  
-    class Meta:
13  
-        model = Price
14  
-
15  
-class BookForm(ModelForm):
16  
-    class Meta:
17  
-       model = Book
18  
-
19  
-class DerivedBookForm(ModelForm):
20  
-    class Meta:
21  
-        model = DerivedBook
22  
-
23  
-class ExplicitPKForm(ModelForm):
24  
-    class Meta:
25  
-        model = ExplicitPK
26  
-        fields = ('key', 'desc',)
27  
-
28  
-class PostForm(ModelForm):
29  
-    class Meta:
30  
-        model = Post
31  
-
32  
-class DerivedPostForm(ModelForm):
33  
-    class Meta:
34  
-        model = DerivedPost
35  
-
36  
-class CustomWriterForm(ModelForm):
37  
-   name = forms.CharField(required=False)
38  
-
39  
-   class Meta:
40  
-       model = Writer
41  
-
42  
-class FlexDatePostForm(ModelForm):
43  
-    class Meta:
44  
-        model = FlexibleDatePost
1,364  tests/modeltests/model_forms/models.py
@@ -247,1367 +247,3 @@ class FlexibleDatePost(models.Model):
247 247
     slug = models.CharField(max_length=50, unique_for_year='posted', blank=True)
248 248
     subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True)
249 249
     posted = models.DateField(blank=True, null=True)
250  
-
251  
-__test__ = {'API_TESTS': """
252  
->>> from django import forms
253  
->>> from django.forms.models import ModelForm, model_to_dict
254  
->>> from django.core.files.uploadedfile import SimpleUploadedFile
255  
-
256  
-The bare bones, absolutely nothing custom, basic case.
257  
-
258  
->>> class CategoryForm(ModelForm):
259  
-...     class Meta:
260  
-...         model = Category
261  
->>> CategoryForm.base_fields.keys()
262  
-['name', 'slug', 'url']
263  
-
264  
-
265  
-Extra fields.
266  
-
267  
->>> class CategoryForm(ModelForm):
268  
-...     some_extra_field = forms.BooleanField()
269  
-...
270  
-...     class Meta:
271  
-...         model = Category
272  
-
273  
->>> CategoryForm.base_fields.keys()
274  
-['name', 'slug', 'url', 'some_extra_field']
275  
-
276  
-Extra field that has a name collision with a related object accessor.
277  
-
278  
->>> class WriterForm(ModelForm):
279  
-...     book = forms.CharField(required=False)
280  
-...
281  
-...     class Meta:
282  
-...         model = Writer
283  
-
284  
->>> wf = WriterForm({'name': 'Richard Lockridge'})
285  
->>> wf.is_valid()
286  
-True
287  
-
288  
-Replacing a field.
289  
-
290  
->>> class CategoryForm(ModelForm):
291  
-...     url = forms.BooleanField()
292  
-...
293  
-...     class Meta:
294  
-...         model = Category
295  
-
296  
->>> CategoryForm.base_fields['url'].__class__
297  
-<class 'django.forms.fields.BooleanField'>
298  
-
299  
-
300  
-Using 'fields'.
301  
-
302  
->>> class CategoryForm(ModelForm):
303  
-...
304  
-...     class Meta:
305  
-...         model = Category
306  
-...         fields = ['url']
307  
-
308  
->>> CategoryForm.base_fields.keys()
309  
-['url']
310  
-
311  
-
312  
-Using 'exclude'
313  
-
314  
->>> class CategoryForm(ModelForm):
315  
-...
316  
-...     class Meta:
317  
-...         model = Category
318  
-...         exclude = ['url']
319  
-
320  
->>> CategoryForm.base_fields.keys()
321  
-['name', 'slug']
322  
-
323  
-
324  
-Using 'fields' *and* 'exclude'. Not sure why you'd want to do this, but uh,
325  
-"be liberal in what you accept" and all.
326  
-
327  
->>> class CategoryForm(ModelForm):
328  
-...
329  
-...     class Meta:
330  
-...         model = Category
331  
-...         fields = ['name', 'url']
332  
-...         exclude = ['url']
333  
-
334  
->>> CategoryForm.base_fields.keys()
335  
-['name']
336  
-
337  
-Using 'widgets'
338  
-
339  
->>> class CategoryForm(ModelForm):
340  
-...
341  
-...     class Meta:
342  
-...         model = Category
343  
-...         fields = ['name', 'url', 'slug']
344  
-...         widgets = {
345  
-...             'name': forms.Textarea,
346  
-...             'url': forms.TextInput(attrs={'class': 'url'})
347  
-...         }
348  
-
349  
->>> str(CategoryForm()['name'])
350  
-'<textarea id="id_name" rows="10" cols="40" name="name"></textarea>'
351  
-
352  
->>> str(CategoryForm()['url'])
353  
-'<input id="id_url" type="text" class="url" name="url" maxlength="40" />'
354  
-
355  
->>> str(CategoryForm()['slug'])
356  
-'<input id="id_slug" type="text" name="slug" maxlength="20" />'
357  
-
358  
-Don't allow more than one 'model' definition in the inheritance hierarchy.
359  
-Technically, it would generate a valid form, but the fact that the resulting
360  
-save method won't deal with multiple objects is likely to trip up people not
361  
-familiar with the mechanics.
362  
-
363  
->>> class CategoryForm(ModelForm):
364  
-...     class Meta:
365  
-...         model = Category
366  
-
367  
->>> class OddForm(CategoryForm):
368  
-...     class Meta:
369  
-...         model = Article
370  
-
371  
-OddForm is now an Article-related thing, because BadForm.Meta overrides
372  
-CategoryForm.Meta.
373  
->>> OddForm.base_fields.keys()
374  
-['headline', 'slug', 'pub_date', 'writer', 'article', 'categories', 'status']
375  
-
376  
->>> class ArticleForm(ModelForm):
377  
-...     class Meta:
378  
-...         model = Article
379  
-
380  
-First class with a Meta class wins.
381  
-
382  
->>> class BadForm(ArticleForm, CategoryForm):
383  
-...     pass
384  
->>> OddForm.base_fields.keys()
385  
-['headline', 'slug', 'pub_date', 'writer', 'article', 'categories', 'status']
386  
-
387  
-Subclassing without specifying a Meta on the class will use the parent's Meta
388  
-(or the first parent in the MRO if there are multiple parent classes).
389  
-
390  
->>> class CategoryForm(ModelForm):
391  
-...     class Meta:
392  
-...         model = Category
393  
->>> class SubCategoryForm(CategoryForm):
394  
-...     pass
395  
->>> SubCategoryForm.base_fields.keys()
396  
-['name', 'slug', 'url']
397  
-
398  
-We can also subclass the Meta inner class to change the fields list.
399  
-
400  
->>> class CategoryForm(ModelForm):
401  
-...     checkbox = forms.BooleanField()
402  
-...
403  
-...     class Meta:
404  
-...         model = Category
405  
->>> class SubCategoryForm(CategoryForm):
406  
-...     class Meta(CategoryForm.Meta):
407  
-...         exclude = ['url']
408  
-
409  
->>> print SubCategoryForm()
410  
-<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
411  
-<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr>
412  
-<tr><th><label for="id_checkbox">Checkbox:</label></th><td><input type="checkbox" name="checkbox" id="id_checkbox" /></td></tr>
413  
-
414  
-# test using fields to provide ordering to the fields
415  
->>> class CategoryForm(ModelForm):
416  
-...     class Meta:
417  
-...         model = Category
418  
-...         fields = ['url', 'name']
419  
-
420  
->>> CategoryForm.base_fields.keys()
421  
-['url', 'name']
422  
-
423  
-
424  
->>> print CategoryForm()
425  
-<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>
426  
-<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
427  
-
428  
->>> class CategoryForm(ModelForm):
429  
-...     class Meta:
430  
-...         model = Category
431  
-...         fields = ['slug', 'url', 'name']
432  
-...         exclude = ['url']
433  
-
434  
->>> CategoryForm.base_fields.keys()
435  
-['slug', 'name']
436  
-
437  
-# Old form_for_x tests #######################################################
438  
-
439  
->>> from django.forms import ModelForm, CharField
440  
->>> import datetime
441  
-
442  
->>> Category.objects.all()
443  
-[]
444  
-
445  
->>> class CategoryForm(ModelForm):
446  
-...     class Meta:
447  
-...         model = Category
448  
->>> f = CategoryForm()
449  
->>> print f
450  
-<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
451  
-<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr>
452  
-<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>
453  
->>> print f.as_ul()
454  
-<li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /></li>
455  
-<li><label for="id_slug">Slug:</label> <input id="id_slug" type="text" name="slug" maxlength="20" /></li>
456  
-<li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /></li>
457  
->>> print f['name']
458  
-<input id="id_name" type="text" name="name" maxlength="20" />
459  
-
460  
->>> f = CategoryForm(auto_id=False)
461  
->>> print f.as_ul()
462  
-<li>Name: <input type="text" name="name" maxlength="20" /></li>
463  
-<li>Slug: <input type="text" name="slug" maxlength="20" /></li>
464  
-<li>The URL: <input type="text" name="url" maxlength="40" /></li>
465  
-
466  
->>> f = CategoryForm({'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'})
467  
->>> f.is_valid()
468  
-True
469  
->>> f.cleaned_data['url']
470  
-u'entertainment'
471  
->>> f.cleaned_data['name']
472  
-u'Entertainment'
473  
->>> f.cleaned_data['slug']
474  
-u'entertainment'
475  
->>> c1 = f.save()
476  
->>> c1
477  
-<Category: Entertainment>
478  
->>> Category.objects.all()
479  
-[<Category: Entertainment>]
480  
-
481  
->>> f = CategoryForm({'name': "It's a test", 'slug': 'its-test', 'url': 'test'})
482  
->>> f.is_valid()
483  
-True
484  
->>> f.cleaned_data['url']
485  
-u'test'
486  
->>> f.cleaned_data['name']
487  
-u"It's a test"
488  
->>> f.cleaned_data['slug']
489  
-u'its-test'
490  
->>> c2 = f.save()
491  
->>> c2
492  
-<Category: It's a test>
493  
->>> Category.objects.order_by('name')
494  
-[<Category: Entertainment>, <Category: It's a test>]
495  
-
496  
-If you call save() with commit=False, then it will return an object that
497  
-hasn't yet been saved to the database. In this case, it's up to you to call
498  
-save() on the resulting model instance.
499  
->>> f = CategoryForm({'name': 'Third test', 'slug': 'third-test', 'url': 'third'})
500  
->>> f.is_valid()
501  
-True
502  
->>> f.cleaned_data['url']
503  
-u'third'
504  
->>> f.cleaned_data['name']
505  
-u'Third test'
506  
->>> f.cleaned_data['slug']
507  
-u'third-test'
508  
->>> c3 = f.save(commit=False)
509  
->>> c3
510  
-<Category: Third test>
511  
->>> Category.objects.order_by('name')
512  
-[<Category: Entertainment>, <Category: It's a test>]
513  
->>> c3.save()
514  
->>> Category.objects.order_by('name')
515  
-[<Category: Entertainment>, <Category: It's a test>, <Category: Third test>]
516  
-
517  
-If you call save() with invalid data, you'll get a ValueError.
518  
->>> f = CategoryForm({'name': '', 'slug': 'not a slug!', 'url': 'foo'})
519  
->>> f.errors['name']
520  
-[u'This field is required.']
521  
->>> f.errors['slug']
522  
-[u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."]
523  
->>> f.cleaned_data
524  
-Traceback (most recent call last):
525  
-...
526  
-AttributeError: 'CategoryForm' object has no attribute 'cleaned_data'
527  
->>> f.save()
528  
-Traceback (most recent call last):
529  
-...
530  
-ValueError: The Category could not be created because the data didn't validate.
531  
->>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'})
532  
->>> f.save()
533  
-Traceback (most recent call last):
534  
-...
535  
-ValueError: The Category could not be created because the data didn't validate.
536  
-
537  
-Create a couple of Writers.
538  
->>> w_royko = Writer(name='Mike Royko')
539  
->>> w_royko.save()
540  
->>> w_woodward = Writer(name='Bob Woodward')
541  
->>> w_woodward.save()
542  
-
543  
-ManyToManyFields are represented by a MultipleChoiceField, ForeignKeys and any
544  
-fields with the 'choices' attribute are represented by a ChoiceField.
545  
->>> class ArticleForm(ModelForm):
546  
-...     class Meta:
547  
-...         model = Article
548  
->>> f = ArticleForm(auto_id=False)
549  
->>> print f
550  
-<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
551  
-<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr>
552  
-<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
553  
-<tr><th>Writer:</th><td><select name="writer">
554  
-<option value="" selected="selected">---------</option>
555  
-<option value="...">Bob Woodward</option>
556  
-<option value="...">Mike Royko</option>
557  
-</select></td></tr>
558  
-<tr><th>Article:</th><td><textarea rows="10" cols="40" name="article"></textarea></td></tr>
559  
-<tr><th>Categories:</th><td><select multiple="multiple" name="categories">
560  
-<option value="...">Entertainment</option>
561  
-<option value="...">It&#39;s a test</option>
562  
-<option value="...">Third test</option>
563  
-</select><br /><span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></td></tr>
564  
-<tr><th>Status:</th><td><select name="status">
565  
-<option value="" selected="selected">---------</option>
566  
-<option value="1">Draft</option>
567  
-<option value="2">Pending</option>
568  
-<option value="3">Live</option>
569  
-</select></td></tr>
570  
-
571  
-You can restrict a form to a subset of the complete list of fields
572  
-by providing a 'fields' argument. If you try to save a
573  
-model created with such a form, you need to ensure that the fields
574  
-that are _not_ on the form have default values, or are allowed to have
575  
-a value of None. If a field isn't specified on a form, the object created
576  
-from the form can't provide a value for that field!
577  
->>> class PartialArticleForm(ModelForm):
578  
-...     class Meta:
579  
-...         model = Article
580  
-...         fields = ('headline','pub_date')
581  
->>> f = PartialArticleForm(auto_id=False)
582  
->>> print f
583  
-<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
584  
-<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
585  
-
586  
-When the ModelForm is passed an instance, that instance's current values are
587  
-inserted as 'initial' data in each Field.
588  
->>> w = Writer.objects.get(name='Mike Royko')
589  
->>> class RoykoForm(ModelForm):
590  
-...     class Meta:
591  
-...         model = Writer
592  
->>> f = RoykoForm(auto_id=False, instance=w)
593  
->>> print f
594  
-<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br /><span class="helptext">Use both first and last names.</span></td></tr>
595  
-
596  
->>> art = Article(headline='Test article', slug='test-article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.')
597  
->>> art.save()
598  
->>> art_id_1 = art.id
599  
->>> art_id_1 is not None
600  
-True
601  
->>> class TestArticleForm(ModelForm):
602  
-...     class Meta:
603  
-...         model = Article
604  
->>> f = TestArticleForm(auto_id=False, instance=art)
605  
->>> print f.as_ul()
606  
-<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
607  
-<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li>
608  
-<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
609  
-<li>Writer: <select name="writer">
610  
-<option value="">---------</option>
611  
-<option value="...">Bob Woodward</option>
612  
-<option value="..." selected="selected">Mike Royko</option>
613  
-</select></li>
614  
-<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
615  
-<li>Categories: <select multiple="multiple" name="categories">
616  
-<option value="...">Entertainment</option>
617  
-<option value="...">It&#39;s a test</option>
618  
-<option value="...">Third test</option>
619  
-</select> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></li>
620  
-<li>Status: <select name="status">
621  
-<option value="" selected="selected">---------</option>
622  
-<option value="1">Draft</option>
623  
-<option value="2">Pending</option>
624  
-<option value="3">Live</option>
625  
-</select></li>
626  
->>> f = TestArticleForm({'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': unicode(w_royko.pk), 'article': 'Hello.'}, instance=art)
627  
->>> f.errors
628  
-{}
629  
->>> f.is_valid()
630  
-True
631  
->>> test_art = f.save()
632  
->>> test_art.id == art_id_1
633  
-True
634  
->>> test_art = Article.objects.get(id=art_id_1)
635  
->>> test_art.headline
636  
-u'Test headline'
637  
-
638  
-You can create a form over a subset of the available fields
639  
-by specifying a 'fields' argument to form_for_instance.
640  
->>> class PartialArticleForm(ModelForm):
641  
-...     class Meta:
642  
-...         model = Article
643  
-...         fields=('headline', 'slug', 'pub_date')
644  
->>> f = PartialArticleForm({'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False, instance=art)
645  
->>> print f.as_ul()
646  
-<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
647  
-<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
648  
-<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
649  
->>> f.is_valid()
650  
-True
651  
->>> new_art = f.save()
652  
->>> new_art.id == art_id_1
653  
-True
654  
->>> new_art = Article.objects.get(id=art_id_1)
655  
->>> new_art.headline
656  
-u'New headline'
657  
-
658  
-Add some categories and test the many-to-many form output.
659  
->>> new_art.categories.all()
660  
-[]
661  
->>> new_art.categories.add(Category.objects.get(name='Entertainment'))
662  
->>> new_art.categories.all()
663  
-[<Category: Entertainment>]
664  
->>> class TestArticleForm(ModelForm):
665  
-...     class Meta:
666  
-...         model = Article
667  
->>> f = TestArticleForm(auto_id=False, instance=new_art)
668  
->>> print f.as_ul()
669  
-<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
670  
-<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
671  
-<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
672  
-<li>Writer: <select name="writer">
673  
-<option value="">---------</option>
674  
-<option value="...">Bob Woodward</option>
675  
-<option value="..." selected="selected">Mike Royko</option>
676  
-</select></li>
677  
-<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
678  
-<li>Categories: <select multiple="multiple" name="categories">
679  
-<option value="..." selected="selected">Entertainment</option>
680  
-<option value="...">It&#39;s a test</option>
681  
-<option value="...">Third test</option>
682  
-</select> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></li>
683  
-<li>Status: <select name="status">
684  
-<option value="" selected="selected">---------</option>
685  
-<option value="1">Draft</option>
686  
-<option value="2">Pending</option>
687  
-<option value="3">Live</option>
688  
-</select></li>
689  
-
690  
-Initial values can be provided for model forms
691  
->>> f = TestArticleForm(auto_id=False, initial={'headline': 'Your headline here', 'categories': [str(c1.id), str(c2.id)]})
692  
->>> print f.as_ul()
693  
-<li>Headline: <input type="text" name="headline" value="Your headline here" maxlength="50" /></li>
694  
-<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
695  
-<li>Pub date: <input type="text" name="pub_date" /></li>
696  
-<li>Writer: <select name="writer">
697  
-<option value="" selected="selected">---------</option>
698  
-<option value="...">Bob Woodward</option>
699  
-<option value="...">Mike Royko</option>
700  
-</select></li>
701  
-<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
702  
-<li>Categories: <select multiple="multiple" name="categories">
703  
-<option value="..." selected="selected">Entertainment</option>
704  
-<option value="..." selected="selected">It&#39;s a test</option>
705  
-<option value="...">Third test</option>
706  
-</select> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></li>
707  
-<li>Status: <select name="status">
708  
-<option value="" selected="selected">---------</option>
709  
-<option value="1">Draft</option>
710  
-<option value="2">Pending</option>
711  
-<option value="3">Live</option>
712  
-</select></li>
713  
-
714  
->>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
715  
-...     'writer': unicode(w_royko.pk), 'article': u'Hello.', 'categories': [unicode(c1.id), unicode(c2.id)]}, instance=new_art)
716  
->>> new_art = f.save()
717  
->>> new_art.id == art_id_1
718  
-True
719  
->>> new_art = Article.objects.get(id=art_id_1)
720  
->>> new_art.categories.order_by('name')
721  
-[<Category: Entertainment>, <Category: It's a test>]
722  
-
723  
-Now, submit form data with no categories. This deletes the existing categories.
724  
->>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
725  
-...     'writer': unicode(w_royko.pk), 'article': u'Hello.'}, instance=new_art)
726  
->>> new_art = f.save()
727  
->>> new_art.id == art_id_1
728  
-True
729  
->>> new_art = Article.objects.get(id=art_id_1)
730  
->>> new_art.categories.all()
731  
-[]
732  
-
733  
-Create a new article, with categories, via the form.
734  
->>> class ArticleForm(ModelForm):
735  
-...     class Meta:
736  
-...         model = Article
737  
->>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
738  
-...     'writer': unicode(w_royko.pk), 'article': u'Test.', 'categories': [unicode(c1.id), unicode(c2.id)]})
739  
->>> new_art = f.save()
740  
->>> art_id_2 = new_art.id
741  
->>> art_id_2 not in (None, art_id_1)
742  
-True
743  
->>> new_art = Article.objects.get(id=art_id_2)
744  
->>> new_art.categories.order_by('name')
745  
-[<Category: Entertainment>, <Category: It's a test>]
746  
-
747  
-Create a new article, with no categories, via the form.
748  
->>> class ArticleForm(ModelForm):
749  
-...     class Meta:
750  
-...         model = Article
751  
->>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
752  
-...     'writer': unicode(w_royko.pk), 'article': u'Test.'})
753  
->>> new_art = f.save()
754  
->>> art_id_3 = new_art.id
755  
->>> art_id_3 not in (None, art_id_1, art_id_2)
756  
-True
757  
->>> new_art = Article.objects.get(id=art_id_3)
758  
->>> new_art.categories.all()
759  
-[]
760  
-
761  
-Create a new article, with categories, via the form, but use commit=False.
762  
-The m2m data won't be saved until save_m2m() is invoked on the form.
763  
->>> class ArticleForm(ModelForm):
764  
-...     class Meta:
765  
-...         model = Article
766  
->>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01',
767  
-...     'writer': unicode(w_royko.pk), 'article': u'Test.', 'categories': [unicode(c1.id), unicode(c2.id)]})
768  
->>> new_art = f.save(commit=False)
769  
-
770  
-# Manually save the instance
771  
->>> new_art.save()
772  
->>> art_id_4 = new_art.id
773  
->>> art_id_4 not in (None, art_id_1, art_id_2, art_id_3)
774  
-True
775  
-
776  
-# The instance doesn't have m2m data yet
777  
->>> new_art = Article.objects.get(id=art_id_4)
778  
->>> new_art.categories.all()
779  
-[]
780  
-
781  
-# Save the m2m data on the form
782  
->>> f.save_m2m()
783  
->>> new_art.categories.order_by('name')
784  
-[<Category: Entertainment>, <Category: It's a test>]
785  
-
786  
-Here, we define a custom ModelForm. Because it happens to have the same fields as
787  
-the Category model, we can just call the form's save() to apply its changes to an
788  
-existing Category instance.
789  
->>> class ShortCategory(ModelForm):
790  
-...     name = CharField(max_length=5)
791  
-...     slug = CharField(max_length=5)
792  
-...     url = CharField(max_length=3)
793  
->>> cat = Category.objects.get(name='Third test')
794  
->>> cat
795  
-<Category: Third test>
796  
->>> cat.id == c3.id
797  
-True
798  
->>> form = ShortCategory({'name': 'Third', 'slug': 'third', 'url': '3rd'}, instance=cat)
799  
->>> form.save()
800  
-<Category: Third>
801  
->>> Category.objects.get(id=c3.id)
802  
-<Category: Third>
803  
-
804  
-Here, we demonstrate that choices for a ForeignKey ChoiceField are determined
805  
-at runtime, based on the data in the database when the form is displayed, not
806  
-the data in the database when the form is instantiated.
807  
->>> class ArticleForm(ModelForm):
808  
-...     class Meta:
809  
-...         model = Article
810  
->>> f = ArticleForm(auto_id=False)
811  
->>> print f.as_ul()
812  
-<li>Headline: <input type="text" name="headline" maxlength="50" /></li>
813  
-<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
814  
-<li>Pub date: <input type="text" name="pub_date" /></li>
815  
-<li>Writer: <select name="writer">
816  
-<option value="" selected="selected">---------</option>
817  
-<option value="...">Bob Woodward</option>
818  
-<option value="...">Mike Royko</option>
819  
-</select></li>
820  
-<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
821  
-<li>Categories: <select multiple="multiple" name="categories">
822  
-<option value="...">Entertainment</option>
823  
-<option value="...">It&#39;s a test</option>
824  
-<option value="...">Third</option>
825  
-</select> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></li>
826  
-<li>Status: <select name="status">
827  
-<option value="" selected="selected">---------</option>
828  
-<option value="1">Draft</option>
829  
-<option value="2">Pending</option>
830  
-<option value="3">Live</option>
831  
-</select></li>
832  
->>> c4 = Category.objects.create(name='Fourth', url='4th')
833  
->>> c4
834  
-<Category: Fourth>
835  
->>> Writer.objects.create(name='Carl Bernstein')
836  
-<Writer: Carl Bernstein>
837  
->>> print f.as_ul()
838  
-<li>Headline: <input type="text" name="headline" maxlength="50" /></li>
839  
-<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
840  
-<li>Pub date: <input type="text" name="pub_date" /></li>
841  
-<li>Writer: <select name="writer">
842  
-<option value="" selected="selected">---------</option>
843  
-<option value="...">Bob Woodward</option>
844  
-<option value="...">Carl Bernstein</option>
845  
-<option value="...">Mike Royko</option>
846  
-</select></li>
847  
-<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
848  
-<li>Categories: <select multiple="multiple" name="categories">
849  
-<option value="...">Entertainment</option>
850  
-<option value="...">It&#39;s a test</option>
851  
-<option value="...">Third</option>
852  
-<option value="...">Fourth</option>
853  
-</select> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></li>
854  
-<li>Status: <select name="status">
855  
-<option value="" selected="selected">---------</option>
856  
-<option value="1">Draft</option>
857  
-<option value="2">Pending</option>
858  
-<option value="3">Live</option>
859  
-</select></li>
860  
-
861  
-# ModelChoiceField ############################################################
862  
-
863  
->>> from django.forms import ModelChoiceField, ModelMultipleChoiceField
864  
-
865  
->>> f = ModelChoiceField(Category.objects.all())
866  
->>> list(f.choices)
867  
-[(u'', u'---------'), (..., u'Entertainment'), (..., u"It's a test"), (..., u'Third'), (..., u'Fourth')]
868  
->>> f.clean('')
869  
-Traceback (most recent call last):
870  
-...
871  
-ValidationError: [u'This field is required.']
872  
->>> f.clean(None)
873  
-Traceback (most recent call last):
874  
-...
875  
-ValidationError: [u'This field is required.']
876  
->>> f.clean(0)
877  
-Traceback (most recent call last):
878  
-...
879  
-ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
880  
->>> f.clean(c3.id)
881  
-<Category: Third>
882  
->>> f.clean(c2.id)
883  
-<Category: It's a test>
884  
-
885  
-# Add a Category object *after* the ModelChoiceField has already been
886  
-# instantiated. This proves clean() checks the database during clean() rather
887  
-# than caching it at time of instantiation.
888  
->>> c5 = Category.objects.create(name='Fifth', url='5th')
889  
->>> c5
890  
-<Category: Fifth>
891  
->>> f.clean(c5.id)
892  
-<Category: Fifth>
893  
-
894  
-# Delete a Category object *after* the ModelChoiceField has already been
895  
-# instantiated. This proves clean() checks the database during clean() rather
896  
-# than caching it at time of instantiation.
897  
->>> Category.objects.get(url='5th').delete()
898  
->>> f.clean(c5.id)
899  
-Traceback (most recent call last):
900  
-...
901  
-ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
902  
-
903  
->>> f = ModelChoiceField(Category.objects.filter(pk=c1.id), required=False)
904  
->>> print f.clean('')
905  
-None
906  
->>> f.clean('')
907  
->>> f.clean(str(c1.id))
908  
-<Category: Entertainment>
909  
->>> f.clean('100')
910  
-Traceback (most recent call last):
911  
-...
912  
-ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
913  
-
914  
-# queryset can be changed after the field is created.
915  
->>> f.queryset = Category.objects.exclude(name='Fourth')
916  
->>> list(f.choices)
917  
-[(u'', u'---------'), (..., u'Entertainment'), (..., u"It's a test"), (..., u'Third')]
918  
->>> f.clean(c3.id)
919  
-<Category: Third>
920  
->>> f.clean(c4.id)
921  
-Traceback (most recent call last):
922  
-...
923  
-ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
924  
-
925  
-# check that we can safely iterate choices repeatedly
926  
->>> gen_one = list(f.choices)
927  
->>> gen_two = f.choices
928  
->>> gen_one[2]
929  
-(..., u"It's a test")
930  
->>> list(gen_two)
931  
-[(u'', u'---------'), (..., u'Entertainment'), (..., u"It's a test"), (..., u'Third')]
932  
-
933  
-# check that we can override the label_from_instance method to print custom labels (#4620)
934  
->>> f.queryset = Category.objects.all()
935  
->>> f.label_from_instance = lambda obj: "category " + str(obj)
936  
->>> list(f.choices)
937  
-[(u'', u'---------'), (..., 'category Entertainment'), (..., "category It's a test"), (..., 'category Third'), (..., 'category Fourth')]
938  
-
939  
-# ModelMultipleChoiceField ####################################################
940  
-
941  
->>> f = ModelMultipleChoiceField(Category.objects.all())
942  
->>> list(f.choices)
943  
-[(..., u'Entertainment'), (..., u"It's a test"), (..., u'Third'), (..., u'Fourth')]
944  
->>> f.clean(None)
945  
-Traceback (most recent call last):
946  
-...
947  
-ValidationError: [u'This field is required.']
948  
->>> f.clean([])
949  
-Traceback (most recent call last):
950  
-...
951  
-ValidationError: [u'This field is required.']
952  
->>> f.clean([c1.id])
953  
-[<Category: Entertainment>]
954  
->>> f.clean([c2.id])
955  
-[<Category: It's a test>]
956  
->>> f.clean([str(c1.id)])
957  
-[<Category: Entertainment>]
958  
->>> f.clean([str(c1.id), str(c2.id)])
959  
-[<Category: Entertainment>, <Category: It's a test>]
960  
->>> f.clean([c1.id, str(c2.id)])
961  
-[<Category: Entertainment>, <Category: It's a test>]
962  
->>> f.clean((c1.id, str(c2.id)))
963  
-[<Category: Entertainment>, <Category: It's a test>]
964  
->>> f.clean(['100'])
965  
-Traceback (most recent call last):
966  
-...
967  
-ValidationError: [u'Select a valid choice. 100 is not one of the available choices.']
968  
->>> f.clean('hello')
969  
-Traceback (most recent call last):
970  
-...
971  
-ValidationError: [u'Enter a list of values.']
972  
->>> f.clean(['fail'])
973  
-Traceback (most recent call last):
974  
-...
975  
-ValidationError: [u'"fail" is not a valid value for a primary key.']
976  
-
977  
-# Add a Category object *after* the ModelMultipleChoiceField has already been
978  
-# instantiated. This proves clean() checks the database during clean() rather
979  
-# than caching it at time of instantiation.
980  
->>> c6 = Category.objects.create(id=6, name='Sixth', url='6th')
981  
->>> c6
982  
-<Category: Sixth>
983  
->>> f.clean([c6.id])
984  
-[<Category: Sixth>]
985  
-
986  
-# Delete a Category object *after* the ModelMultipleChoiceField has already been
987  
-# instantiated. This proves clean() checks the database during clean() rather
988  
-# than caching it at time of instantiation.
989  
->>> Category.objects.get(url='6th').delete()
990  
->>> f.clean([c6.id])
991  
-Traceback (most recent call last):
992  
-...
993  
-ValidationError: [u'Select a valid choice. 6 is not one of the available choices.']
994  
-
995  
->>> f = ModelMultipleChoiceField(Category.objects.all(), required=False)
996  
->>> f.clean([])
997  
-[]
998  
->>> f.clean(())
999  
-[]
1000  
->>> f.clean(['10'])
1001  
-Traceback (most recent call last):
1002  
-...
1003  
-ValidationError: [u'Select a valid choice. 10 is not one of the available choices.']
1004  
->>> f.clean([str(c3.id), '10'])
1005  
-Traceback (most recent call last):
1006  
-...
1007  
-ValidationError: [u'Select a valid choice. 10 is not one of the available choices.']
1008  
->>> f.clean([str(c1.id), '10'])
1009  
-Traceback (most recent call last):
1010  
-...
1011  
-ValidationError: [u'Select a valid choice. 10 is not one of the available choices.']
1012  
-
1013  
-# queryset can be changed after the field is created.
1014  
->>> f.queryset = Category.objects.exclude(name='Fourth')
1015  
->>> list(f.choices)
1016  
-[(..., u'Entertainment'), (..., u"It's a test"), (..., u'Third')]
1017  
->>> f.clean([c3.id])
1018  
-[<Category: Third>]
1019  
->>> f.clean([c4.id])
1020  
-Traceback (most recent call last):
1021  
-...
1022  
-ValidationError: [u'Select a valid choice. ... is not one of the available choices.']
1023  
->>> f.clean([str(c3.id), str(c4.id)])
1024  
-Traceback (most recent call last):
1025  
-...
1026  
-ValidationError: [u'Select a valid choice. ... is not one of the available choices.']
1027  
-
1028  
->>> f.queryset = Category.objects.all()
1029  
->>> f.label_from_instance = lambda obj: "multicategory " + str(obj)
1030  
->>> list(f.choices)
1031  
-[(..., 'multicategory Entertainment'), (..., "multicategory It's a test"), (..., 'multicategory Third'), (..., 'multicategory Fourth')]
1032  
-
1033  
-# OneToOneField ###############################################################
1034  
-
1035  
->>> class ImprovedArticleForm(ModelForm):
1036  
-...     class Meta:
1037  
-...         model = ImprovedArticle
1038  
->>> ImprovedArticleForm.base_fields.keys()
1039  
-['article']
1040  
-
1041  
->>> class ImprovedArticleWithParentLinkForm(ModelForm):
1042  
-...     class Meta:
1043  
-...         model = ImprovedArticleWithParentLink
1044  
->>> ImprovedArticleWithParentLinkForm.base_fields.keys()
1045  
-[]
1046  
-
1047  
->>> bw = BetterWriter(name=u'Joe Better', score=10)
1048  
->>> bw.save()
1049  
->>> sorted(model_to_dict(bw).keys())
1050  
-['id', 'name', 'score', 'writer_ptr']
1051  
-
1052  
->>> class BetterWriterForm(ModelForm):
1053  
-...     class Meta:
1054  
-...         model = BetterWriter
1055  
->>> form = BetterWriterForm({'name': 'Some Name', 'score': 12})
1056  
->>> form.is_valid()
1057  
-True
1058  
->>> bw2 = form.save()
1059  
->>> bw2.delete()
1060  
-
1061  
-
1062  
->>> class WriterProfileForm(ModelForm):
1063  
-...     class Meta:
1064  
-...         model = WriterProfile
1065  
->>> form = WriterProfileForm()
1066  
->>> print form.as_p()
1067  
-<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer">
1068  
-<option value="" selected="selected">---------</option>
1069  
-<option value="...">Bob Woodward</option>
1070  
-<option value="...">Carl Bernstein</option>
1071  
-<option value="...">Joe Better</option>
1072  
-<option value="...">Mike Royko</option>
1073  
-</select></p>
1074  
-<p><label for="id_age">Age:</label> <input type="text" name="age" id="id_age" /></p>
1075  
-
1076  
->>> data = {
1077  
-...     'writer': unicode(w_woodward.pk),
1078  
-...     'age': u'65',
1079  
-... }
1080  
->>> form = WriterProfileForm(data)
1081  
->>> instance = form.save()
1082  
->>> instance
1083  
-<WriterProfile: Bob Woodward is 65>
1084  
-
1085  
->>> form = WriterProfileForm(instance=instance)
1086  
->>> print form.as_p()
1087  
-<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer">
1088  
-<option value="">---------</option>
1089  
-<option value="..." selected="selected">Bob Woodward</option>
1090  
-<option value="...">Carl Bernstein</option>
1091  
-<option value="...">Joe Better</option>
1092  
-<option value="...">Mike Royko</option>
1093  
-</select></p>
1094  
-<p><label for="id_age">Age:</label> <input type="text" name="age" value="65" id="id_age" /></p>
1095  
-
1096  
-# PhoneNumberField ############################################################
1097  
-
1098  
->>> class PhoneNumberForm(ModelForm):
1099  
-...     class Meta:
1100  
-...         model = PhoneNumber
1101  
->>> f = PhoneNumberForm({'phone': '(312) 555-1212', 'description': 'Assistance'})
1102  
->>> f.is_valid()
1103  
-True
1104  
->>> f.cleaned_data['phone']
1105  
-u'312-555-1212'
1106  
->>> f.cleaned_data['description']
1107  
-u'Assistance'
1108  
-
1109  
-# FileField ###################################################################
1110  
-
1111  
-# File forms.
1112  
-
1113  
->>> class TextFileForm(ModelForm):
1114  
-...     class Meta:
1115  
-...         model = TextFile
1116  
-
1117  
-# Test conditions when files is either not given or empty.
1118  
-
1119  
->>> f = TextFileForm(data={'description': u'Assistance'})
1120  
->>> f.is_valid()
1121  
-False
1122  
->>> f = TextFileForm(data={'description': u'Assistance'}, files={})
1123  
->>> f.is_valid()
1124  
-False
1125  
-
1126  
-# Upload a file and ensure it all works as expected.
1127  
-
1128  
->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test1.txt', 'hello world')})
1129  
->>> f.is_valid()
1130  
-True
1131  
->>> type(f.cleaned_data['file'])
1132  
-<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
1133  
->>> instance = f.save()
1134  
->>> instance.file
1135  
-<FieldFile: tests/test1.txt>
1136  
-
1137  
->>> instance.file.delete()
1138  
-
1139  
->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test1.txt', 'hello world')})
1140  
->>> f.is_valid()
1141  
-True
1142  
->>> type(f.cleaned_data['file'])
1143  
-<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
1144  
->>> instance = f.save()
1145  
->>> instance.file
1146  
-<FieldFile: tests/test1.txt>
1147  
-
1148  
-# Check if the max_length attribute has been inherited from the model.
1149  
->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test-maxlength.txt', 'hello world')})
1150  
->>> f.is_valid()
1151  
-False
1152  
-
1153  
-# Edit an instance that already has the file defined in the model. This will not
1154  
-# save the file again, but leave it exactly as it is.
1155  
-
1156  
->>> f = TextFileForm(data={'description': u'Assistance'}, instance=instance)
1157  
->>> f.is_valid()
1158  
-True
1159  
->>> f.cleaned_data['file']
1160  
-<FieldFile: tests/test1.txt>
1161  
->>> instance = f.save()
1162  
->>> instance.file
1163  
-<FieldFile: tests/test1.txt>
1164  
-
1165  
-# Delete the current file since this is not done by Django.
1166  
->>> instance.file.delete()
1167  
-
1168  
-# Override the file by uploading a new one.
1169  
-
1170  
->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test2.txt', 'hello world')}, instance=instance)
1171  
->>> f.is_valid()
1172  
-True
1173  
->>> instance = f.save()
1174  
->>> instance.file
1175  
-<FieldFile: tests/test2.txt>
1176  
-
1177  
-# Delete the current file since this is not done by Django.
1178  
->>> instance.file.delete()
1179  
-
1180  
->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test2.txt', 'hello world')})
1181  
->>> f.is_valid()
1182  
-True
1183  
->>> instance = f.save()
1184  
->>> instance.file
1185  
-<FieldFile: tests/test2.txt>
1186  
-
1187  
-# Delete the current file since this is not done by Django.
1188  
->>> instance.file.delete()
1189  
-
1190  
->>> instance.delete()
1191  
-
1192  
-# Test the non-required FileField
1193  
->>> f = TextFileForm(data={'description': u'Assistance'})
1194  
->>> f.fields['file'].required = False
1195  
->>> f.is_valid()
1196  
-True
1197  
->>> instance = f.save()
1198  
->>> instance.file
1199  
-<FieldFile: None>
1200  
-
1201  
->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')}, instance=instance)
1202  
->>> f.is_valid()
1203  
-True
1204  
->>> instance = f.save()
1205  
->>> instance.file
1206  
-<FieldFile: tests/test3.txt>
1207  
-
1208  
-# Instance can be edited w/out re-uploading the file and existing file should be preserved.
1209  
-
1210  
->>> f = TextFileForm(data={'description': u'New Description'}, instance=instance)
1211  
->>> f.fields['file'].required = False
1212  
->>> f.is_valid()
1213  
-True
1214  
->>> instance = f.save()
1215  
->>> instance.description
1216  
-u'New Description'
1217  
->>> instance.file
1218  
-<FieldFile: tests/test3.txt>
1219  
-
1220  
-# Delete the current file since this is not done by Django.
1221  
->>> instance.file.delete()
1222  
->>> instance.delete()
1223  
-
1224  
->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')})
1225  
->>> f.is_valid()
1226  
-True
1227  
->>> instance = f.save()
1228  
->>> instance.file
1229  
-<FieldFile: tests/test3.txt>
1230  
-
1231  
-# Delete the current file since this is not done by Django.
1232  
->>> instance.file.delete()
1233  
->>> instance.delete()
1234  
-
1235  
-# BigIntegerField ################################################################
1236  
->>> class BigIntForm(forms.ModelForm):
1237  
-...     class Meta:
1238  
-...         model = BigInt
1239  
-...
1240  
->>> bif = BigIntForm({'biggie': '-9223372036854775808'})
1241  
->>> bif.is_valid()
1242  
-True
1243  
->>> bif = BigIntForm({'biggie': '-9223372036854775809'})
1244  
->>> bif.is_valid()
1245  
-False
1246  
->>> bif.errors
1247  
-{'biggie': [u'Ensure this value is greater than or equal to -9223372036854775808.']}
1248  
->>> bif = BigIntForm({'biggie': '9223372036854775807'})
1249  
->>> bif.is_valid()
1250  
-True
1251  
->>> bif = BigIntForm({'biggie': '9223372036854775808'})
1252  
->>> bif.is_valid()
1253  
-False
1254  
->>> bif.errors
1255  
-{'biggie': [u'Ensure this value is less than or equal to 9223372036854775807.']}
1256  
-"""}
1257  
-
1258  
-if test_images:
1259  
-    __test__['API_TESTS'] += """
1260  
-# ImageField ###################################################################
1261  
-
1262  
-# ImageField and FileField are nearly identical, but they differ slighty when
1263  
-# it comes to validation. This specifically tests that #6302 is fixed for
1264  
-# both file fields and image fields.
1265  
-
1266  
->>> class ImageFileForm(ModelForm):
1267  
-...     class Meta:
1268  
-...         model = ImageFile
1269  
-
1270  
->>> image_data = open(os.path.join(os.path.dirname(__file__), "test.png"), 'rb').read()
1271  
->>> image_data2 = open(os.path.join(os.path.dirname(__file__), "test2.png"), 'rb').read()
1272  
-
1273  
->>> f = ImageFileForm(data={'description': u'An image'}, files={'image': SimpleUploadedFile('test.png', image_data)})
1274  
->>> f.is_valid()
1275  
-True
1276  
->>> type(f.cleaned_data['image'])
1277  
-<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
1278  
->>> instance = f.save()
1279  
->>> instance.image
1280  
-<...FieldFile: tests/test.png>
1281  
->>> instance.width
1282  
-16
1283  
->>> instance.height
1284  
-16
1285  
-
1286  
-# Delete the current file since this is not done by Django, but don't save
1287  
-# because the dimension fields are not null=True.
1288  
->>> instance.image.delete(save=False)
1289  
-
1290  
->>> f = ImageFileForm(data={'description': u'An image'}, files={'image': SimpleUploadedFile('test.png', image_data)})
1291  
->>> f.is_valid()
1292  
-True
1293  
->>> type(f.cleaned_data['image'])
1294  
-<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
1295  
->>> instance = f.save()
1296  
->>> instance.image
1297  
-<...FieldFile: tests/test.png>
1298  
->>> instance.width
1299  
-16
1300  
->>> instance.height
1301  
-16
1302