mirror of
https://github.com/django/django.git
synced 2025-10-11 15:59:11 +00:00
http://code.djangoproject.com/svn/django/trunk ........ r5626 | russellm | 2007-07-07 10:16:23 +0800 (Sat, 07 Jul 2007) | 2 lines Added some uncredited authors that worked on the Oracle branch. ........ r5629 | mtredinnick | 2007-07-08 01:15:54 +0800 (Sun, 08 Jul 2007) | 8 lines Changed HttpRequest.path to be a Unicode object. It has already been URL-decoded by the time we see it anyway, so keeping it as a UTF-8 bytestring was causing unnecessary problems. Also added handling for non-ASCII URL fragments in feed creation (the portion that was outside the control of the Feed class was messed up). ........ r5630 | mtredinnick | 2007-07-08 02:24:27 +0800 (Sun, 08 Jul 2007) | 4 lines Fixed #4772 -- Fixed reverse URL creation to work with non-ASCII arguments. Also included a test for non-ASCII strings in URL patterns, although that already worked correctly. ........ r5631 | mtredinnick | 2007-07-08 02:39:23 +0800 (Sun, 08 Jul 2007) | 3 lines Corrected misleading comment from [5619]. Not sure what I was smoking at the time. ........ r5632 | mtredinnick | 2007-07-08 08:39:32 +0800 (Sun, 08 Jul 2007) | 5 lines Fixed reverse URL lookup using functions when the original URL pattern was a string. This is now just as fragile as it was prior to [5609], but works in a few cases that people were relying on, apparently. ........ r5636 | mtredinnick | 2007-07-08 19:22:53 +0800 (Sun, 08 Jul 2007) | 4 lines Fixed #4798-- Made sure that function keyword arguments are strings (for the keywords themselves) when using Unicode URL patterns. ........ r5638 | gwilson | 2007-07-10 10:34:42 +0800 (Tue, 10 Jul 2007) | 2 lines Fixed #4817 -- Removed leading forward slashes from some urlconf examples in the documentation. ........ r5639 | gwilson | 2007-07-10 10:45:11 +0800 (Tue, 10 Jul 2007) | 2 lines Fixed #4814 -- Fixed some whitespace issues in tutorial01, thanks John Shaffer. ........ r5640 | gwilson | 2007-07-10 11:26:26 +0800 (Tue, 10 Jul 2007) | 2 lines Fixed #4812 -- Fixed an octal escape in regular expression that is used in the `isValidEmail` validator, thanks batchman@free.fr. ........ r5641 | mtredinnick | 2007-07-10 20:02:06 +0800 (Tue, 10 Jul 2007) | 3 lines Fixed #4823 -- Fixed a Python 2.3 incompatibility from [5636] (it was even demonstrated by existing tests, so I really screwed this up). ........ r5642 | mtredinnick | 2007-07-10 20:03:36 +0800 (Tue, 10 Jul 2007) | 3 lines Fixed #4804 -- Fixed a problem when validating choice lists with non-ASCII data. Thanks, django@vonposer.de. ........ r5643 | mtredinnick | 2007-07-10 20:33:55 +0800 (Tue, 10 Jul 2007) | 4 lines Fixed #3760 -- Added the ability to manually set feed- and item-level id elements in Atom feeds. This is fully backwards compatible. Based on a patch from spark343@cs.ubc.ca. ........ r5644 | mtredinnick | 2007-07-11 14:55:12 +0800 (Wed, 11 Jul 2007) | 3 lines Fixed #4815 -- Fixed decoding of request parameters when the input encoding is not UTF-8. Thanks, Jordan Dimov. ........ r5645 | mtredinnick | 2007-07-11 15:00:27 +0800 (Wed, 11 Jul 2007) | 3 lines Fixed #4802 -- Updated French translation. Combined contribution from baptiste.goupil@gmail.com and rocherl@club-internet.fr. ........ r5646 | mtredinnick | 2007-07-11 15:12:50 +0800 (Wed, 11 Jul 2007) | 2 lines Fixed #4753 -- Small update to Spanish translation from Mario Gonzalez. ........ r5649 | jacob | 2007-07-12 08:33:44 +0800 (Thu, 12 Jul 2007) | 1 line Fixed #4615: corrected reverse URL resolution examples in tutorial 4. Thanks for the patch, simeonf. ........ r5650 | adrian | 2007-07-12 12:43:29 +0800 (Thu, 12 Jul 2007) | 1 line Added 'New in Django development version' note to docs/syndication_feeds.txt changes from [5643] ........ r5651 | adrian | 2007-07-12 12:44:45 +0800 (Thu, 12 Jul 2007) | 1 line Edited changes to docs/tutorial04.txt from [5649] ........ r5652 | adrian | 2007-07-12 13:23:47 +0800 (Thu, 12 Jul 2007) | 1 line Added helpful error message to SiteManager.get_current() if the user hasn't set SITE_ID ........ r5653 | adrian | 2007-07-12 13:28:04 +0800 (Thu, 12 Jul 2007) | 1 line Added RequestSite class to sites framework ........ r5654 | adrian | 2007-07-12 13:29:32 +0800 (Thu, 12 Jul 2007) | 1 line Improved syndication feed framework to use RequestSite if the sites framework is not installed -- i.e., the sites framework is no longer required to use the syndication feed framework. This is backwards incompatible if anybody has subclassed Feed and overridden __init__(), because the second parameter is now expected to be an HttpRequest object instead of request.path ........ r5658 | russellm | 2007-07-12 15:45:35 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4459 -- Added 'raw' argument to save method, to override any pre-save processing, and modified serializers to use a raw-save. This enables serialization of DateFields with auto_now/auto_now_add. Also modified serializers to invoke save() directly on the model baseclass, to avoid any (potentially order-dependent, data modifying) behavior in a custom save() method. ........ r5659 | russellm | 2007-07-12 19:24:16 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #3770 -- Remove null=True tag from OneToOne serialization test. OneToOne fields can't have a value of null. ........ r5660 | russellm | 2007-07-12 19:27:38 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #3768 -- Disabled NullBooleanField PK serialization test. We can't and don't test null PK values. ........ r5662 | russellm | 2007-07-12 20:33:24 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4837 -- Updated Debian packaging details. Thanks for the suggestion, Yasushi Masuda <whosaysni@gmail.com>. ........ r5663 | russellm | 2007-07-12 20:44:05 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4808 -- Added Chilean regions in localflavor. Thanks, Marijn Vriens <marijn@metronomo.cl>. ........ r5664 | russellm | 2007-07-12 20:48:27 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4745 -- Updated docs to point out that 0 is not a valid SITE_ID when running the tests. Thanks for the suggestion, Lars Stavholm <stava@telcotec.se>. ........ r5665 | russellm | 2007-07-12 20:50:02 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4763 -- Minor typo in cache documentations. Thanks, dan@coffeecode.net. ........ r5666 | russellm | 2007-07-12 20:55:28 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4627 -- Added details on MacPorts packaging of Django. Thanks, Paul Bissex. ........ r5667 | russellm | 2007-07-12 21:23:11 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4640 -- Fixed import to stringfilter in docs. Proposed solution to move stringfilter into django.template.__init__ introduces a circular import problem. ........ r5668 | russellm | 2007-07-12 21:32:00 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4722 -- Clarified discussion about PYTHONPATH in modpython docs. Thanks for the suggestion, Collin Grady <cgrady@the-magi.us>. ........ r5669 | russellm | 2007-07-12 21:37:59 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4755 -- Modified newforms MultipleChoiceField to use list comprehension, rather than iteration. ........ r5670 | russellm | 2007-07-12 21:41:27 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4764 -- Added reference to Locale middleware in middleware docs. Thanks, dan@coffeecode.net. ........ r5671 | russellm | 2007-07-12 21:55:19 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4768 -- Converted timesince and dateformat to use explicit floor division (pre-emptive avoidance of Python 3000 compatibility problem), and removed a redundant millisecond check. Thanks, John Shaffer <jshaffer2112@gmail.com>. ........ r5672 | russellm | 2007-07-12 22:00:13 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4775 -- Added some missing Hungarian accents to the urlify.js LATIN_MAP. Thanks, Pistahh <szekeres@iii.hu>. ........ r5673 | russellm | 2007-07-12 22:05:16 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4502 -- Clarified reference to view in tutorial. Thanks for the suggestion, Carl Karsten <carl@personnelware.com>. ........ r5674 | russellm | 2007-07-12 22:11:41 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4522 -- Clarified the allowed filter arguments on the time and date filters. Thanks for the suggestion, admackin@gmail.com. ........ r5675 | russellm | 2007-07-12 22:21:51 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4525 -- Fixed mistaken documentation on arguments to runfcgi. Thanks, Johan Bergstrom <bugs@bergstroem.nu>. ........ r5676 | russellm | 2007-07-12 22:41:32 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4538 -- Split the installation instructions to differentiate between installing a distribution package and installing an official release. Thanks to Carl Karsten for the idea, and Paul Bissex for the patch. ........ r5677 | russellm | 2007-07-12 23:26:37 +0800 (Thu, 12 Jul 2007) | 2 lines Fixed #4526 -- Modified the test Client login method to fail when a user is inactive. Thanks, marcin@elksoft.pl. ........ r5678 | russellm | 2007-07-13 13:03:33 +0800 (Fri, 13 Jul 2007) | 2 lines Fixed #3505 -- Added handling for the error raised when the user forgets the comma in a single element tuple when defining AUTHENTICATION_BACKENDS. Thanks for the help identifying this problem, Mario Gonzalez <gonzalemario@gmail.com>. ........ r5679 | mtredinnick | 2007-07-13 16:52:07 +0800 (Fri, 13 Jul 2007) | 3 lines Fixed #2591 -- Fixed a problem with inspectdb with psycopg2 (only). Patch from Gary Wilson. ........ r5680 | mtredinnick | 2007-07-13 17:09:59 +0800 (Fri, 13 Jul 2007) | 3 lines Fixed #4807 -- Fixed a couple of corner cases in decimal form input validation. Based on a suggestion from Chriss Moffit. ........ r5681 | mtredinnick | 2007-07-13 17:14:51 +0800 (Fri, 13 Jul 2007) | 3 lines Fixed #4839 -- Added __repr__ methods to URL classes that show the pattern they contain. Thanks, Thomas G?\195?\188ttler. ........ r5682 | mtredinnick | 2007-07-13 18:56:30 +0800 (Fri, 13 Jul 2007) | 3 lines Fixed #4842 -- Added slightly more robust error reporting. Thanks, Thomas G?\195?\188ttler. ........ r5683 | mtredinnick | 2007-07-13 19:05:01 +0800 (Fri, 13 Jul 2007) | 3 lines Fixed #4846 -- Fixed some Python 2.3 encoding problems in the admin interface. Based on a patch from daybreaker12@gmail.com. ........ r5684 | mtredinnick | 2007-07-13 20:03:20 +0800 (Fri, 13 Jul 2007) | 3 lines Fixed #4861 -- Removed some duplicated logic from the newforms RegexField by making it a subclass of CharField. Thanks, Collin Grady. ........ r5685 | mtredinnick | 2007-07-13 21:15:35 +0800 (Fri, 13 Jul 2007) | 3 lines Fixed #4865 -- Replaced a stray generator comprehension with a list comprehension so that we don't break Python 2.3. ........ r5686 | mtredinnick | 2007-07-13 22:13:35 +0800 (Fri, 13 Jul 2007) | 3 lines Fixed #4469 -- Added slightly more informative error messages to max- and min-length newform validation. Based on a patch from A. Murat Eren. ........ r5687 | mtredinnick | 2007-07-13 22:14:47 +0800 (Fri, 13 Jul 2007) | 2 lines Added author credit for [5686]. Refs #4469. ........ r5688 | mtredinnick | 2007-07-13 22:33:46 +0800 (Fri, 13 Jul 2007) | 3 lines Fixed #4484 -- Fixed APPEND_SLASH handling to handle an empty path value. Thanks, VesselinK. ........ r5689 | mtredinnick | 2007-07-13 22:40:39 +0800 (Fri, 13 Jul 2007) | 2 lines Fixed #4556 -- Stylistic changes to [5500]. Thanks, glin@seznam.cz. ........ r5690 | gwilson | 2007-07-14 04:36:01 +0800 (Sat, 14 Jul 2007) | 2 lines Refs #2591 -- Removed int conversion and try/except since the value in the single-item list is already an int. I overlooked this in my original patch, which was applied in [5679]. ........ r5691 | adrian | 2007-07-14 05:20:07 +0800 (Sat, 14 Jul 2007) | 1 line Documented the 'commit' argument to save() methods on forms created via form_for_model() or form_for_instance() ........ r5692 | mtredinnick | 2007-07-14 13:27:22 +0800 (Sat, 14 Jul 2007) | 3 lines Fixed #4869 -- Added a note that syncdb does not alter existing tables. Thanks, James Bennett. ........ r5693 | mtredinnick | 2007-07-14 20:48:24 +0800 (Sat, 14 Jul 2007) | 3 lines Fixed #4863 -- Removed comment references to a no-longer present link. Pointed out by Thomas G?\195?\188ttler. ........ r5694 | mtredinnick | 2007-07-14 21:14:28 +0800 (Sat, 14 Jul 2007) | 2 lines Fixed #4862 -- Fixed invalid Javascript creation in popup windows in admin. ........ r5695 | mtredinnick | 2007-07-14 21:39:41 +0800 (Sat, 14 Jul 2007) | 2 lines Fixed a problem with translatable strings from [5686]. ........ r5696 | mtredinnick | 2007-07-14 22:47:14 +0800 (Sat, 14 Jul 2007) | 3 lines Fixed #4731 -- Changed management.setup_environ() so that it no longer assumes the settings module is called "settings". Patch from SmileyChris. ........ r5697 | mtredinnick | 2007-07-14 22:50:35 +0800 (Sat, 14 Jul 2007) | 3 lines Fixed #4870 -- Removed unneeded import and fixed a docstring in an example. Thanks, Collin Grady. ........ r5698 | adrian | 2007-07-15 00:58:54 +0800 (Sun, 15 Jul 2007) | 1 line Edited docs/db-api.txt changes from [5658] ........ r5699 | adrian | 2007-07-15 01:04:30 +0800 (Sun, 15 Jul 2007) | 1 line Negligible capitalization fix in test/client.py docstring ........ r5700 | russellm | 2007-07-15 12:41:59 +0800 (Sun, 15 Jul 2007) | 2 lines Clarified the documentation on the steps that happen during a save, and how raw save affects those steps. ........ r5701 | gwilson | 2007-07-15 13:03:28 +0800 (Sun, 15 Jul 2007) | 2 lines Fixed #4310 -- Fixed a regular expression bug in `strip_entities` function and added tests for several `django.utils.html` functions. Based on patch from Brian Harring. ........ r5702 | gwilson | 2007-07-15 13:11:06 +0800 (Sun, 15 Jul 2007) | 2 lines Fixed #4877 -- Fixed typo in testing documentation, patch from John Shaffer. ........ r5703 | gwilson | 2007-07-15 14:24:54 +0800 (Sun, 15 Jul 2007) | 2 lines Fixed #3012 -- Changed the locmem cache backend to use pickle instead of deepcopy to make it compatible with iterators (which cannot be copied). Patch from Sundance. ........ r5704 | gwilson | 2007-07-15 14:29:45 +0800 (Sun, 15 Jul 2007) | 2 lines Changed imports to adhere to PEP 8. ........ r5705 | mtredinnick | 2007-07-15 17:39:13 +0800 (Sun, 15 Jul 2007) | 3 lines Fixed #4880 -- Updated Spanish translation (includes re-encoding to UTF-8). Thanks, Jorge Gajon. ........ r5706 | mtredinnick | 2007-07-15 17:46:42 +0800 (Sun, 15 Jul 2007) | 3 lines Fixed #4882 -- Updated Argentinean Spanish translation (includes re-encoding to UTF-8). Thanks, Ramiro Morales. ........ r5707 | mtredinnick | 2007-07-15 18:08:05 +0800 (Sun, 15 Jul 2007) | 3 lines Re-encoded djangojs.po for French and German locales to UTF-8. These were the last two non-UTF-8 PO files. ........ r5708 | mtredinnick | 2007-07-15 18:10:44 +0800 (Sun, 15 Jul 2007) | 6 lines Fixed #4734 -- Changed message extraction to permit non-ACSII msgid strings. Thanks, krzysiek.pawlik@silvermedia.pl. This is slightly backwards-incompatible for translators: PO files are now assumed to be in UTF-8 encoding. ........ r5709 | adrian | 2007-07-16 03:34:21 +0800 (Mon, 16 Jul 2007) | 1 line Edited docs/db-api.txt changes from [5700] ........ r5710 | adrian | 2007-07-16 05:16:32 +0800 (Mon, 16 Jul 2007) | 1 line Improved docs/templates.txt section on the 'regroup' tag ........ r5711 | mtredinnick | 2007-07-16 11:48:03 +0800 (Mon, 16 Jul 2007) | 2 lines Updated AUTHORS for [5708]. ........ r5712 | mtredinnick | 2007-07-16 11:50:22 +0800 (Mon, 16 Jul 2007) | 3 lines Fixed #4199 -- Changed date formatting in HTTP expires header to be spec compliant. Thanks, Chris Bennett. ........ r5713 | mtredinnick | 2007-07-16 12:45:45 +0800 (Mon, 16 Jul 2007) | 3 lines Fixed #4884 -- Fixed an initialisation problem when assigned to settings before accessing them. Thanks, Noam Raphael. ........ r5714 | mtredinnick | 2007-07-16 12:47:52 +0800 (Mon, 16 Jul 2007) | 2 lines Fixed #4806 -- Updated Simplified Chinese translation. Thanks, limodou. ........ r5715 | mtredinnick | 2007-07-16 12:54:49 +0800 (Mon, 16 Jul 2007) | 3 lines Fixed #4887 -- Fixed another place where template tag arguments are used directly as function keyword args. Thanks, Brian Rosner. ........ r5716 | gwilson | 2007-07-16 13:00:18 +0800 (Mon, 16 Jul 2007) | 2 lines Refs #3012 -- Removed iterator from `test_data_types` cache test that I added in [5703]. Iterators cannot be pickled either. Left the rest of [5703] there though since it fixed another issue that was causing the `test_data_types` cache test to fail with the `locmem` cache backend, the fact that functions cannot be copied. ........ r5717 | gwilson | 2007-07-16 13:28:13 +0800 (Mon, 16 Jul 2007) | 2 lines Cleaned up a couple unused imports and fixed docstrings to follow Python Style Guide. ........ r5718 | mtredinnick | 2007-07-16 17:36:10 +0800 (Mon, 16 Jul 2007) | 3 lines Fixed #4845 -- Fixed some problems with Unicode usage and caching. Thanks, Jeremy Dunck. ........ r5719 | gwilson | 2007-07-16 21:47:43 +0800 (Mon, 16 Jul 2007) | 2 lines Removed unused variable and changed comments about `permalink` decorator into a docstring. ........ r5720 | gwilson | 2007-07-17 06:29:09 +0800 (Tue, 17 Jul 2007) | 2 lines Fixed #4851 -- Fixed description of an example query in `db-api` docs. ........ r5721 | mtredinnick | 2007-07-17 12:22:11 +0800 (Tue, 17 Jul 2007) | 2 lines Fixed #4898 -- Fixed a precendence problem when constructing HTTP Date header. ........ r5722 | mtredinnick | 2007-07-17 18:25:43 +0800 (Tue, 17 Jul 2007) | 3 lines Fixed #4899 -- Fixed a problem with PO file header generation caused by [5708]. Thanks, Ramiro Morales. ........ r5723 | mtredinnick | 2007-07-19 17:23:45 +0800 (Thu, 19 Jul 2007) | 2 lines Fixed #4917 -- Updated Swedish translation. Thanks, Pilip Lindborg. ........ r5724 | mtredinnick | 2007-07-19 17:24:36 +0800 (Thu, 19 Jul 2007) | 2 lines Fixed #3925 -- Added Slovak localflavor items. Thanks, Martin Kos?\195?\173r. ........ r5725 | adrian | 2007-07-20 14:28:56 +0800 (Fri, 20 Jul 2007) | 1 line Added a db_type() method to the database Field class. This is a hook for calculating the database column type for a given Field. Also converted all management.py CREATE TABLE statements to use db_type(), which made that code cleaner. The Field.get_internal_type() hook still exists, but we should consider removing it at some point, because db_type() is more general. Also added docs -- the beginnings of docs on how to create custom database Field classes. This is backwards-compatible. ........ r5726 | adrian | 2007-07-20 14:34:26 +0800 (Fri, 20 Jul 2007) | 1 line Simplified the indent level in management.py _get_sql_model_create() by using a 'continue' statement rather than nesting everything in an 'if' ........ r5727 | russellm | 2007-07-20 20:07:58 +0800 (Fri, 20 Jul 2007) | 2 lines Fixed #4558 -- Modified XML serializer to handle whitespace better around None tags. Thanks to Bill Fenner <fenner@gmail.com> for the report and fix. ........ r5728 | russellm | 2007-07-20 20:15:02 +0800 (Fri, 20 Jul 2007) | 2 lines Fixed #4897 -- Fixed minor typo in doctest comment. ........ r5729 | russellm | 2007-07-20 21:57:49 +0800 (Fri, 20 Jul 2007) | 2 lines Fixed #3782 -- Added support for the suite() method recommended by the Python unittest docs. Thanks for the suggestion, rene.puls@repro-mayr.de. ........ r5730 | russellm | 2007-07-20 22:07:54 +0800 (Fri, 20 Jul 2007) | 2 lines Refs #3782 -- Added documentation note that suite() handling is only in development version. ........ r5731 | russellm | 2007-07-20 22:32:20 +0800 (Fri, 20 Jul 2007) | 2 lines Fixed #4901 -- Modified assertContains to provide a default check of 'any instances of text in content'. Thanks for the suggestion, nis@superlativ.dk. ........ r5732 | russellm | 2007-07-20 22:42:57 +0800 (Fri, 20 Jul 2007) | 2 lines Fixed #4738 -- Modified the prompt that is displayed when a test database cannot be created. The existing prompt was misleading if the issue wasn't a pre-existing database. Thanks for the suggestion, John Shaffer <jshaffer2112@gmail.com>. ........ r5733 | adrian | 2007-07-20 23:40:54 +0800 (Fri, 20 Jul 2007) | 1 line Fixed negligible typo in docstring in tests/regressiontests/test_client_regress/models.py from [5731] ........ r5736 | adrian | 2007-07-21 05:24:30 +0800 (Sat, 21 Jul 2007) | 1 line Added some additional docs to docs/model-api.txt db_type() section ........ r5738 | russellm | 2007-07-21 11:30:38 +0800 (Sat, 21 Jul 2007) | 2 lines Fixed #4304 -- Modified sys.exit to os._exit to make sure development server quits when an error occurs attempting to bind to the requested port (e.g., if another server is already running). Thanks, Mario Gonzalez <gonzalemario@gmail.com>. ........ r5739 | russellm | 2007-07-21 12:36:28 +0800 (Sat, 21 Jul 2007) | 2 lines Minor fix to allow for count=0 in assertContains. ........ r5740 | russellm | 2007-07-21 13:15:19 +0800 (Sat, 21 Jul 2007) | 2 lines Added test cases for change [5739]. ........ r5741 | russellm | 2007-07-21 13:17:20 +0800 (Sat, 21 Jul 2007) | 2 lines Fixed #4402 -- Modified test client to allow multi-valued inputs on GET requests. Thanks for the suggestion, eddymul@gmail.com. ........ r5743 | gwilson | 2007-07-22 10:18:36 +0800 (Sun, 22 Jul 2007) | 2 lines Fixed #4945 -- Removed unused `GET_ITERATOR_CHUNK_SIZE` definition from manager.py. `GET_ITERATOR_CHUNK_SIZE` is already defined in query.py. Thanks zigiDev@mac.com. ........ r5744 | gwilson | 2007-07-22 11:09:24 +0800 (Sun, 22 Jul 2007) | 2 lines Added docstrings to shortcuts module and functions. ........ r5745 | gwilson | 2007-07-22 11:12:50 +0800 (Sun, 22 Jul 2007) | 2 lines Shortcut functions do not accept `QuerySet` objects, yet :) ........ r5746 | gwilson | 2007-07-22 11:41:11 +0800 (Sun, 22 Jul 2007) | 2 lines Fixed #4373 -- Modified the get_object_or_404/get_list_or_404 shortcuts to also accept `QuerySet`s. Thanks SuperJared. ........ r5747 | gwilson | 2007-07-22 11:45:03 +0800 (Sun, 22 Jul 2007) | 2 lines Corrected typo in [5746]. ........ r5750 | gwilson | 2007-07-23 12:45:01 +0800 (Mon, 23 Jul 2007) | 2 lines Fixed #4952 -- Fixed the `get_template_sources` functions of the `app_directories` and `filesystem` template loaders to not return paths outside of given template directories. Both functions now make use of a new `safe_join` utility function. Thanks to SmileyChris for help with the patch. ........ r5752 | russellm | 2007-07-23 20:14:32 +0800 (Mon, 23 Jul 2007) | 2 lines Fixed #3771 -- Modified the test runner to observe the --noinput argument controlling script interactivity. This means that test scripts can now be put in a buildbot environment. This is a backwards incompatible change for anyone that has written a custom test runner. Thanks for the suggestion, moof@metamoof.net. ........ r5753 | russellm | 2007-07-23 21:52:59 +0800 (Mon, 23 Jul 2007) | 2 lines Added documentation for a test runner argument that has always been present, but was undocumented. ........ r5756 | adrian | 2007-07-25 11:12:31 +0800 (Wed, 25 Jul 2007) | 1 line Changed docstring additions from [5744] to use active verbs ('returns' instead of 'return') ........ r5757 | adrian | 2007-07-25 11:15:05 +0800 (Wed, 25 Jul 2007) | 1 line Added 'New in Django development version' to docs/db-api.txt change from [5746] ........ r5758 | adrian | 2007-07-25 11:18:17 +0800 (Wed, 25 Jul 2007) | 1 line Changed safe_join() docstring from [5750] to use active verbs. See also [5756] ........ r5764 | gwilson | 2007-07-26 13:01:53 +0800 (Thu, 26 Jul 2007) | 2 lines Fixed #4971 -- Fixed some escaping and quoting problems in the databrowse contrib app. Based on patch from Johann Queuniet. ........ r5765 | adrian | 2007-07-27 01:16:34 +0800 (Fri, 27 Jul 2007) | 1 line Added section to docs/contributing.txt about docstring coding style ........ r5766 | mtredinnick | 2007-07-27 06:59:34 +0800 (Fri, 27 Jul 2007) | 2 lines Added support for database cache table in test database. ........ r5767 | adrian | 2007-07-28 05:53:02 +0800 (Sat, 28 Jul 2007) | 1 line Added unit test that confirms a bug in ValuesQuerySets that have extra(select) specified. If the select dictionary has several fields, Django assigns the wrong values to the select-field names ........ r5768 | adrian | 2007-07-28 06:07:42 +0800 (Sat, 28 Jul 2007) | 1 line Fixed bug with using values() and extra(select) in the same QuerySet, with a select dictionary containing more than a few elements. This bug was identified in unit test from [5767]. The problem was that we were relying on the dictionary's .items() ordering, which is undefined ........ r5769 | russellm | 2007-07-28 12:02:52 +0800 (Sat, 28 Jul 2007) | 2 lines Fixed #4460 -- Added the ability to be more specific in the test cases that are executed. This is a backwards incompatible change for any user with a custom test runner. See the wiki for details. ........ r5770 | russellm | 2007-07-28 15:27:53 +0800 (Sat, 28 Jul 2007) | 2 lines Fixed #4995 -- Fixed some problems in documentation ReST formatting. Thanks, Simon G. ........ r5771 | simon | 2007-07-29 02:30:40 +0800 (Sun, 29 Jul 2007) | 1 line After discussing with Malcolm, added set_unusable_password() and has_usable_password() methods to the User object, plus tests and updated documentation ........ r5774 | adrian | 2007-07-30 02:21:16 +0800 (Mon, 30 Jul 2007) | 1 line Added 'New in Django development version' to changes in docs/authentication.txt from [5771] ........ r5778 | gwilson | 2007-07-31 01:25:35 +0800 (Tue, 31 Jul 2007) | 4 lines Fixed call to `ugettext`, which is imported as `_`. Changed raise to conform to PEP 3109 and wrapped the long line. Added beginnings of tests for model fields. ........ r5782 | gwilson | 2007-08-01 13:41:32 +0800 (Wed, 01 Aug 2007) | 2 lines Fixed #4228 -- Removed hardcoding of `RadioFieldRenderer` in the `RadioSelect` Widget so that the display of `RadioSelect`s can be more easily customized. `BoundField.__unicode__` also no longer special cases `RadioSelect` since `RadioSelect.render()` now returns a string like every other Widget. ........ r5783 | gwilson | 2007-08-01 13:52:18 +0800 (Wed, 01 Aug 2007) | 2 lines Fixed #5037 -- Fixed use of wrong field type in a db-api docs example, thanks ubernostrum. ........ r5796 | gwilson | 2007-08-04 11:19:14 +0800 (Sat, 04 Aug 2007) | 2 lines Fixed #5078 -- Fixed several broken links to the syndication documentation. ........ r5797 | gwilson | 2007-08-04 11:36:58 +0800 (Sat, 04 Aug 2007) | 2 lines Changed the 0.95 release notes to point to the 0.95 documentation index. ........ r5798 | gwilson | 2007-08-04 11:39:24 +0800 (Sat, 04 Aug 2007) | 2 lines Changed several documentation links to be relative. ........ r5799 | gwilson | 2007-08-04 22:41:49 +0800 (Sat, 04 Aug 2007) | 2 lines Refs #3397 -- Corrected the Exception that is caught when ordering by non-fields (added in [4596]), thanks glin@seznam.cz. ........ r5800 | gwilson | 2007-08-04 22:52:13 +0800 (Sat, 04 Aug 2007) | 2 lines Fixed #5083 -- Fixed typo in newforms documentation, thanks Rik. ........ r5801 | gwilson | 2007-08-05 12:39:52 +0800 (Sun, 05 Aug 2007) | 2 lines Refs #5089 -- Added file name to poll detail template examples in the tutorial. ........ r5802 | gwilson | 2007-08-05 12:42:26 +0800 (Sun, 05 Aug 2007) | 2 lines Changed some more links to be relative in the documentation. I had a couple unsaved files that didn't get in with [5798]. ........ r5803 | gwilson | 2007-08-05 13:14:46 +0800 (Sun, 05 Aug 2007) | 2 lines Fixed #2101 -- Renamed `maxlength` argument to `max_length` for oldforms `FormField`s and db model `Field`s. This is fully backwards compatible at the moment since the legacy `maxlength` argument is still supported. Using `maxlength` will, however, issue a `PendingDeprecationWarning` when used. ........ r5804 | russellm | 2007-08-05 15:39:36 +0800 (Sun, 05 Aug 2007) | 2 lines Fixed #4001 -- Added dynamic save_m2m method() to forms created with form_for_model and form_for_instance on save(commit=False). ........ r5807 | adrian | 2007-08-06 12:36:43 +0800 (Mon, 06 Aug 2007) | 1 line Fixed #5074 -- Added link to audio clip of 'Django' pronunciation ........ r5808 | adrian | 2007-08-06 12:52:14 +0800 (Mon, 06 Aug 2007) | 1 line Edited docs/newforms.txt changes from [5804] ........ r5809 | adrian | 2007-08-06 13:04:27 +0800 (Mon, 06 Aug 2007) | 1 line Fixed #5082 -- Enabled tab completion in 'django-admin.py shell' for objects that were imported into the global namespace at runtime. Thanks, dusk@woofle.net ........ r5810 | adrian | 2007-08-06 13:06:15 +0800 (Mon, 06 Aug 2007) | 1 line Fixed #5077 -- django/utils/encoding.py no longer imports settings, as it doesn't use that module. Thanks, Collin Grady ........ r5811 | adrian | 2007-08-06 13:07:38 +0800 (Mon, 06 Aug 2007) | 1 line Fixed #5071 -- Fixed 'global name ugettext is not defined' error in django.core.validators. Thanks, Marco Bonetti ........ r5812 | adrian | 2007-08-06 13:13:06 +0800 (Mon, 06 Aug 2007) | 1 line Fixed #5064 -- Fixed potentially confusing sentence in docs/authentication.txt. Thanks, Collin Grady ........ r5813 | adrian | 2007-08-06 13:16:35 +0800 (Mon, 06 Aug 2007) | 1 line Fixed #5053 -- Added 'action' attribute to <form> tags that didn't have that attribute in docs/newforms.txt examples. Perfectionism appreciated, trickyb ........ r5814 | adrian | 2007-08-06 13:27:58 +0800 (Mon, 06 Aug 2007) | 1 line Added a closing </p>' to a code example in docs/email.txt ........ r5815 | adrian | 2007-08-06 13:28:45 +0800 (Mon, 06 Aug 2007) | 1 line Fixed #5006 -- Fixed incorrect/outdated docstring for the 'if' template tag. Thanks, Thomas Petazzoni ........ r5816 | adrian | 2007-08-06 13:33:18 +0800 (Mon, 06 Aug 2007) | 1 line Added note to docs/model-api.txt about help_text not being escaped in the admin interface ........ r5817 | adrian | 2007-08-06 13:34:45 +0800 (Mon, 06 Aug 2007) | 1 line Fixed #4985 -- Clarified location of HttpResponse in docs/request_response.txt. Thanks for raising the issue, rainer.mansfeld@romulo.de ........ r5818 | adrian | 2007-08-06 13:37:17 +0800 (Mon, 06 Aug 2007) | 1 line Fixed #4980 -- Removed 'forms' from the 'not considered stable and will be rewritten' section of docs/api_stability.txt. They've already been rewritten. ........ r5819 | russellm | 2007-08-06 21:58:56 +0800 (Mon, 06 Aug 2007) | 2 lines Fixed #3297 -- Implemented FileField and ImageField for newforms. Thanks to the many users that contributed to and tested this patch. ........ r5820 | russellm | 2007-08-06 22:17:10 +0800 (Mon, 06 Aug 2007) | 2 lines Added note that FileField and ImageField are only in development version. There are also some minor backwards compatibility issues with the changes introduced in [5819] - see the wiki for details. ........ r5823 | adrian | 2007-08-07 04:27:04 +0800 (Tue, 07 Aug 2007) | 1 line Fixed British spelling of 'customize' and 'behavior' in Manager.get_query_set() docstring ........ r5824 | adrian | 2007-08-07 10:18:36 +0800 (Tue, 07 Aug 2007) | 1 line Fixed #5105 -- Fixed two ReST errors in docs/newforms.txt. Thanks, Ramiro Morales ........ r5825 | adrian | 2007-08-07 10:33:11 +0800 (Tue, 07 Aug 2007) | 1 line Fixed #5097 -- Made various updates and corrections to the documentation. Thanks, Nicola Larosa ........ r5826 | russellm | 2007-08-07 19:20:15 +0800 (Tue, 07 Aug 2007) | 2 lines Removed a redundant directory join during FileField form saving. Thanks to David Danier's eagle eyes for picking up this one. ........ git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@5828 bcc190cf-cafb-0310-a4f2-bffc1f526a37
701 lines
28 KiB
Plaintext
701 lines
28 KiB
Plaintext
===============================
|
|
Forms, fields, and manipulators
|
|
===============================
|
|
|
|
Forwards-compatibility note
|
|
===========================
|
|
|
|
The legacy forms/manipulators system described in this document is going to be
|
|
replaced in the next Django release. If you're starting from scratch, we
|
|
strongly encourage you not to waste your time learning this. Instead, learn and
|
|
use the django.newforms system, which we have begun to document in the
|
|
`newforms documentation`_.
|
|
|
|
If you have legacy form/manipulator code, read the "Migration plan" section in
|
|
that document to understand how we're making the switch.
|
|
|
|
.. _newforms documentation: ../newforms/
|
|
|
|
Introduction
|
|
============
|
|
|
|
Once you've got a chance to play with Django's admin interface, you'll probably
|
|
wonder if the fantastic form validation framework it uses is available to user
|
|
code. It is, and this document explains how the framework works.
|
|
|
|
We'll take a top-down approach to examining Django's form validation framework,
|
|
because much of the time you won't need to use the lower-level APIs. Throughout
|
|
this document, we'll be working with the following model, a "place" object::
|
|
|
|
from django.db import models
|
|
|
|
PLACE_TYPES = (
|
|
(1, 'Bar'),
|
|
(2, 'Restaurant'),
|
|
(3, 'Movie Theater'),
|
|
(4, 'Secret Hideout'),
|
|
)
|
|
|
|
class Place(models.Model):
|
|
name = models.CharField(max_length=100)
|
|
address = models.CharField(max_length=100, blank=True)
|
|
city = models.CharField(max_length=50, blank=True)
|
|
state = models.USStateField()
|
|
zip_code = models.CharField(max_length=5, blank=True)
|
|
place_type = models.IntegerField(choices=PLACE_TYPES)
|
|
|
|
class Admin:
|
|
pass
|
|
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
Defining the above class is enough to create an admin interface to a ``Place``,
|
|
but what if you want to allow public users to submit places?
|
|
|
|
Automatic Manipulators
|
|
======================
|
|
|
|
The highest-level interface for object creation and modification is the
|
|
**automatic Manipulator** framework. An automatic manipulator is a utility
|
|
class tied to a given model that "knows" how to create or modify instances of
|
|
that model and how to validate data for the object. Automatic Manipulators come
|
|
in two flavors: ``AddManipulators`` and ``ChangeManipulators``. Functionally
|
|
they are quite similar, but the former knows how to create new instances of the
|
|
model, while the latter modifies existing instances. Both types of classes are
|
|
automatically created when you define a new class::
|
|
|
|
>>> from mysite.myapp.models import Place
|
|
>>> Place.AddManipulator
|
|
<class 'django.models.manipulators.AddManipulator'>
|
|
>>> Place.ChangeManipulator
|
|
<class 'django.models.manipulators.ChangeManipulator'>
|
|
|
|
Using the ``AddManipulator``
|
|
----------------------------
|
|
|
|
We'll start with the ``AddManipulator``. Here's a very simple view that takes
|
|
POSTed data from the browser and creates a new ``Place`` object::
|
|
|
|
from django.shortcuts import render_to_response
|
|
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
|
from django import forms
|
|
from mysite.myapp.models import Place
|
|
|
|
def naive_create_place(request):
|
|
"""A naive approach to creating places; don't actually use this!"""
|
|
# Create the AddManipulator.
|
|
manipulator = Place.AddManipulator()
|
|
|
|
# Make a copy of the POSTed data so that do_html2python can
|
|
# modify it in place (request.POST is immutable).
|
|
new_data = request.POST.copy()
|
|
|
|
# Convert the request data (which will all be strings) into the
|
|
# appropriate Python types for those fields.
|
|
manipulator.do_html2python(new_data)
|
|
|
|
# Save the new object.
|
|
new_place = manipulator.save(new_data)
|
|
|
|
# It worked!
|
|
return HttpResponse("Place created: %s" % new_place)
|
|
|
|
The ``naive_create_place`` example works, but as you probably can tell, this
|
|
view has a number of problems:
|
|
|
|
* No validation of any sort is performed. If, for example, the ``name`` field
|
|
isn't given in ``request.POST``, the save step will cause a database error
|
|
because that field is required. Ugly.
|
|
|
|
* Even if you *do* perform validation, there's still no way to give that
|
|
information to the user in any sort of useful way.
|
|
|
|
* You'll have to separately create a form (and view) that submits to this
|
|
page, which is a pain and is redundant.
|
|
|
|
Let's dodge these problems momentarily to take a look at how you could create a
|
|
view with a form that submits to this flawed creation view::
|
|
|
|
def naive_create_place_form(request):
|
|
"""Simplistic place form view; don't actually use anything like this!"""
|
|
# Create a FormWrapper object that the template can use. Ignore
|
|
# the last two arguments to FormWrapper for now.
|
|
form = forms.FormWrapper(Place.AddManipulator(), {}, {})
|
|
return render_to_response('places/naive_create_form.html', {'form': form})
|
|
|
|
(This view, as well as all the following ones, has the same imports as in the
|
|
first example above.)
|
|
|
|
The ``forms.FormWrapper`` object is a wrapper that templates can
|
|
easily deal with to create forms. Here's the ``naive_create_form.html``
|
|
template::
|
|
|
|
{% extends "base.html" %}
|
|
|
|
{% block content %}
|
|
<h1>Create a place:</h1>
|
|
|
|
<form method="post" action="../do_new/">
|
|
<p><label for="id_name">Name:</label> {{ form.name }}</p>
|
|
<p><label for="id_address">Address:</label> {{ form.address }}</p>
|
|
<p><label for="id_city">City:</label> {{ form.city }}</p>
|
|
<p><label for="id_state">State:</label> {{ form.state }}</p>
|
|
<p><label for="id_zip_code">Zip:</label> {{ form.zip_code }}</p>
|
|
<p><label for="id_place_type">Place type:</label> {{ form.place_type }}</p>
|
|
<input type="submit" />
|
|
</form>
|
|
{% endblock %}
|
|
|
|
Before we get back to the problems with these naive set of views, let's go over
|
|
some salient points of the above template:
|
|
|
|
* Field "widgets" are handled for you: ``{{ form.field }}`` automatically
|
|
creates the "right" type of widget for the form, as you can see with the
|
|
``place_type`` field above.
|
|
|
|
* There isn't a way just to spit out the form. You'll still need to define
|
|
how the form gets laid out. This is a feature: Every form should be
|
|
designed differently. Django doesn't force you into any type of mold.
|
|
If you must use tables, use tables. If you're a semantic purist, you can
|
|
probably find better HTML than in the above template.
|
|
|
|
* To avoid name conflicts, the ``id`` values of form elements take the
|
|
form "id_*fieldname*".
|
|
|
|
By creating a creation form we've solved problem number 3 above, but we still
|
|
don't have any validation. Let's revise the validation issue by writing a new
|
|
creation view that takes validation into account::
|
|
|
|
def create_place_with_validation(request):
|
|
manipulator = Place.AddManipulator()
|
|
new_data = request.POST.copy()
|
|
|
|
# Check for validation errors
|
|
errors = manipulator.get_validation_errors(new_data)
|
|
manipulator.do_html2python(new_data)
|
|
if errors:
|
|
return render_to_response('places/errors.html', {'errors': errors})
|
|
else:
|
|
new_place = manipulator.save(new_data)
|
|
return HttpResponse("Place created: %s" % new_place)
|
|
|
|
In this new version, errors will be found -- ``manipulator.get_validation_errors``
|
|
handles all the validation for you -- and those errors can be nicely presented
|
|
on an error page (templated, of course)::
|
|
|
|
{% extends "base.html" %}
|
|
|
|
{% block content %}
|
|
|
|
<h1>Please go back and correct the following error{{ errors|pluralize }}:</h1>
|
|
<ul>
|
|
{% for e in errors.items %}
|
|
<li>Field "{{ e.0 }}": {{ e.1|join:", " }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
|
|
{% endblock %}
|
|
|
|
Still, this has its own problems:
|
|
|
|
* There's still the issue of creating a separate (redundant) view for the
|
|
submission form.
|
|
|
|
* Errors, though nicely presented, are on a separate page, so the user will
|
|
have to use the "back" button to fix errors. That's ridiculous and unusable.
|
|
|
|
The best way to deal with these issues is to collapse the two views -- the form
|
|
and the submission -- into a single view. This view will be responsible for
|
|
creating the form, validating POSTed data, and creating the new object (if the
|
|
data is valid). An added bonus of this approach is that errors and the form will
|
|
both be available on the same page, so errors with fields can be presented in
|
|
context.
|
|
|
|
.. admonition:: Philosophy:
|
|
|
|
Finally, for the HTTP purists in the audience (and the authorship), this
|
|
nicely matches the "true" meanings of HTTP GET and HTTP POST: GET fetches
|
|
the form, and POST creates the new object.
|
|
|
|
Below is the finished view::
|
|
|
|
def create_place(request):
|
|
manipulator = Place.AddManipulator()
|
|
|
|
if request.method == 'POST':
|
|
# If data was POSTed, we're trying to create a new Place.
|
|
new_data = request.POST.copy()
|
|
|
|
# Check for errors.
|
|
errors = manipulator.get_validation_errors(new_data)
|
|
manipulator.do_html2python(new_data)
|
|
|
|
if not errors:
|
|
# No errors. This means we can save the data!
|
|
new_place = manipulator.save(new_data)
|
|
|
|
# Redirect to the object's "edit" page. Always use a redirect
|
|
# after POST data, so that reloads don't accidently create
|
|
# duplicate entires, and so users don't see the confusing
|
|
# "Repost POST data?" alert box in their browsers.
|
|
return HttpResponseRedirect("/places/edit/%i/" % new_place.id)
|
|
else:
|
|
# No POST, so we want a brand new form without any data or errors.
|
|
errors = new_data = {}
|
|
|
|
# Create the FormWrapper, template, context, response.
|
|
form = forms.FormWrapper(manipulator, new_data, errors)
|
|
return render_to_response('places/create_form.html', {'form': form})
|
|
|
|
and here's the ``create_form`` template::
|
|
|
|
{% extends "base.html" %}
|
|
|
|
{% block content %}
|
|
<h1>Create a place:</h1>
|
|
|
|
{% if form.has_errors %}
|
|
<h2>Please correct the following error{{ form.error_dict|pluralize }}:</h2>
|
|
{% endif %}
|
|
|
|
<form method="post" action=".">
|
|
<p>
|
|
<label for="id_name">Name:</label> {{ form.name }}
|
|
{% if form.name.errors %}*** {{ form.name.errors|join:", " }}{% endif %}
|
|
</p>
|
|
<p>
|
|
<label for="id_address">Address:</label> {{ form.address }}
|
|
{% if form.address.errors %}*** {{ form.address.errors|join:", " }}{% endif %}
|
|
</p>
|
|
<p>
|
|
<label for="id_city">City:</label> {{ form.city }}
|
|
{% if form.city.errors %}*** {{ form.city.errors|join:", " }}{% endif %}
|
|
</p>
|
|
<p>
|
|
<label for="id_state">State:</label> {{ form.state }}
|
|
{% if form.state.errors %}*** {{ form.state.errors|join:", " }}{% endif %}
|
|
</p>
|
|
<p>
|
|
<label for="id_zip_code">Zip:</label> {{ form.zip_code }}
|
|
{% if form.zip_code.errors %}*** {{ form.zip_code.errors|join:", " }}{% endif %}
|
|
</p>
|
|
<p>
|
|
<label for="id_place_type">Place type:</label> {{ form.place_type }}
|
|
{% if form.place_type.errors %}*** {{ form.place_type.errors|join:", " }}{% endif %}
|
|
</p>
|
|
<input type="submit" />
|
|
</form>
|
|
{% endblock %}
|
|
|
|
The second two arguments to ``FormWrapper`` (``new_data`` and ``errors``)
|
|
deserve some mention.
|
|
|
|
The first is any "default" data to be used as values for the fields. Pulling
|
|
the data from ``request.POST``, as is done above, makes sure that if there are
|
|
errors, the values the user put in aren't lost. If you try the above example,
|
|
you'll see this in action.
|
|
|
|
The second argument is the error list retrieved from
|
|
``manipulator.get_validation_errors``. When passed into the ``FormWrapper``,
|
|
this gives each field an ``errors`` item (which is a list of error messages
|
|
associated with the field) as well as a ``html_error_list`` item, which is a
|
|
``<ul>`` of error messages. The above template uses these error items to
|
|
display a simple error message next to each field. The error list is saved as
|
|
an ``error_dict`` attribute of the ``FormWrapper`` object.
|
|
|
|
Using the ``ChangeManipulator``
|
|
-------------------------------
|
|
|
|
The above has covered using the ``AddManipulator`` to create a new object. What
|
|
about editing an existing one? It's shockingly similar to creating a new one::
|
|
|
|
def edit_place(request, place_id):
|
|
# Get the place in question from the database and create a
|
|
# ChangeManipulator at the same time.
|
|
try:
|
|
manipulator = Place.ChangeManipulator(place_id)
|
|
except Place.DoesNotExist:
|
|
raise Http404
|
|
|
|
# Grab the Place object in question for future use.
|
|
place = manipulator.original_object
|
|
|
|
if request.method == 'POST':
|
|
new_data = request.POST.copy()
|
|
errors = manipulator.get_validation_errors(new_data)
|
|
manipulator.do_html2python(new_data)
|
|
if not errors:
|
|
manipulator.save(new_data)
|
|
|
|
# Do a post-after-redirect so that reload works, etc.
|
|
return HttpResponseRedirect("/places/edit/%i/" % place.id)
|
|
else:
|
|
errors = {}
|
|
# This makes sure the form accurate represents the fields of the place.
|
|
new_data = manipulator.flatten_data()
|
|
|
|
form = forms.FormWrapper(manipulator, new_data, errors)
|
|
return render_to_response('places/edit_form.html', {'form': form, 'place': place})
|
|
|
|
The only real differences are:
|
|
|
|
* We create a ``ChangeManipulator`` instead of an ``AddManipulator``.
|
|
The argument to a ``ChangeManipulator`` is the ID of the object
|
|
to be changed. As you can see, the initializer will raise an
|
|
``ObjectDoesNotExist`` exception if the ID is invalid.
|
|
|
|
* ``ChangeManipulator.original_object`` stores the instance of the
|
|
object being edited.
|
|
|
|
* We set ``new_data`` based upon ``flatten_data()`` from the manipulator.
|
|
``flatten_data()`` takes the data from the original object under
|
|
manipulation, and converts it into a data dictionary that can be used
|
|
to populate form elements with the existing values for the object.
|
|
|
|
* The above example uses a different template, so create and edit can be
|
|
"skinned" differently if needed, but the form chunk itself is completely
|
|
identical to the one in the create form above.
|
|
|
|
The astute programmer will notice the add and create functions are nearly
|
|
identical and could in fact be collapsed into a single view. This is left as an
|
|
exercise for said programmer.
|
|
|
|
(However, the even-more-astute programmer will take heed of the note at the top
|
|
of this document and check out the `generic views`_ documentation if all she
|
|
wishes to do is this type of simple create/update.)
|
|
|
|
Custom forms and manipulators
|
|
=============================
|
|
|
|
All the above is fine and dandy if you just want to use the automatically
|
|
created manipulators. But the coolness doesn't end there: You can easily create
|
|
your own custom manipulators for handling custom forms.
|
|
|
|
Custom manipulators are pretty simple. Here's a manipulator that you might use
|
|
for a "contact" form on a website::
|
|
|
|
from django import forms
|
|
|
|
urgency_choices = (
|
|
(1, "Extremely urgent"),
|
|
(2, "Urgent"),
|
|
(3, "Normal"),
|
|
(4, "Unimportant"),
|
|
)
|
|
|
|
class ContactManipulator(forms.Manipulator):
|
|
def __init__(self):
|
|
self.fields = (
|
|
forms.EmailField(field_name="from", is_required=True),
|
|
forms.TextField(field_name="subject", length=30, max_length=200, is_required=True),
|
|
forms.SelectField(field_name="urgency", choices=urgency_choices),
|
|
forms.LargeTextField(field_name="contents", is_required=True),
|
|
)
|
|
|
|
A certain similarity to Django's models should be apparent. The only required
|
|
method of a custom manipulator is ``__init__`` which must define the fields
|
|
present in the manipulator. See the ``django.forms`` module for
|
|
all the form fields provided by Django.
|
|
|
|
You use this custom manipulator exactly as you would use an auto-generated one.
|
|
Here's a simple function that might drive the above form::
|
|
|
|
def contact_form(request):
|
|
manipulator = ContactManipulator()
|
|
if request.method == 'POST':
|
|
new_data = request.POST.copy()
|
|
errors = manipulator.get_validation_errors(new_data)
|
|
manipulator.do_html2python(new_data)
|
|
if not errors:
|
|
|
|
# Send e-mail using new_data here...
|
|
|
|
return HttpResponseRedirect("/contact/thankyou/")
|
|
else:
|
|
errors = new_data = {}
|
|
form = forms.FormWrapper(manipulator, new_data, errors)
|
|
return render_to_response('contact_form.html', {'form': form})
|
|
|
|
Implementing ``flatten_data`` for custom manipulators
|
|
------------------------------------------------------
|
|
|
|
It is possible (although rarely needed) to replace the default automatically
|
|
created manipulators on a model with your own custom manipulators. If you do
|
|
this and you are intending to use those models in generic views, you should
|
|
also define a ``flatten_data`` method in any ``ChangeManipulator`` replacement.
|
|
This should act like the default ``flatten_data`` and return a dictionary
|
|
mapping field names to their values, like so::
|
|
|
|
def flatten_data(self):
|
|
obj = self.original_object
|
|
return dict(
|
|
from = obj.from,
|
|
subject = obj.subject,
|
|
...
|
|
)
|
|
|
|
In this way, your new change manipulator will act exactly like the default
|
|
version.
|
|
|
|
``FileField`` and ``ImageField`` special cases
|
|
==============================================
|
|
|
|
Dealing with ``FileField`` and ``ImageField`` objects is a little more
|
|
complicated.
|
|
|
|
First, you'll need to make sure that your ``<form>`` element correctly defines
|
|
the ``enctype`` as ``"multipart/form-data"``, in order to upload files::
|
|
|
|
<form enctype="multipart/form-data" method="post" action="/foo/">
|
|
|
|
Next, you'll need to treat the field in the template slightly differently. A
|
|
``FileField`` or ``ImageField`` is represented by *two* HTML form elements.
|
|
|
|
For example, given this field in a model::
|
|
|
|
photo = model.ImageField('/path/to/upload/location')
|
|
|
|
You'd need to display two formfields in the template::
|
|
|
|
<p><label for="id_photo">Photo:</label> {{ form.photo }}{{ form.photo_file }}</p>
|
|
|
|
The first bit (``{{ form.photo }}``) displays the currently-selected file,
|
|
while the second (``{{ form.photo_file }}``) actually contains the file upload
|
|
form field. Thus, at the validation layer you need to check the ``photo_file``
|
|
key.
|
|
|
|
Finally, in your view, make sure to access ``request.FILES``, rather than
|
|
``request.POST``, for the uploaded files. This is necessary because
|
|
``request.POST`` does not contain file-upload data.
|
|
|
|
For example, following the ``new_data`` convention, you might do something like
|
|
this::
|
|
|
|
new_data = request.POST.copy()
|
|
new_data.update(request.FILES)
|
|
|
|
Validators
|
|
==========
|
|
|
|
One useful feature of manipulators is the automatic validation. Validation is
|
|
done using a simple validation API: A validator is a callable that raises a
|
|
``ValidationError`` if there's something wrong with the data.
|
|
``django.core.validators`` defines a host of validator functions (see below),
|
|
but defining your own couldn't be easier::
|
|
|
|
from django.core import validators
|
|
from django import forms
|
|
|
|
class ContactManipulator(forms.Manipulator):
|
|
def __init__(self):
|
|
self.fields = (
|
|
# ... snip fields as above ...
|
|
forms.EmailField(field_name="to", validator_list=[self.isValidToAddress])
|
|
)
|
|
|
|
def isValidToAddress(self, field_data, all_data):
|
|
if not field_data.endswith("@example.com"):
|
|
raise validators.ValidationError("You can only send messages to example.com e-mail addresses.")
|
|
|
|
Above, we've added a "to" field to the contact form, but required that the "to"
|
|
address end with "@example.com" by adding the ``isValidToAddress`` validator to
|
|
the field's ``validator_list``.
|
|
|
|
The arguments to a validator function take a little explanation. ``field_data``
|
|
is the value of the field in question, and ``all_data`` is a dictionary of all
|
|
the data being validated.
|
|
|
|
.. admonition:: Note::
|
|
|
|
At the point validators are called all data will still be
|
|
strings (as ``do_html2python`` hasn't been called yet).
|
|
|
|
Also, because consistency in user interfaces is important, we strongly urge you
|
|
to put punctuation at the end of your validation messages.
|
|
|
|
When are validators called?
|
|
---------------------------
|
|
|
|
After a form has been submitted, Django validates each field in turn. First,
|
|
if the field is required, Django checks that it is present and non-empty. Then,
|
|
if that test passes *and the form submission contained data* for that field, all
|
|
the validators for that field are called in turn. The emphasized portion in the
|
|
last sentence is important: if a form field is not submitted (because it
|
|
contains no data -- which is normal HTML behavior), the validators are not
|
|
run against the field.
|
|
|
|
This feature is particularly important for models using
|
|
``models.BooleanField`` or custom manipulators using things like
|
|
``forms.CheckBoxField``. If the checkbox is not selected, it will not
|
|
contribute to the form submission.
|
|
|
|
If you would like your validator to run *always*, regardless of whether its
|
|
attached field contains any data, set the ``always_test`` attribute on the
|
|
validator function. For example::
|
|
|
|
def my_custom_validator(field_data, all_data):
|
|
# ...
|
|
my_custom_validator.always_test = True
|
|
|
|
This validator will always be executed for any field it is attached to.
|
|
|
|
Ready-made validators
|
|
---------------------
|
|
|
|
Writing your own validator is not difficult, but there are some situations
|
|
that come up over and over again. Django comes with a number of validators
|
|
that can be used directly in your code. All of these functions and classes
|
|
reside in ``django/core/validators.py``.
|
|
|
|
The following validators should all be self-explanatory. Each one provides a
|
|
check for the given property:
|
|
|
|
* isAlphaNumeric
|
|
* isAlphaNumericURL
|
|
* isSlug
|
|
* isLowerCase
|
|
* isUpperCase
|
|
* isCommaSeparatedIntegerList
|
|
* isCommaSeparatedEmailList
|
|
* isValidIPAddress4
|
|
* isNotEmpty
|
|
* isOnlyDigits
|
|
* isNotOnlyDigits
|
|
* isInteger
|
|
* isOnlyLetters
|
|
* isValidANSIDate
|
|
* isValidANSITime
|
|
* isValidEmail
|
|
* isValidFloat
|
|
* isValidImage
|
|
* isValidImageURL
|
|
* isValidPhone
|
|
* isValidQuicktimeVideoURL
|
|
* isValidURL
|
|
* isValidHTML
|
|
* isWellFormedXml
|
|
* isWellFormedXmlFragment
|
|
* isExistingURL
|
|
* isValidUSState
|
|
* hasNoProfanities
|
|
|
|
There are also a group of validators that are slightly more flexible. For
|
|
these validators, you create a validator instance, passing in the parameters
|
|
described below. The returned object is a callable that can be used as a
|
|
validator.
|
|
|
|
For example::
|
|
|
|
from django.core import validators
|
|
from django import forms
|
|
|
|
power_validator = validators.IsAPowerOf(2)
|
|
|
|
class InstallationManipulator(forms.Manipulator)
|
|
def __init__(self):
|
|
self.fields = (
|
|
...
|
|
forms.IntegerField(field_name = "size", validator_list=[power_validator])
|
|
)
|
|
|
|
Here, ``validators.IsAPowerOf(...)`` returned something that could be used as
|
|
a validator (in this case, a check that a number was a power of 2).
|
|
|
|
Each of the standard validators that take parameters have an optional final
|
|
argument (``error_message``) that is the message returned when validation
|
|
fails. If no message is passed in, a default message is used.
|
|
|
|
``AlwaysMatchesOtherField``
|
|
Takes a field name and the current field is valid if and only if its value
|
|
matches the contents of the other field.
|
|
|
|
``ValidateIfOtherFieldEquals``
|
|
Takes three parameters: ``other_field``, ``other_value`` and
|
|
``validator_list``, in that order. If ``other_field`` has a value of
|
|
``other_value``, then the validators in ``validator_list`` are all run
|
|
against the current field.
|
|
|
|
``RequiredIfOtherFieldGiven``
|
|
Takes a field name of the current field is only required if the other
|
|
field has a value.
|
|
|
|
``RequiredIfOtherFieldsGiven``
|
|
Similar to ``RequiredIfOtherFieldGiven``, except that it takes a list of
|
|
field names and if any one of the supplied fields has a value provided,
|
|
the current field being validated is required.
|
|
|
|
``RequiredIfOtherFieldNotGiven``
|
|
Takes the name of the other field and this field is only required if the
|
|
other field has no value.
|
|
|
|
``RequiredIfOtherFieldEquals`` and ``RequiredIfOtherFieldDoesNotEqual``
|
|
Each of these validator classes takes a field name and a value (in that
|
|
order). If the given field does (or does not have, in the latter case) the
|
|
given value, then the current field being validated is required.
|
|
|
|
An optional ``other_label`` argument can be passed which, if given, is used
|
|
in error messages instead of the value. This allows more user friendly error
|
|
messages if the value itself is not descriptive enough.
|
|
|
|
Note that because validators are called before any ``do_html2python()``
|
|
functions, the value being compared against is a string. So
|
|
``RequiredIfOtherFieldEquals('choice', '1')`` is correct, whilst
|
|
``RequiredIfOtherFieldEquals('choice', 1)`` will never result in the
|
|
equality test succeeding.
|
|
|
|
``IsLessThanOtherField``
|
|
Takes a field name and validates that the current field being validated
|
|
has a value that is less than (or equal to) the other field's value.
|
|
Again, comparisons are done using strings, so be cautious about using
|
|
this function to compare data that should be treated as another type. The
|
|
string "123" is less than the string "2", for example. If you don't want
|
|
string comparison here, you will need to write your own validator.
|
|
|
|
``NumberIsInRange``
|
|
Takes two boundary numbers, ``lower`` and ``upper``, and checks that the
|
|
field is greater than ``lower`` (if given) and less than ``upper`` (if
|
|
given).
|
|
|
|
Both checks are inclusive. That is, ``NumberIsInRange(10, 20)`` will allow
|
|
values of both 10 and 20. This validator only checks numeric values
|
|
(e.g., float and integer values).
|
|
|
|
``IsAPowerOf``
|
|
Takes an integer argument and when called as a validator, checks that the
|
|
field being validated is a power of the integer.
|
|
|
|
``IsValidDecimal``
|
|
Takes a maximum number of digits and number of decimal places (in that
|
|
order) and validates whether the field is a decimal with no more than the
|
|
maximum number of digits and decimal places.
|
|
|
|
``MatchesRegularExpression``
|
|
Takes a regular expression (a string) as a parameter and validates the
|
|
field value against it.
|
|
|
|
``AnyValidator``
|
|
Takes a list of validators as a parameter. At validation time, if the
|
|
field successfully validates against any one of the validators, it passes
|
|
validation. The validators are tested in the order specified in the
|
|
original list.
|
|
|
|
``URLMimeTypeCheck``
|
|
Used to validate URL fields. Takes a list of MIME types (such as
|
|
``text/plain``) at creation time. At validation time, it verifies that the
|
|
field is indeed a URL and then tries to retrieve the content at the URL.
|
|
Validation succeeds if the content could be retrieved and it has a content
|
|
type from the list used to create the validator.
|
|
|
|
``RelaxNGCompact``
|
|
Used to validate an XML document against a Relax NG compact schema. Takes
|
|
a file path to the location of the schema and an optional root element
|
|
(which is wrapped around the XML fragment before validation, if supplied).
|
|
At validation time, the XML fragment is validated against the schema using
|
|
the executable specified in the ``JING_PATH`` setting (see the settings_
|
|
document for more details).
|
|
|
|
.. _`generic views`: ../generic_views/
|
|
.. _`models API`: ../model-api/
|
|
.. _settings: ../settings/
|