1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

Merged revisions 4350-4357,4359-4365,4371-4372,4374-4377,4380-4386,4388,4390-4391,4400-4402,4404-4408,4410,4412-4419,4426-4427,4430-4432,4434,4441,4443-4444,4446-4447,4450,4452-4453,4455-4458,4476,4503,4546,4564-4569,4580-4586,4617,4630,4641-4643,4653-4655,4657,4669,4673-4675,4694-4696,4713-4714,4720-4723,4725-4732,4735-4741,4750,4755,4758,4769-4770,4776-4777,4783-4795,4798,4805-4808,4810,4813-4815,4817,4824,4836,4838-4843,4851-4855,4869,4872,4882-4884,4906,4916,4935-4936,4940-4944,4946-4953,4962-4963,4969,4971-4973,4990,4994-4997,5000-5003,5006-5008,5013-5014,5019-5024,5026-5036,5046-5047,5054-5059,5062,5079,5081-5083,5090,5100-5101,5114,5122-5123,5126,5128,5134-5136,5148-5149,5151,5157,5174,5178,5183-5185,5192-5195,5197-5200,5203,5205,5208,5214,5223-5224,5226-5227,5229-5230,5235-5236,5238-5244,5246-5249,5251,5254-5262,5266-5280,5282-5284,5286,5301,5307,5309-5310,5312,5314-5317,5319-5332,5334-5345,5372-5378,5381-5382,5384,5386,5388-5390,5393-5397,5399-5400,5416,5419-5430,5440-5441,5444-5448,5461-5464,5467,5473-5481,5487-5489,5491-5492,5498-5499,5507-5510,5512,5527,5529,5531-5535,5540-5541,5546,5570,5572-5574,5576-5578,5580-5581,5583-5589,5591,5595-5597,5601-5608,5613,5626-5826 via svnmerge from

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
This commit is contained in:
Russell Keith-Magee 2007-08-07 13:43:49 +00:00
parent a704a38292
commit 83861364dd
221 changed files with 11278 additions and 8246 deletions

19
AUTHORS
View File

@ -57,10 +57,12 @@ answer newbie questions, and generally made Django that much better:
Ned Batchelder <http://www.nedbatchelder.com/>
Shannon -jj Behrens <http://jjinux.blogspot.com/>
Esdras Beleza <linux@esdrasbeleza.com>
Chris Bennett <chrisrbennett@yahoo.com>
James Bennett
Ben <afternoon@uk2.net>
Paul Bissex <http://e-scribe.com/>
Simon Blanchard
Matt Boersma <ogghead@gmail.com>
boobsd@gmail.com
Andrew Brehaut <http://brehaut.net/blog>
brut.alll@gmail.com
@ -94,10 +96,12 @@ answer newbie questions, and generally made Django that much better:
Maximillian Dornseif <md@hudora.de>
Jeremy Dunck <http://dunck.us/>
Andrew Durdin <adurdin@gmail.com>
dusk@woofle.net
Andy Dustman <farcepest@gmail.com>
Clint Ecker
enlight
Enrico <rico.bl@gmail.com>
A. Murat Eren <meren@pardus.org.tr>
Ludvig Ericson <ludvig.ericson@gmail.com>
Dirk Eschler <dirk.eschler@gmx.net>
Marc Fargas <telenieko@telenieko.com>
@ -114,7 +118,7 @@ answer newbie questions, and generally made Django that much better:
glin@seznam.cz
martin.glueck@gmail.com
GomoX <gomo@datafull.com>
Mario Gonzalez <gonzalemario @t gmail.com>
Mario Gonzalez <gonzalemario@gmail.com>
Simon Greenhill <dev@simon.net.nz>
Owen Griffiths
Espen Grindhaug <http://grindhaug.org/>
@ -141,7 +145,8 @@ answer newbie questions, and generally made Django that much better:
junzhang.jn@gmail.com
Antti Kaihola <http://akaihola.blogspot.com/>
Ben Dean Kawamura <ben.dean.kawamura@gmail.com>
ian.g.kelly@gmail.com
Ian G. Kelly <ian.g.kelly@gmail.com>
Ben Khoo <khoobks@westnet.com.au>
Garth Kidd <http://www.deadlybloodyserious.com/>
kilian <kilian.cavalotti@lip6.fr>
Sune Kirkeby <http://ibofobi.dk/>
@ -153,6 +158,7 @@ answer newbie questions, and generally made Django that much better:
Martin Kosír <martin@martinkosir.net>
Meir Kriheli <http://mksoft.co.il/>
Bruce Kroeze <http://coderseye.com/>
krzysiek.pawlik@silvermedia.pl
Joseph Kocherhans
konrad@gwu.edu
kurtiss@meetro.com
@ -167,13 +173,14 @@ answer newbie questions, and generally made Django that much better:
lerouxb@gmail.com
Waylan Limberg <waylan@gmail.com>
limodou
Philip Lindborg <philip.lindborg@gmail.com>
Matt McClanahan <http://mmcc.cx/>
Martin Maney <http://www.chipy.org/Martin_Maney>
masonsimon+django@gmail.com
Manuzhai
Petar Marić <http://www.petarmaric.com/>
Nuno Mariz <nmariz@gmail.com>
marijn@metronomo.cl
Marijn Vriens <marijn@metronomo.cl>
mark@junklight.com
Yasushi Masuda <whosaysni@gmail.com>
mattycakes@gmail.com
@ -183,6 +190,7 @@ answer newbie questions, and generally made Django that much better:
mikko@sorl.net
mitakummaa@gmail.com
mmarshall
Andreas Mock <andreas.mock@web.de>
Reza Mohammadi <reza@zeerak.ir>
Eric Moritz <http://eric.themoritzfamily.com/>
mrmachine <real.human@mrmachine.net>
@ -207,6 +215,7 @@ answer newbie questions, and generally made Django that much better:
plisk
Daniel Poelzleithner <http://poelzi.org/>
polpak@yahoo.com
Johann Queuniet <johann.queuniet@adh.naellia.eu>
J. Rademaker
Michael Radziej <mir@noris.de>
Ramiro Morales <rm0@gmx.net>
@ -216,12 +225,14 @@ answer newbie questions, and generally made Django that much better:
rhettg@gmail.com
Henrique Romano <onaiort@gmail.com>
Armin Ronacher
Brian Rosner <brosner@gmail.com>
Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
Vinay Sajip <vinay_sajip@yahoo.co.uk>
David Schein
scott@staplefish.com
serbaut@gmail.com
John Shaffer <jshaffer2112@gmail.com>
Pete Shinners <pete@shinners.org>
Jozko Skrablin <jozko.skrablin@gmail.com>
SmileyChris <smileychris@gmail.com>
@ -232,6 +243,8 @@ answer newbie questions, and generally made Django that much better:
Vasiliy Stavenko <stavenko@gmail.com>
Thomas Steinacher <http://www.eggdrop.ch/>
nowell strite
Sundance
SuperJared
Radek Švarz <http://www.svarz.cz/translate/>
Swaroop C H <http://www.swaroopch.info>
Aaron Swartz <http://www.aaronsw.com/>

View File

@ -9,6 +9,7 @@ import re
import os
import sys
import getopt
from itertools import dropwhile
pythonize_re = re.compile(r'\n\s*//')
@ -103,8 +104,8 @@ def make_messages():
open(os.path.join(dirpath, '%s.py' % file), "wb").write(templatize(src))
thefile = '%s.py' % file
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
msgs = stdout.read()
errors = stderr.read()
@ -116,13 +117,18 @@ def make_messages():
old = '#: '+os.path.join(dirpath, thefile)[2:]
new = '#: '+os.path.join(dirpath, file)[2:]
msgs = msgs.replace(old, new)
if os.path.exists(potfile):
# Strip the header
msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
else:
msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
if msgs:
open(potfile, 'ab').write(msgs)
if thefile != file:
os.unlink(os.path.join(dirpath, thefile))
if os.path.exists(potfile):
(stdin, stdout, stderr) = os.popen3('msguniq "%s"' % potfile, 'b')
(stdin, stdout, stderr) = os.popen3('msguniq --to-code=utf-8 "%s"' % potfile, 'b')
msgs = stdout.read()
errors = stderr.read()
if errors:

View File

@ -37,6 +37,8 @@ class LazySettings(object):
# __setattr__(), which would be an infinite loop.
self.__dict__['_target'] = value
else:
if self._target is None:
self._import_settings()
setattr(self._target, name, value)
def _import_settings(self):

View File

@ -30,7 +30,6 @@ TIME_ZONE = 'America/Chicago'
# Language code for this installation. All choices can be found here:
# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
# http://blogs.law.harvard.edu/tech/stories/storyReader$15
LANGUAGE_CODE = 'en-us'
# Languages we provide translations for, out of the box. The language name

View File

@ -11,21 +11,21 @@ msgstr ""
"PO-Revision-Date: 2005-12-04 13:21+0100\n"
"Last-Translator: Dirk Eschler <dirk.eschler@gmx.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Verfügbare %s"
msgstr "Verfügbare %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Alles auswählen"
msgstr "Alles auswählen"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Hinzufügen"
msgstr "Hinzufügen"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
@ -34,15 +34,15 @@ msgstr "Entfernen"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Ausgewählte %s"
msgstr "Ausgewählte %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Gewünschte Auswahl treffen und "
msgstr "Gewünschte Auswahl treffen und "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Alles abwählen"
msgstr "Alles abwählen"
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
@ -50,7 +50,7 @@ msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Januar Februar März April Mai Juni Juli August September Oktober November "
"Januar Februar März April Mai Juni Juli August September Oktober November "
"Dezember"
#: contrib/admin/media/js/dateparse.js:27

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +1,41 @@
# Spanish translation for the django-admin JS files.
# Copyright (C)
# This file is distributed under the same license as the PACKAGE package.
# Jorge Gajon <gajon@gajon.org>, 2005.
#
msgid ""
msgstr ""
"Project-Id-Version: Django JavaScript 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2005-12-06 21:32+0100\n"
"POT-Creation-Date: 2007-07-14 13:47-0500\n"
"PO-Revision-Date: 2007-07-14 13:41-0500\n"
"Last-Translator: Jorge Gajon <gajon@gajon.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/calendar.js:24
#: contrib/admin/media/js/dateparse.js:32
msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre "
"Noviembre Diciembre"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "D L M M J V S"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Domingo Lunes Martes Miércoles Jueves Viernes Sábado"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "%s Disponibles"
#: contrib/admin/media/js/SelectFilter2.js:41
#, fuzzy
msgid "Choose all"
msgstr "Selecciona todos"
@ -45,66 +60,58 @@ msgstr "Haz tus elecciones y da click en "
msgid "Clear all"
msgstr "Elimina todos"
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre "
"Noviembre Diciembre"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Domingo Lunes Martes Miércoles Jueves Viernes Sábado"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "D L M M J V S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr "Ahora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "Reloj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "Elige una hora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "Medianoche"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Mediodía"
msgstr "Mediodía"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr "Cancelar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "Hoy"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "Calendario"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "Ayer"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Mañana"
msgstr "Mañana"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr "Mostrar"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr "Esconder"

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,17 @@
# Argentinean spanish translation for the django-admin JS files, based on
# Spanish translation work by Jorge Gajon.
# This file is distributed under the same license as the Django package.
# Copyright (C) Ramiro Morales <rm0@gmx.net>, 2006,2007.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR
#
msgid ""
msgstr ""
"Project-Id-Version: Django JavaScript 1.0\n"
"Project-Id-Version: Django Javascript 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-02-25 17:48-0300\n"
"PO-Revision-Date: 2007-02-25 17:55-0300\n"
"POT-Creation-Date: 2007-07-14 13:45-0300\n"
"PO-Revision-Date: 2007-07-14 14:36-0300\n"
"Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
"Language-Team: Django-I18N <django-i18n@googlegroups.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
@ -55,7 +55,7 @@ msgstr ""
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Domingo Lunes Martes Miércoles Jueves Viernes Sábado"
msgstr "Domingo Lunes Martes Miércoles Jueves Viernes Sábado"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
@ -93,7 +93,7 @@ msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Mediodía"
msgstr "Mediodía"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
@ -115,4 +115,4 @@ msgstr "Ayer"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Mañana"
msgstr "Mañana"

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
# French translation for js.
# Copyright (C) 2005 Mikaël Barbero
# Copyright (C) 2005 Mikaël Barbero
# This file is distributed under the same license as the PACKAGE package.
# Mikaël Barbero <mikael.barbero nospam at nospam free.fr>, 2005.
# Mikaël Barbero <mikael.barbero nospam at nospam free.fr>, 2005.
#
msgid ""
msgstr ""
@ -9,10 +9,10 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-24 16:39+0100\n"
"PO-Revision-Date: 2005-12-24 16:39+0100\n"
"Last-Translator: Mikaël Barbero <mikael.barbero nospam at nospam free.fr>\n"
"Last-Translator: Mikaël Barbero <mikael.barbero nospam at nospam free.fr>\n"
"Language-Team: French <fr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/calendar.js:24
@ -21,8 +21,8 @@ msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Janvier Février Mars Avril Mai Juin Juillet Août Septembre Octobre Novembre "
"Décembre"
"Janvier Février Mars Avril Mai Juin Juillet Août Septembre Octobre Novembre "
"Décembre"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
@ -56,7 +56,7 @@ msgstr "Choisi %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Sélectionnez un ou plusieurs choix et cliquez "
msgstr "Sélectionnez un ou plusieurs choix et cliquez "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,6 @@ TIME_ZONE = 'America/Chicago'
# Language code for this installation. All choices can be found here:
# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
# http://blogs.law.harvard.edu/tech/stories/storyReader$15
LANGUAGE_CODE = 'en-us'
SITE_ID = 1

View File

@ -31,10 +31,11 @@ function showAddAnotherPopup(triggeringLink) {
var name = triggeringLink.id.replace(/^add_/, '');
name = name.replace(/\./g, '___');
href = triggeringLink.href
if (href.indexOf('?') == -1)
href += '?_popup=1';
else
href += '&_popup=1';
if (href.indexOf('?') == -1) {
href += '?_popup=1';
} else {
href += '&_popup=1';
}
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;

View File

@ -2,12 +2,12 @@ var LATIN_MAP = {
'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ý': 'Y', 'Þ': 'TH',
'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ':
'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i',
'î': 'i', 'ï': 'i', 'ð': 'o', 'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ':
'o', 'ö': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u', 'ý': 'y',
'þ': 'th', 'ÿ': 'y'
'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä':
'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'o', 'ñ': 'n', 'ò': 'o', 'ó':
'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', ': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u',
'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
}
var LATIN_SYMBOLS_MAP = {
'©':'(c)'

View File

@ -18,7 +18,7 @@ class LogEntry(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType, blank=True, null=True)
object_id = models.TextField(_('object id'), blank=True, null=True)
object_repr = models.CharField(_('object repr'), maxlength=200)
object_repr = models.CharField(_('object repr'), max_length=200)
action_flag = models.PositiveSmallIntegerField(_('action flag'))
change_message = models.TextField(_('change message'), blank=True)
objects = LogEntryManager()

View File

@ -190,9 +190,11 @@ def items_for_result(cl, result):
table_tag = {True:'th', False:'td'}[first]
first = False
url = cl.url_for_result(result)
result_id = smart_unicode(getattr(result, pk)) # conversion to string is needed in case of 23L (long ints)
# Convert the pk to something that can be used in Javascript.
# Problem cases are long ints (23L) and non-ASCII strings.
result_id = repr(force_unicode(getattr(result, pk)))[1:]
yield (u'<%s%s><a href="%s"%s>%s</a></%s>' % \
(table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr, table_tag))
(table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %s); return false;"' % result_id or ''), result_repr, table_tag))
else:
yield (u'<td%s>%s</td>' % (row_class, result_repr))

View File

@ -362,7 +362,7 @@ class ChangeList(object):
try:
attr = getattr(self.model, field_name)
order_field = attr.admin_order_field
except IndexError:
except AttributeError:
pass
else:
if not isinstance(f.rel, models.ManyToOneRel) or not f.null:

View File

@ -12,6 +12,8 @@ def load_backend(path):
mod = __import__(module, {}, {}, [attr])
except ImportError, e:
raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e)
except ValueError, e:
raise ImproperlyConfigured, 'Error importing authentication backends. Is AUTHENTICATION_BACKENDS a correctly defined list or tuple?'
try:
cls = getattr(mod, attr)
except AttributeError:

View File

@ -10,10 +10,10 @@ class UserCreationForm(oldforms.Manipulator):
"A form that creates a user, with no privileges, from the given username and password."
def __init__(self):
self.fields = (
oldforms.TextField(field_name='username', length=30, maxlength=30, is_required=True,
oldforms.TextField(field_name='username', length=30, max_length=30, is_required=True,
validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
oldforms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
)
@ -42,9 +42,9 @@ class AuthenticationForm(oldforms.Manipulator):
"""
self.request = request
self.fields = [
oldforms.TextField(field_name="username", length=15, maxlength=30, is_required=True,
oldforms.TextField(field_name="username", length=15, max_length=30, is_required=True,
validator_list=[self.isValidUser, self.hasCookiesEnabled]),
oldforms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True),
oldforms.PasswordField(field_name="password", length=15, max_length=30, is_required=True),
]
self.user_cache = None
@ -111,11 +111,11 @@ class PasswordChangeForm(oldforms.Manipulator):
def __init__(self, user):
self.user = user
self.fields = (
oldforms.PasswordField(field_name="old_password", length=30, maxlength=30, is_required=True,
oldforms.PasswordField(field_name="old_password", length=30, max_length=30, is_required=True,
validator_list=[self.isValidOldPassword]),
oldforms.PasswordField(field_name="new_password1", length=30, maxlength=30, is_required=True,
oldforms.PasswordField(field_name="new_password1", length=30, max_length=30, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]),
oldforms.PasswordField(field_name="new_password2", length=30, maxlength=30, is_required=True),
oldforms.PasswordField(field_name="new_password2", length=30, max_length=30, is_required=True),
)
def isValidOldPassword(self, new_data, all_data):
@ -133,8 +133,8 @@ class AdminPasswordChangeForm(oldforms.Manipulator):
def __init__(self, user):
self.user = user
self.fields = (
oldforms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
)

View File

@ -7,6 +7,8 @@ from django.utils.translation import ugettext_lazy as _
import datetime
import urllib
UNUSABLE_PASSWORD = '!' # This will never be a valid hash
try:
set
except NameError:
@ -48,9 +50,9 @@ class Permission(models.Model):
Three basic permissions -- add, change and delete -- are automatically created for each Django model.
"""
name = models.CharField(_('name'), maxlength=50)
name = models.CharField(_('name'), max_length=50)
content_type = models.ForeignKey(ContentType)
codename = models.CharField(_('codename'), maxlength=100)
codename = models.CharField(_('codename'), max_length=100)
class Meta:
verbose_name = _('permission')
@ -68,7 +70,7 @@ class Group(models.Model):
Beyond permissions, groups are a convenient way to categorize users to apply some label, or extended functionality, to them. For example, you could create a group 'Special users', and you could write code that would do special things to those users -- such as giving them access to a members-only portion of your site, or sending them members-only e-mail messages.
"""
name = models.CharField(_('name'), maxlength=80, unique=True)
name = models.CharField(_('name'), max_length=80, unique=True)
permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True)
class Meta:
@ -80,11 +82,14 @@ class Group(models.Model):
return self.name
class UserManager(models.Manager):
def create_user(self, username, email, password):
def create_user(self, username, email, password=None):
"Creates and saves a User with the given username, e-mail and password."
now = datetime.datetime.now()
user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
user.set_password(password)
if password:
user.set_password(password)
else:
user.set_unusable_password()
user.save()
return user
@ -100,11 +105,11 @@ class User(models.Model):
Username and password are required. Other fields are optional.
"""
username = models.CharField(_('username'), maxlength=30, unique=True, validator_list=[validators.isAlphaNumeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
first_name = models.CharField(_('first name'), maxlength=30, blank=True)
last_name = models.CharField(_('last name'), maxlength=30, blank=True)
username = models.CharField(_('username'), max_length=30, unique=True, validator_list=[validators.isAlphaNumeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('e-mail address'), blank=True)
password = models.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts."))
is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
@ -164,6 +169,13 @@ class User(models.Model):
return is_correct
return check_password(raw_password, self.password)
def set_unusable_password(self):
# Sets a value that will never be a valid hash
self.password = UNUSABLE_PASSWORD
def has_usable_password(self):
return self.password != UNUSABLE_PASSWORD
def get_group_permissions(self):
"Returns a list of permission strings that this user has through his/her groups."
if not hasattr(self, '_group_perm_cache'):
@ -253,7 +265,8 @@ class User(models.Model):
return self._profile_cache
class Message(models.Model):
"""The message system is a lightweight way to queue messages for given users. A message is associated with a User instance (so it is only applicable for registered users). There's no concept of expiration or timestamps. Messages are created by the Django admin after successful actions. For example, "The poll Foo was created successfully." is a message.
"""
The message system is a lightweight way to queue messages for given users. A message is associated with a User instance (so it is only applicable for registered users). There's no concept of expiration or timestamps. Messages are created by the Django admin after successful actions. For example, "The poll Foo was created successfully." is a message.
"""
user = models.ForeignKey(User)
message = models.TextField(_('message'))

View File

@ -0,0 +1,19 @@
"""
>>> from models import User
>>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
>>> u.has_usable_password()
True
>>> u.check_password('bad')
False
>>> u.check_password('testpw')
True
>>> u.set_unusable_password()
>>> u.save()
>>> u.check_password('testpw')
False
>>> u.has_usable_password()
False
>>> u2 = User.objects.create_user('testuser2', 'test2@example.com')
>>> u2.has_usable_password()
False
"""

View File

@ -65,8 +65,8 @@ class Comment(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.IntegerField(_('object ID'))
headline = models.CharField(_('headline'), maxlength=255, blank=True)
comment = models.TextField(_('comment'), maxlength=3000)
headline = models.CharField(_('headline'), max_length=255, blank=True)
comment = models.TextField(_('comment'), max_length=3000)
rating1 = models.PositiveSmallIntegerField(_('rating #1'), blank=True, null=True)
rating2 = models.PositiveSmallIntegerField(_('rating #2'), blank=True, null=True)
rating3 = models.PositiveSmallIntegerField(_('rating #3'), blank=True, null=True)
@ -154,8 +154,8 @@ class FreeComment(models.Model):
# A FreeComment is a comment by a non-registered user.
content_type = models.ForeignKey(ContentType)
object_id = models.IntegerField(_('object ID'))
comment = models.TextField(_('comment'), maxlength=3000)
person_name = models.CharField(_("person's name"), maxlength=50)
comment = models.TextField(_('comment'), max_length=3000)
person_name = models.CharField(_("person's name"), max_length=50)
submit_date = models.DateTimeField(_('date/time submitted'), auto_now_add=True)
is_public = models.BooleanField(_('is public'))
ip_address = models.IPAddressField(_('ip address'))

View File

@ -5,6 +5,7 @@ from django import template
from django.template import loader
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import smart_str
import re
register = template.Library()
@ -174,6 +175,7 @@ class DoCommentForm:
if tokens[4] != 'with':
raise template.TemplateSyntaxError, "Fourth argument in %r tag must be 'with'" % tokens[0]
for option, args in zip(tokens[5::2], tokens[6::2]):
option = smart_str(option)
if option in ('photos_optional', 'photos_required') and not self.free:
# VALIDATION ##############################################
option_list = args.split(',')

View File

@ -29,7 +29,7 @@ class PublicCommentManipulator(AuthenticationForm):
else:
return []
self.fields.extend([
oldforms.LargeTextField(field_name="comment", maxlength=3000, is_required=True,
oldforms.LargeTextField(field_name="comment", max_length=3000, is_required=True,
validator_list=[self.hasNoProfanities]),
oldforms.RadioSelectField(field_name="rating1", choices=choices,
is_required=ratings_required and num_rating_choices > 0,
@ -122,9 +122,9 @@ class PublicFreeCommentManipulator(oldforms.Manipulator):
"Manipulator that handles public free (unregistered) comments"
def __init__(self):
self.fields = (
oldforms.TextField(field_name="person_name", maxlength=50, is_required=True,
oldforms.TextField(field_name="person_name", max_length=50, is_required=True,
validator_list=[self.hasNoProfanities]),
oldforms.LargeTextField(field_name="comment", maxlength=3000, is_required=True,
oldforms.LargeTextField(field_name="comment", max_length=3000, is_required=True,
validator_list=[self.hasNoProfanities]),
)

View File

@ -32,9 +32,9 @@ class ContentTypeManager(models.Manager):
CONTENT_TYPE_CACHE = {}
class ContentType(models.Model):
name = models.CharField(maxlength=100)
app_label = models.CharField(maxlength=100)
model = models.CharField(_('python model class name'), maxlength=100)
name = models.CharField(max_length=100)
app_label = models.CharField(max_length=100)
model = models.CharField(_('python model class name'), max_length=100)
objects = ContentTypeManager()
class Meta:
verbose_name = _('content type')

View File

@ -37,9 +37,10 @@ class FieldChoicePlugin(DatabrowsePlugin):
def urls(self, plugin_name, easy_instance_field):
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
field_value = smart_str(easy_instance_field.raw_value)
return [u'%s%s/%s/%s/' % (easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name,
urllib.quote(smart_str(easy_instance_field.raw_value)))]
urllib.quote(field_value, safe=''))]
def model_view(self, request, model_databrowse, url):
self.model, self.site = model_databrowse.model, model_databrowse.site

View File

@ -10,7 +10,7 @@
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -10,7 +10,7 @@
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -10,7 +10,7 @@
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -10,7 +10,7 @@
<ul class="objectlist">
{% for choice in field.choices %}
<li class="{% cycle odd,even %}"><a href="{{ choice.url }}">{{ choice.label }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ choice.url }}">{{ choice.label|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -11,7 +11,7 @@
<h2><a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a></h2>
<p>
{% for object in model.sample_objects %}
<a href="{{ object.url }}">{{ object }}</a>,
<a href="{{ object.url }}">{{ object|escape }}</a>,
{% endfor %}
<a class="more" href="{{ model.url }}">More &rarr;</a>
</p>

View File

@ -12,7 +12,7 @@
<ul class="objectlist">
{% for object in model.objects %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -4,9 +4,9 @@
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ object.model.url }}">{{ object.model.verbose_name_plural|capfirst }}</a> / {{ object }}</div>
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ object.model.url }}">{{ object.model.verbose_name_plural|capfirst }}</a> / {{ object|escape }}</div>
<h1>{{ object.model.verbose_name|capfirst }}: {{ object }}</h1>
<h1>{{ object.model.verbose_name|capfirst }}: {{ object|escape }}</h1>
<table class="objectinfo">
{% for field in object.fields %}
@ -14,8 +14,8 @@
<th>{{ field.field.verbose_name|capfirst }}</th>
<td>
{% if field.urls %}
{% for urlvalue in field.urls %}
{% if urlvalue.1 %}<a href="{{ urlvalue.1 }}">{% endif %}{{ urlvalue.0 }}{% if urlvalue.1 %}</a>{% endif %}{% if not forloop.last %}, {% endif %}
{% for value, url in field.urls %}
{% if url %}<a href="{{ url }}">{% endif %}{{ value|escape }}{% if url %}</a>{% endif %}{% if not forloop.last %}, {% endif %}
{% endfor %}
{% else %}None{% endif %}
</td>
@ -29,7 +29,7 @@
{% if related_object.object_list %}
<ul class="objectlist">
{% for object in related_object.object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>
{% else %}

View File

@ -4,12 +4,12 @@ from django.contrib.sites.models import Site
from django.utils.translation import ugettext_lazy as _
class FlatPage(models.Model):
url = models.CharField(_('URL'), maxlength=100, validator_list=[validators.isAlphaNumericURL], db_index=True,
url = models.CharField(_('URL'), max_length=100, validator_list=[validators.isAlphaNumericURL], db_index=True,
help_text=_("Example: '/about/contact/'. Make sure to have leading and trailing slashes."))
title = models.CharField(_('title'), maxlength=200)
title = models.CharField(_('title'), max_length=200)
content = models.TextField(_('content'))
enable_comments = models.BooleanField(_('enable comments'))
template_name = models.CharField(_('template name'), maxlength=70, blank=True,
template_name = models.CharField(_('template name'), max_length=70, blank=True,
help_text=_("Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'."))
registration_required = models.BooleanField(_('registration required'), help_text=_("If this is checked, only logged-in users will be able to view the page."))
sites = models.ManyToManyField(Site)

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
"""
A list of Chilean regions as `choices` in a formfield.
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
REGION_CHOICES = (
('RM', u'Región Metropolitana de Santiago'),
('I', u'Región de Tarapacá'),
('II', u'Región de Antofagasta'),
('III', u'Región de Atacama'),
('IV', u'Región de Coquimbo'),
('V', u'Región de Valparaíso'),
('VI', u'Región del Libertador Bernardo O\'Higgins'),
('VII', u'Región del Maule'),
('VIII',u'Región del Bío Bío'),
('IX', u'Región de la Araucanía'),
('X', u'Región de los Lagos'),
('XI', u'Región de Aysén del General Carlos Ibáñez del Campo'),
('XII', u'Región de Magallanes y la Antártica Chilena'),
('XIV', u'Región de Los Ríos'),
('XV', u'Región de Arica-Parinacota'),
)

View File

@ -3,10 +3,20 @@ Chile specific form helpers.
"""
from django.newforms import ValidationError
from django.newforms.fields import RegexField, EMPTY_VALUES
from django.newforms.fields import RegexField, Select, EMPTY_VALUES
from django.utils.translation import ugettext
from django.utils.encoding import smart_unicode
class CLRegionSelect(Select):
"""
A Select widget that uses a list of Chilean Regions (Regiones)
as its choices.
"""
def __init__(self, attrs=None):
from cl_regions import REGION_CHOICES
super(CLRegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
class CLRutField(RegexField):
"""
Chilean "Rol Unico Tributario" (RUT) field. This is the Chilean national

View File

@ -1,4 +1,3 @@
# -*- coding: iso-8859-1 -*-
"""
Norwegian-specific Form helpers
"""
@ -66,7 +65,7 @@ class NOSocialSecurityNumber(Field):
weight_2 = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2, 1]
def multiply_reduce(aval, bval):
return sum((a * b) for (a, b) in zip(aval, bval))
return sum([(a * b) for (a, b) in zip(aval, bval)])
if multiply_reduce(digits, weight_1) % 11 != 0:
raise ValidationError(msg)

View File

@ -0,0 +1,41 @@
"""
Slovak-specific form helpers
"""
from django.newforms.fields import Select, RegexField
from django.utils.translation import ugettext
class SKRegionSelect(Select):
"""
A select widget widget with list of Slovak regions as choices.
"""
def __init__(self, attrs=None):
from sk_regions import REGION_CHOICES
super(SKRegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
class SKDistrictSelect(Select):
"""
A select widget with list of Slovak districts as choices.
"""
def __init__(self, attrs=None):
from sk_districts import DISTRICT_CHOICES
super(SKDistrictSelect, self).__init__(attrs, choices=DISTRICT_CHOICES)
class SKPostalCodeField(RegexField):
"""
A form field that validates its input as Slovak postal code.
Valid form is XXXXX or XXX XX, where X represents integer.
"""
def __init__(self, *args, **kwargs):
super(SKPostalCodeField, self).__init__(r'^\d{5}$|^\d{3} \d{2}$',
max_length=None, min_length=None,
error_message=ugettext(u'Enter a postal code in the format XXXXX or XXX XX.'),
*args, **kwargs)
def clean(self, value):
"""
Validates the input and returns a string that contains only numbers.
Returns an empty string for empty values.
"""
v = super(SKPostalCodeField, self).clean(value)
return v.replace(' ', '')

View File

@ -0,0 +1,87 @@
"""
Slovak districts according to http://sk.wikipedia.org/wiki/Administrat%C3%ADvne_%C4%8Dlenenie_Slovenska
"""
from django.utils.translation import ugettext_lazy as _
DISTRICT_CHOICES = (
('BB', _('Banska Bystrica')),
('BS', _('Banska Stiavnica')),
('BJ', _('Bardejov')),
('BN', _('Banovce nad Bebravou')),
('BR', _('Brezno')),
('BA1', _('Bratislava I')),
('BA2', _('Bratislava II')),
('BA3', _('Bratislava III')),
('BA4', _('Bratislava IV')),
('BA5', _('Bratislava V')),
('BY', _('Bytca')),
('CA', _('Cadca')),
('DT', _('Detva')),
('DK', _('Dolny Kubin')),
('DS', _('Dunajska Streda')),
('GA', _('Galanta')),
('GL', _('Gelnica')),
('HC', _('Hlohovec')),
('HE', _('Humenne')),
('IL', _('Ilava')),
('KK', _('Kezmarok')),
('KN', _('Komarno')),
('KE1', _('Kosice I')),
('KE2', _('Kosice II')),
('KE3', _('Kosice III')),
('KE4', _('Kosice IV')),
('KEO', _('Kosice - okolie')),
('KA', _('Krupina')),
('KM', _('Kysucke Nove Mesto')),
('LV', _('Levice')),
('LE', _('Levoca')),
('LM', _('Liptovsky Mikulas')),
('LC', _('Lucenec')),
('MA', _('Malacky')),
('MT', _('Martin')),
('ML', _('Medzilaborce')),
('MI', _('Michalovce')),
('MY', _('Myjava')),
('NO', _('Namestovo')),
('NR', _('Nitra')),
('NM', _('Nove Mesto nad Vahom')),
('NZ', _('Nove Zamky')),
('PE', _('Partizanske')),
('PK', _('Pezinok')),
('PN', _('Piestany')),
('PT', _('Poltar')),
('PP', _('Poprad')),
('PB', _('Povazska Bystrica')),
('PO', _('Presov')),
('PD', _('Prievidza')),
('PU', _('Puchov')),
('RA', _('Revuca')),
('RS', _('Rimavska Sobota')),
('RV', _('Roznava')),
('RK', _('Ruzomberok')),
('SB', _('Sabinov')),
('SC', _('Senec')),
('SE', _('Senica')),
('SI', _('Skalica')),
('SV', _('Snina')),
('SO', _('Sobrance')),
('SN', _('Spisska Nova Ves')),
('SL', _('Stara Lubovna')),
('SP', _('Stropkov')),
('SK', _('Svidnik')),
('SA', _('Sala')),
('TO', _('Topolcany')),
('TV', _('Trebisov')),
('TN', _('Trencin')),
('TT', _('Trnava')),
('TR', _('Turcianske Teplice')),
('TS', _('Tvrdosin')),
('VK', _('Velky Krtis')),
('VT', _('Vranov nad Toplou')),
('ZM', _('Zlate Moravce')),
('ZV', _('Zvolen')),
('ZC', _('Zarnovica')),
('ZH', _('Ziar nad Hronom')),
('ZA', _('Zilina')),
)

View File

@ -0,0 +1,16 @@
"""
Slovak regions according to http://sk.wikipedia.org/wiki/Administrat%C3%ADvne_%C4%8Dlenenie_Slovenska
"""
from django.utils.translation import ugettext_lazy as _
REGION_CHOICES = (
('BB', _('Banska Bystrica region')),
('BA', _('Bratislava region')),
('KE', _('Kosice region')),
('NR', _('Nitra region')),
('PO', _('Presov region')),
('TN', _('Trencin region')),
('TT', _('Trnava region')),
('ZA', _('Zilina region')),
)

View File

@ -4,9 +4,9 @@ from django.utils.translation import ugettext_lazy as _
class Redirect(models.Model):
site = models.ForeignKey(Site, radio_admin=models.VERTICAL)
old_path = models.CharField(_('redirect from'), maxlength=200, db_index=True,
old_path = models.CharField(_('redirect from'), max_length=200, db_index=True,
help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'."))
new_path = models.CharField(_('redirect to'), maxlength=200, blank=True,
new_path = models.CharField(_('redirect to'), max_length=200, blank=True,
help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'."))
class Meta:

View File

@ -2,7 +2,9 @@ from django.conf import settings
from django.contrib.sessions.models import Session
from django.core.exceptions import SuspiciousOperation
from django.utils.cache import patch_vary_headers
from email.Utils import formatdate
import datetime
import time
TEST_COOKIE_NAME = 'testcookie'
TEST_COOKIE_VALUE = 'worked'
@ -37,7 +39,7 @@ class SessionWrapper(object):
return self._session.get(key, default)
def pop(self, key, *args):
self.modified = self.modified or key in self._session
self.modified = self.modified or key in self._session
return self._session.pop(key, *args)
def set_test_cookie(self):
@ -98,7 +100,11 @@ class SessionMiddleware(object):
expires = None
else:
max_age = settings.SESSION_COOKIE_AGE
expires = datetime.datetime.strftime(datetime.datetime.utcnow() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE), "%a, %d-%b-%Y %H:%M:%S GMT")
rfcdate = formatdate(time.time() + settings.SESSION_COOKIE_AGE)
# Fixed length date must have '-' separation in the format
# DD-MMM-YYYY for compliance with Netscape cookie standard
expires = (rfcdate[:7] + "-" + rfcdate[8:11]
+ "-" + rfcdate[12:26] + "GMT")
new_session = Session.objects.save(session_key, request.session._session,
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,

View File

@ -65,7 +65,7 @@ class Session(models.Model):
the sessions documentation that is shipped with Django (also available
on the Django website).
"""
session_key = models.CharField(_('session key'), maxlength=40, primary_key=True)
session_key = models.CharField(_('session key'), max_length=40, primary_key=True)
session_data = models.TextField(_('session data'))
expire_date = models.DateTimeField(_('expire date'))
objects = SessionManager()

View File

@ -4,11 +4,16 @@ from django.utils.translation import ugettext_lazy as _
class SiteManager(models.Manager):
def get_current(self):
from django.conf import settings
return self.get(pk=settings.SITE_ID)
try:
sid = settings.SITE_ID
except AttributeError:
from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured("You're using the Django \"sites framework\" without having set the SITE_ID setting. Create a site in your database and set the SITE_ID setting to fix this error.")
return self.get(pk=sid)
class Site(models.Model):
domain = models.CharField(_('domain name'), maxlength=100)
name = models.CharField(_('display name'), maxlength=50)
domain = models.CharField(_('domain name'), max_length=100)
name = models.CharField(_('display name'), max_length=50)
objects = SiteManager()
class Meta:
@ -31,3 +36,20 @@ class SiteAdmin(admin.ModelAdmin):
search_fields = ('domain', 'name')
admin.site.register(Site, SiteAdmin)
class RequestSite(object):
"""
A class that shares the primary interface of Site (i.e., it has
``domain`` and ``name`` attributes) but gets its data from a Django
HttpRequest object rather than from a database.
The save() and delete() methods raise NotImplementedError.
"""
def __init__(self, request):
self.domain = self.name = request.META['SERVER_NAME']
def save(self):
raise NotImplementedError('RequestSite cannot be saved.')
def delete(self):
raise NotImplementedError('RequestSite cannot be deleted.')

View File

@ -1,15 +1,15 @@
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.template import Context, loader, Template, TemplateDoesNotExist
from django.contrib.sites.models import Site
from django.contrib.sites.models import Site, RequestSite
from django.utils import feedgenerator
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_unicode, iri_to_uri
from django.conf import settings
def add_domain(domain, url):
if not url.startswith('http://'):
# 'url' must already be ASCII and URL-quoted, so no need for encoding
# conversions here.
url = u'http://%s%s' % (domain, url)
url = iri_to_uri(u'http://%s%s' % (domain, url))
return url
class FeedDoesNotExist(ObjectDoesNotExist):
@ -22,9 +22,10 @@ class Feed(object):
title_template = None
description_template = None
def __init__(self, slug, feed_url):
def __init__(self, slug, request):
self.slug = slug
self.feed_url = feed_url
self.request = request
self.feed_url = request.path
self.title_template_name = self.title_template or ('feeds/%s_title.html' % slug)
self.description_template_name = self.description_template or ('feeds/%s_description.html' % slug)
@ -67,7 +68,11 @@ class Feed(object):
else:
obj = None
current_site = Site.objects.get_current()
if Site._meta.installed:
current_site = Site.objects.get_current()
else:
current_site = RequestSite(self.request)
link = self.__get_dynamic_attr('link', obj)
link = add_domain(current_site.domain, link)
@ -83,6 +88,7 @@ class Feed(object):
author_email = self.__get_dynamic_attr('author_email', obj),
categories = self.__get_dynamic_attr('categories', obj),
feed_copyright = self.__get_dynamic_attr('feed_copyright', obj),
feed_guid = self.__get_dynamic_attr('feed_guid', obj),
)
try:
@ -114,7 +120,7 @@ class Feed(object):
title = title_tmp.render(Context({'obj': item, 'site': current_site})),
link = link,
description = description_tmp.render(Context({'obj': item, 'site': current_site})),
unique_id = link,
unique_id = self.__get_dynamic_attr('item_guid', item, link),
enclosure = enc,
pubdate = self.__get_dynamic_attr('item_pubdate', item),
author_name = author_name,

View File

@ -16,7 +16,7 @@ def feed(request, url, feed_dict=None):
raise Http404, "Slug %r isn't registered." % slug
try:
feedgen = f(slug, request.path).get_feed(param)
feedgen = f(slug, request).get_feed(param)
except feeds.FeedDoesNotExist:
raise Http404, "Invalid feed parameters. Slug %r is valid, but other parameters, or lack thereof, are not." % slug

View File

@ -1,7 +1,8 @@
"File-based cache backend"
from django.core.cache.backends.simple import CacheClass as SimpleCacheClass
import os, time, urllib
from django.utils.http import urlquote_plus
import os, time
try:
import cPickle as pickle
except ImportError:
@ -77,4 +78,4 @@ class CacheClass(SimpleCacheClass):
raise EnvironmentError, "Cache directory '%s' does not exist and could not be created'" % self._dir
def _key_to_file(self, key):
return os.path.join(self._dir, urllib.quote_plus(key))
return os.path.join(self._dir, urlquote_plus(key))

View File

@ -1,8 +1,13 @@
"Thread-safe in-memory cache backend."
import time
try:
import cPickle as pickle
except ImportError:
import pickle
from django.core.cache.backends.simple import CacheClass as SimpleCacheClass
from django.utils.synch import RWLock
import copy, time
class CacheClass(SimpleCacheClass):
def __init__(self, host, params):
@ -20,7 +25,10 @@ class CacheClass(SimpleCacheClass):
elif exp < now:
should_delete = True
else:
return copy.deepcopy(self._cache[key])
try:
return pickle.loads(self._cache[key])
except pickle.PickleError:
return default
finally:
self._lock.reader_leaves()
if should_delete:
@ -35,7 +43,10 @@ class CacheClass(SimpleCacheClass):
def set(self, key, value, timeout=None):
self._lock.writer_enters()
try:
SimpleCacheClass.set(self, key, value, timeout)
try:
super(CacheClass, self).set(key, pickle.dumps(value), timeout)
except pickle.PickleError:
pass
finally:
self._lock.writer_leaves()

View File

@ -1,6 +1,7 @@
"Memcached cache backend"
from django.core.cache.backends.base import BaseCache, InvalidCacheBackendError
from django.utils.encoding import smart_unicode, smart_str
try:
import cmemcache as memcache
@ -16,17 +17,22 @@ class CacheClass(BaseCache):
self._cache = memcache.Client(server.split(';'))
def get(self, key, default=None):
val = self._cache.get(key)
val = self._cache.get(smart_str(key))
if val is None:
return default
else:
return val
if isinstance(val, basestring):
return smart_unicode(val)
else:
return val
def set(self, key, value, timeout=0):
self._cache.set(key, value, timeout or self.default_timeout)
if isinstance(value, unicode):
value = value.encode('utf-8')
self._cache.set(smart_str(key), value, timeout or self.default_timeout)
def delete(self, key):
self._cache.delete(key)
self._cache.delete(smart_str(key))
def get_many(self, keys):
return self._cache.get_multi(keys)
return self._cache.get_multi(map(smart_str,keys))

View File

@ -2,6 +2,7 @@ from django.core.handlers.base import BaseHandler
from django.core import signals
from django.dispatch import dispatcher
from django.utils import datastructures
from django.utils.encoding import force_unicode
from django import http
from pprint import pformat
import os
@ -13,7 +14,7 @@ import os
class ModPythonRequest(http.HttpRequest):
def __init__(self, req):
self._req = req
self.path = req.uri
self.path = force_unicode(req.uri)
def __repr__(self):
# Since this is called as part of error handling, we need to be very

View File

@ -2,6 +2,7 @@ from django.core.handlers.base import BaseHandler
from django.core import signals
from django.dispatch import dispatcher
from django.utils import datastructures
from django.utils.encoding import force_unicode
from django import http
from pprint import pformat
from shutil import copyfileobj
@ -73,7 +74,7 @@ def safe_copyfileobj(fsrc, fdst, length=16*1024, size=0):
class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
self.environ = environ
self.path = environ['PATH_INFO']
self.path = force_unicode(environ['PATH_INFO'])
self.META = environ
self.method = environ['REQUEST_METHOD'].upper()

View File

@ -95,19 +95,12 @@ def _get_sequence_list():
return sequence_list
# If the foreign key points to an AutoField, a PositiveIntegerField or a
# PositiveSmallIntegerField, the foreign key should be an IntegerField, not the
# referred field type. Otherwise, the foreign key should be the same type of
# field as the field to which it points.
get_rel_data_type = lambda f: (f.get_internal_type() in ('AutoField', 'PositiveIntegerField', 'PositiveSmallIntegerField')) and 'IntegerField' or f.get_internal_type()
def get_sql_create(app):
"Returns a list of the CREATE TABLE SQL statements for the given app."
from django.db import get_creation_module, models
from django.db import models
from django.conf import settings
data_types = get_creation_module().DATA_TYPES
if not data_types:
if settings.DATABASE_ENGINE == 'dummy':
# This must be the "dummy" database backend, which means the user
# hasn't set DATABASE_ENGINE.
sys.stderr.write(style.ERROR("Error: Django doesn't know which syntax to use for your SQL statements,\n" +
@ -159,52 +152,46 @@ def _get_sql_model_create(model, known_models=set()):
Returns list_of_sql, pending_references_dict
"""
from django.db import backend, get_creation_module, models
data_types = get_creation_module().DATA_TYPES
from django.db import backend, models
opts = model._meta
final_output = []
table_output = []
pending_references = {}
for f in opts.fields:
if isinstance(f, (models.ForeignKey, models.OneToOneField)):
rel_field = f.rel.get_related_field()
while isinstance(rel_field, (models.ForeignKey, models.OneToOneField)):
rel_field = rel_field.rel.get_related_field()
data_type = get_rel_data_type(rel_field)
else:
rel_field = f
data_type = f.get_internal_type()
col_type = data_types[data_type]
col_type = f.db_type()
tablespace = f.db_tablespace or opts.db_tablespace
if col_type is not None:
# Make the definition (e.g. 'foo VARCHAR(30)') for this field.
field_output = [style.SQL_FIELD(backend.quote_name(f.column)),
style.SQL_COLTYPE(col_type % rel_field.__dict__)]
field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or '')))
if f.unique and (not f.primary_key or backend.allows_unique_and_pk):
field_output.append(style.SQL_KEYWORD('UNIQUE'))
if f.primary_key:
field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))
if tablespace and backend.supports_tablespaces and (f.unique or f.primary_key) and backend.autoindexes_primary_keys:
# We must specify the index tablespace inline, because we
# won't be generating a CREATE INDEX statement for this field.
field_output.append(backend.get_tablespace_sql(tablespace, inline=True))
if f.rel:
if f.rel.to in known_models:
field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \
style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)) + ' (' + \
style.SQL_FIELD(backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')' +
backend.get_deferrable_sql()
)
else:
# We haven't yet created the table to which this field
# is related, so save it for later.
pr = pending_references.setdefault(f.rel.to, []).append((model, f))
table_output.append(' '.join(field_output))
if col_type is None:
# Skip ManyToManyFields, because they're not represented as
# database columns in this table.
continue
# Make the definition (e.g. 'foo VARCHAR(30)') for this field.
field_output = [style.SQL_FIELD(backend.quote_name(f.column)),
style.SQL_COLTYPE(col_type)]
field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or '')))
if f.unique and (not f.primary_key or backend.allows_unique_and_pk):
field_output.append(style.SQL_KEYWORD('UNIQUE'))
if f.primary_key:
field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))
if tablespace and backend.supports_tablespaces and (f.unique or f.primary_key) and backend.autoindexes_primary_keys:
# We must specify the index tablespace inline, because we
# won't be generating a CREATE INDEX statement for this field.
field_output.append(backend.get_tablespace_sql(tablespace, inline=True))
if f.rel:
if f.rel.to in known_models:
field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \
style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)) + ' (' + \
style.SQL_FIELD(backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')' +
backend.get_deferrable_sql()
)
else:
# We haven't yet created the table to which this field
# is related, so save it for later.
pr = pending_references.setdefault(f.rel.to, []).append((model, f))
table_output.append(' '.join(field_output))
if opts.order_with_respect_to:
table_output.append(style.SQL_FIELD(backend.quote_name('_order')) + ' ' + \
style.SQL_COLTYPE(data_types['IntegerField']) + ' ' + \
style.SQL_COLTYPE(models.IntegerField().db_type()) + ' ' + \
style.SQL_KEYWORD('NULL'))
for field_constraints in opts.unique_together:
table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \
@ -232,9 +219,8 @@ def _get_sql_for_pending_references(model, pending_references):
"""
Get any ALTER TABLE statements to add constraints after the fact.
"""
from django.db import backend, get_creation_module
from django.db import backend
from django.db.backends.util import truncate_name
data_types = get_creation_module().DATA_TYPES
final_output = []
if backend.supports_constraints:
@ -257,11 +243,9 @@ def _get_sql_for_pending_references(model, pending_references):
return final_output
def _get_many_to_many_sql_for_model(model):
from django.db import backend, get_creation_module
from django.db import backend, models
from django.contrib.contenttypes import generic
data_types = get_creation_module().DATA_TYPES
opts = model._meta
final_output = []
for f in opts.many_to_many:
@ -275,19 +259,19 @@ def _get_many_to_many_sql_for_model(model):
style.SQL_TABLE(backend.quote_name(f.m2m_db_table())) + ' (']
table_output.append(' %s %s %s%s,' % \
(style.SQL_FIELD(backend.quote_name('id')),
style.SQL_COLTYPE(data_types['AutoField']),
style.SQL_COLTYPE(models.AutoField(primary_key=True).db_type()),
style.SQL_KEYWORD('NOT NULL PRIMARY KEY'),
tablespace_sql))
table_output.append(' %s %s %s %s (%s)%s,' % \
(style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
style.SQL_COLTYPE(data_types[get_rel_data_type(opts.pk)] % opts.pk.__dict__),
style.SQL_COLTYPE(models.ForeignKey(model).db_type()),
style.SQL_KEYWORD('NOT NULL REFERENCES'),
style.SQL_TABLE(backend.quote_name(opts.db_table)),
style.SQL_FIELD(backend.quote_name(opts.pk.column)),
backend.get_deferrable_sql()))
table_output.append(' %s %s %s %s (%s)%s,' % \
(style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())),
style.SQL_COLTYPE(data_types[get_rel_data_type(f.rel.to._meta.pk)] % f.rel.to._meta.pk.__dict__),
style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type()),
style.SQL_KEYWORD('NOT NULL REFERENCES'),
style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)),
style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column)),
@ -517,7 +501,7 @@ def _emit_post_sync_signal(created_models, verbosity, interactive):
def syncdb(verbosity=1, interactive=True):
"Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
from django.db import backend, connection, transaction, models, get_creation_module
from django.db import backend, connection, transaction, models
from django.conf import settings
disable_termcolors()
@ -533,8 +517,6 @@ def syncdb(verbosity=1, interactive=True):
except ImportError:
pass
data_types = get_creation_module().DATA_TYPES
cursor = connection.cursor()
# Get a list of all existing database tables,
@ -928,9 +910,9 @@ def inspectdb():
field_type, new_params = field_type
extra_params.update(new_params)
# Add maxlength for all CharFields.
# Add max_length for all CharFields.
if field_type == 'CharField' and row[3]:
extra_params['maxlength'] = row[3]
extra_params['max_length'] = row[3]
if field_type == 'DecimalField':
extra_params['max_digits'] = row[4]
@ -1005,8 +987,8 @@ def get_validation_errors(outfile, app=None):
for f in opts.fields:
if f.name == 'id' and not f.primary_key and opts.pk.name == 'id':
e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name)
if isinstance(f, models.CharField) and f.maxlength in (None, 0):
e.add(opts, '"%s": CharFields require a "maxlength" attribute.' % f.name)
if isinstance(f, models.CharField) and f.max_length in (None, 0):
e.add(opts, '"%s": CharFields require a "max_length" attribute.' % f.name)
if isinstance(f, models.DecimalField):
if f.decimal_places is None:
e.add(opts, '"%s": DecimalFields require a "decimal_places" attribute.' % f.name)
@ -1029,11 +1011,11 @@ def get_validation_errors(outfile, app=None):
if f.db_index not in (None, True, False):
e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name)
# Check that maxlength <= 255 if using older MySQL versions.
# Check that max_length <= 255 if using older MySQL versions.
if settings.DATABASE_ENGINE == 'mysql':
db_version = connection.get_server_version()
if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.maxlength > 255:
e.add(opts, '"%s": %s cannot have a "maxlength" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]])))
if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.max_length > 255:
e.add(opts, '"%s": %s cannot have a "max_length" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]])))
# Check to see if the related field will clash with any
# existing fields, m2m fields, m2m related objects or related objects
@ -1257,7 +1239,8 @@ def runserver(addr, port, use_reloader=True, admin_media_dir=''):
except (AttributeError, KeyError):
error_text = str(e)
sys.stderr.write(style.ERROR("Error: %s" % error_text) + '\n')
sys.exit(1)
# Need to use an OS exit because sys.exit doesn't work in a thread
os._exit(1)
except KeyboardInterrupt:
sys.exit(0)
if use_reloader:
@ -1269,18 +1252,17 @@ runserver.args = '[--noreload] [--adminmedia=ADMIN_MEDIA_PATH] [optional port nu
def createcachetable(tablename):
"Creates the table needed to use the SQL cache backend"
from django.db import backend, connection, transaction, get_creation_module, models
data_types = get_creation_module().DATA_TYPES
from django.db import backend, connection, transaction, models
fields = (
# "key" is a reserved word in MySQL, so use "cache_key" instead.
models.CharField(name='cache_key', maxlength=255, unique=True, primary_key=True),
models.CharField(name='cache_key', max_length=255, unique=True, primary_key=True),
models.TextField(name='value'),
models.DateTimeField(name='expires', db_index=True),
)
table_output = []
index_output = []
for f in fields:
field_output = [backend.quote_name(f.name), data_types[f.get_internal_type()] % f.__dict__]
field_output = [backend.quote_name(f.name), f.db_type()]
field_output.append("%sNULL" % (not f.null and "NOT " or ""))
if f.unique:
field_output.append("UNIQUE")
@ -1321,6 +1303,10 @@ def run_shell(use_plain=False):
shell.mainloop()
except ImportError:
import code
# Set up a dictionary to serve as the environment for the shell, so
# that tab completion works on objects that are imported at runtime.
# See ticket 5082.
imported_objects = {}
try: # Try activating rlcompleter, because it's handy.
import readline
except ImportError:
@ -1329,8 +1315,9 @@ def run_shell(use_plain=False):
# We don't have to wrap the following import in a 'try', because
# we already know 'readline' was imported successfully.
import rlcompleter
readline.set_completer(rlcompleter.Completer(imported_objects).complete)
readline.parse_and_bind("tab:complete")
code.interact()
code.interact(local=imported_objects)
run_shell.args = '[--plain]'
def dbshell():
@ -1352,16 +1339,11 @@ def runfcgi(args):
runfastcgi(args)
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
def test(app_labels, verbosity=1):
def test(test_labels, verbosity=1, interactive=True):
"Runs the test suite for the specified applications"
from django.conf import settings
from django.db.models import get_app, get_apps
if len(app_labels) == 0:
app_list = get_apps()
else:
app_list = [get_app(app_label) for app_label in app_labels]
test_path = settings.TEST_RUNNER.split('.')
# Allow for Python 2.5 relative paths
if len(test_path) > 1:
@ -1371,12 +1353,12 @@ def test(app_labels, verbosity=1):
test_module = __import__(test_module_name, {}, {}, test_path[-1])
test_runner = getattr(test_module, test_path[-1])
failures = test_runner(app_list, verbosity)
failures = test_runner(test_labels, verbosity=verbosity, interactive=interactive)
if failures:
sys.exit(failures)
test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified'
test.args = '[--verbosity] ' + APP_ARGS
test.args = '[--verbosity] [--noinput]' + APP_ARGS
def load_data(fixture_labels, verbosity=1):
"Installs the provided fixture file(s) as data in the database."
@ -1450,7 +1432,7 @@ def load_data(fixture_labels, verbosity=1):
print "Installing %s fixture '%s' from %s." % \
(format, fixture_name, humanize(fixture_dir))
try:
objects = serializers.deserialize(format, fixture)
objects = serializers.deserialize(format, fixture)
for obj in objects:
count[0] += 1
models.add(obj.object.__class__)
@ -1652,7 +1634,12 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
action_mapping[action](args[1])
except IndexError:
parser.print_usage_and_exit()
elif action in ('test', 'loaddata'):
elif action == 'test':
try:
action_mapping[action](args[1:], int(options.verbosity), options.interactive)
except IndexError:
parser.print_usage_and_exit()
elif action == 'loaddata':
try:
action_mapping[action](args[1:], int(options.verbosity))
except IndexError:
@ -1716,14 +1703,15 @@ def setup_environ(settings_mod):
# Add this project to sys.path so that it's importable in the conventional
# way. For example, if this file (manage.py) lives in a directory
# "myproject", this code would add "/path/to/myproject" to sys.path.
project_directory = os.path.dirname(settings_mod.__file__)
project_directory, settings_filename = os.path.split(settings_mod.__file__)
project_name = os.path.basename(project_directory)
settings_name = os.path.splitext(settings_filename)[0]
sys.path.append(os.path.join(project_directory, '..'))
project_module = __import__(project_name, {}, {}, [''])
sys.path.pop()
# Set DJANGO_SETTINGS_MODULE appropriately.
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)
return project_directory
def execute_manager(settings_mod, argv=None):

View File

@ -158,7 +158,12 @@ class DeserializedObject(object):
return "<DeserializedObject: %s>" % smart_str(self.object)
def save(self, save_m2m=True):
self.object.save()
# Call save on the Model baseclass directly. This bypasses any
# model-defined save. The save is also forced to be raw.
# This ensures that the data that is deserialized is literally
# what came from the file, not post-processed by pre_save/save
# methods.
models.Model.save(self.object, raw=True)
if self.m2m_data and save_m2m:
for accessor_name, object_list in self.m2m_data.items():
setattr(self.object, accessor_name, object_list)

View File

@ -171,7 +171,7 @@ class Deserializer(base.Deserializer):
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
data[field.attname] = self._handle_fk_field_node(field_node, field)
else:
if len(field_node.childNodes) == 1 and field_node.childNodes[0].nodeName == 'None':
if field_node.getElementsByTagName('None'):
value = None
else:
value = field.to_python(getInnerText(field_node).strip())
@ -185,7 +185,7 @@ class Deserializer(base.Deserializer):
Handle a <field> node for a ForeignKey
"""
# Check if there is a child node named 'None', returning None if so.
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
if node.getElementsByTagName('None'):
return None
else:
return field.rel.to._meta.get_field(field.rel.field_name).to_python(

View File

@ -9,7 +9,13 @@ been reviewed for security issues. Don't use it for production use.
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from types import ListType, StringType
import os, re, sys, time, urllib, mimetypes
from email.Utils import formatdate
import mimetypes
import os
import re
import sys
import time
import urllib
__version__ = "0.1"
__all__ = ['WSGIServer','WSGIRequestHandler','demo_app']
@ -370,7 +376,7 @@ class ServerHandler(object):
self._write('HTTP/%s %s\r\n' % (self.http_version,self.status))
if 'Date' not in self.headers:
self._write(
'Date: %s\r\n' % time.asctime(time.gmtime(time.time()))
'Date: %s\r\n' % (formatdate()[:26] + "GMT")
)
if self.server_software and 'Server' not in self.headers:
self._write('Server: %s\r\n' % self.server_software)

View File

@ -9,7 +9,7 @@ a string) and returns a tuple in this format:
from django.http import Http404
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
from django.utils.encoding import iri_to_uri
from django.utils.encoding import iri_to_uri, force_unicode, smart_str
from django.utils.functional import memoize
import re
@ -38,29 +38,27 @@ def get_callable(lookup_view, can_fail=False):
If can_fail is True, lookup_view might be a URL pattern label, so errors
during the import fail and the string is returned.
"""
try:
# Bail out early if lookup_view is not ASCII. This can't be a function.
lookup_view = lookup_view.encode('ascii')
if not callable(lookup_view):
if not callable(lookup_view):
try:
# Bail early for non-ASCII strings (they can't be functions).
lookup_view = lookup_view.encode('ascii')
mod_name, func_name = get_mod_func(lookup_view)
try:
if func_name != '':
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except (ImportError, AttributeError):
if not can_fail:
raise
except UnicodeEncodeError:
pass
if func_name != '':
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except (ImportError, AttributeError):
if not can_fail:
raise
except UnicodeEncodeError:
pass
return lookup_view
get_callable = memoize(get_callable, _callable_cache)
get_callable = memoize(get_callable, _callable_cache, 1)
def get_resolver(urlconf):
if urlconf is None:
from django.conf import settings
urlconf = settings.ROOT_URLCONF
return RegexURLResolver(r'^/', urlconf)
get_resolver = memoize(get_resolver, _resolver_cache)
get_resolver = memoize(get_resolver, _resolver_cache, 1)
def get_mod_func(callback):
# Converts 'django.views.news.stories.story_detail' to
@ -101,7 +99,7 @@ class MatchChecker(object):
# First we need to figure out whether it's a named or unnamed group.
#
grouped = match_obj.group(1)
m = re.search(r'^\?P<(\w+)>(.*?)$', grouped)
m = re.search(r'^\?P<(\w+)>(.*?)$', grouped, re.UNICODE)
if m: # If this was a named group...
# m.group(1) is the name of the group
# m.group(2) is the regex.
@ -127,9 +125,9 @@ class MatchChecker(object):
test_regex = grouped
# Note we're using re.match here on purpose because the start of
# to string needs to match.
if not re.match(test_regex + '$', str(value)): # TODO: Unicode?
if not re.match(test_regex + '$', force_unicode(value), re.UNICODE):
raise NoReverseMatch("Value %r didn't match regular expression %r" % (value, test_regex))
return str(value) # TODO: Unicode?
return force_unicode(value)
class RegexURLPattern(object):
def __init__(self, regex, callback, default_args=None, name=None):
@ -137,7 +135,7 @@ class RegexURLPattern(object):
# callback is either a string like 'foo.views.news.stories.story_detail'
# which represents the path to a module and a view function name, or a
# callable object (view).
self.regex = re.compile(regex)
self.regex = re.compile(regex, re.UNICODE)
if callable(callback):
self._callback = callback
else:
@ -146,6 +144,9 @@ class RegexURLPattern(object):
self.default_args = default_args or {}
self.name = name
def __repr__(self):
return '<%s %s %s>' % (self.__class__.__name__, self.name, self.regex.pattern)
def add_prefix(self, prefix):
"""
Adds the prefix string to a string-based callback.
@ -201,12 +202,15 @@ class RegexURLResolver(object):
def __init__(self, regex, urlconf_name, default_kwargs=None):
# regex is a string representing a regular expression.
# urlconf_name is a string representing the module containing urlconfs.
self.regex = re.compile(regex)
self.regex = re.compile(regex, re.UNICODE)
self.urlconf_name = urlconf_name
self.callback = None
self.default_kwargs = default_kwargs or {}
self._reverse_dict = {}
def __repr__(self):
return '<%s %s %s>' % (self.__class__.__name__, self.urlconf_name, self.regex.pattern)
def _get_reverse_dict(self):
if not self._reverse_dict and hasattr(self.urlconf_module, 'urlpatterns'):
for pattern in reversed(self.urlconf_module.urlpatterns):
@ -231,8 +235,11 @@ class RegexURLResolver(object):
tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']])
else:
if sub_match:
sub_match_dict = dict(self.default_kwargs, **sub_match[2])
return sub_match[0], sub_match[1], dict(match.groupdict(), **sub_match_dict)
sub_match_dict = dict([(smart_str(k), v) for k, v in match.groupdict().items()])
sub_match_dict.update(self.default_kwargs)
for k, v in sub_match[2].iteritems():
sub_match_dict[smart_str(k)] = v
return sub_match[0], sub_match[1], sub_match_dict
tried.append(pattern.regex.pattern)
raise Resolver404, {'tried': tried, 'path': new_path}

View File

@ -14,6 +14,10 @@ from django.utils.translation import ugettext as _, ugettext_lazy, ungettext
from django.utils.functional import Promise, lazy
from django.utils.encoding import force_unicode
import re
try:
from decimal import Decimal, DecimalException
except ImportError:
from django.utils._decimal import Decimal, DecimalException # Python 2.3
_datere = r'\d{4}-\d{1,2}-\d{1,2}'
_timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?'
@ -24,9 +28,8 @@ ansi_time_re = re.compile('^%s$' % _timere)
ansi_datetime_re = re.compile('^%s %s$' % (_datere, _timere))
email_re = re.compile(
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"' # quoted-string
r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain
decimal_re = re.compile(r'^-?(?P<digits>\d+)(\.(?P<decimals>\d+))?$')
integer_re = re.compile(r'^-?\d+$')
ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE)
@ -415,13 +418,15 @@ class IsValidDecimal(object):
self.max_digits, self.decimal_places = max_digits, decimal_places
def __call__(self, field_data, all_data):
match = decimal_re.search(str(field_data))
if not match:
try:
val = Decimal(field_data)
except DecimalException:
raise ValidationError, _("Please enter a valid decimal number.")
digits = len(match.group('digits') or '')
decimals = len(match.group('decimals') or '')
pieces = str(val).split('.')
decimals = (len(pieces) == 2) and len(pieces[1]) or 0
digits = len(pieces[0])
if digits + decimals > self.max_digits:
raise ValidationError, ungettext("Please enter a valid decimal number with at most %s total digit.",
"Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
@ -437,7 +442,7 @@ def isValidFloat(field_data, all_data):
try:
float(data)
except ValueError:
raise ValidationError, ugettext("Please enter a valid floating point number.")
raise ValidationError, _("Please enter a valid floating point number.")
class HasAllowableSize(object):
"""

View File

@ -1,8 +1,8 @@
DATA_TYPES = {
'AutoField': 'int IDENTITY (1, 1)',
'BooleanField': 'bit',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'smalldatetime',
'DateTimeField': 'smalldatetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
@ -12,13 +12,12 @@ DATA_TYPES = {
'ImageField': 'varchar(100)',
'IntegerField': 'int',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bit',
'OneToOneField': 'int',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(column)s] CHECK ([%(column)s] > 0)',
'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)',
'SlugField': 'varchar(%(maxlength)s)',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'text',
'TimeField': 'time',

View File

@ -5,8 +5,8 @@
DATA_TYPES = {
'AutoField': 'integer AUTO_INCREMENT',
'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
@ -16,13 +16,12 @@ DATA_TYPES = {
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(maxlength)s)',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',

View File

@ -5,8 +5,8 @@
DATA_TYPES = {
'AutoField': 'integer AUTO_INCREMENT',
'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
@ -16,13 +16,12 @@ DATA_TYPES = {
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(maxlength)s)',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',

View File

@ -8,8 +8,8 @@ from django.core import management
DATA_TYPES = {
'AutoField': 'NUMBER(11)',
'BooleanField': 'NUMBER(1) CHECK (%(column)s IN (0,1))',
'CharField': 'NVARCHAR2(%(maxlength)s)',
'CommaSeparatedIntegerField': 'VARCHAR2(%(maxlength)s)',
'CharField': 'NVARCHAR2(%(max_length)s)',
'CommaSeparatedIntegerField': 'VARCHAR2(%(max_length)s)',
'DateField': 'DATE',
'DateTimeField': 'TIMESTAMP',
'DecimalField': 'NUMBER(%(max_digits)s, %(decimal_places)s)',
@ -19,7 +19,6 @@ DATA_TYPES = {
'ImageField': 'NVARCHAR2(100)',
'IntegerField': 'NUMBER(11)',
'IPAddressField': 'VARCHAR2(15)',
'ManyToManyField': None,
'NullBooleanField': 'NUMBER(1) CHECK ((%(column)s IN (0,1)) OR (%(column)s IS NULL))',
'OneToOneField': 'NUMBER(11)',
'PhoneNumberField': 'VARCHAR2(20)',

View File

@ -5,8 +5,8 @@
DATA_TYPES = {
'AutoField': 'serial',
'BooleanField': 'boolean',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'timestamp with time zone',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
@ -16,13 +16,12 @@ DATA_TYPES = {
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'inet',
'ManyToManyField': None,
'NullBooleanField': 'boolean',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)',
'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)',
'SlugField': 'varchar(%(maxlength)s)',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'text',
'TimeField': 'time',

View File

@ -30,11 +30,8 @@ def get_relations(cursor, table_name):
AND con.contype = 'f'""", [table_name])
relations = {}
for row in cursor.fetchall():
try:
# row[0] and row[1] are like "{2}", so strip the curly braces.
relations[int(row[0][1:-1]) - 1] = (int(row[1][1:-1]) - 1, row[2])
except ValueError:
continue
# row[0] and row[1] are single-item lists, so grab the single item.
relations[row[0][0] - 1] = (row[1][0] - 1, row[2])
return relations
def get_indexes(cursor, table_name):

View File

@ -4,8 +4,8 @@
DATA_TYPES = {
'AutoField': 'integer',
'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'decimal',
@ -15,13 +15,12 @@ DATA_TYPES = {
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer unsigned',
'PositiveSmallIntegerField': 'smallint unsigned',
'SlugField': 'varchar(%(maxlength)s)',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'text',
'TimeField': 'time',

View File

@ -81,7 +81,7 @@ class FlexibleFieldLookupDict:
import re
m = re.search(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$', key)
if m:
return ('CharField', {'maxlength': int(m.group(1))})
return ('CharField', {'max_length': int(m.group(1))})
raise KeyError
DATA_TYPES_REVERSE = FlexibleFieldLookupDict()

View File

@ -15,14 +15,18 @@ from django.utils.text import capfirst
# Admin stages.
ADD, CHANGE, BOTH = 1, 2, 3
# Decorator. Takes a function that returns a tuple in this format:
# (viewname, viewargs, viewkwargs)
# Returns a function that calls urlresolvers.reverse() on that data, to return
# the URL for those parameters.
def permalink(func):
"""
Decorator that calls urlresolvers.reverse() to return a URL using
parameters returned by the decorated function "func".
"func" should be a function that returns a tuple in one of the
following formats:
(viewname, viewargs)
(viewname, viewargs, viewkwargs)
"""
from django.core.urlresolvers import reverse
def inner(*args, **kwargs):
bits = func(*args, **kwargs)
viewname = bits[0]
return reverse(bits[0], None, *bits[1:3])
return inner

View File

@ -206,7 +206,7 @@ class Model(object):
_prepare = classmethod(_prepare)
def save(self):
def save(self, raw=False):
dispatcher.send(signal=signals.pre_save, sender=self.__class__, instance=self)
non_pks = [f for f in self._meta.fields if not f.primary_key]
@ -223,7 +223,7 @@ class Model(object):
self._meta.pk.get_db_prep_lookup('exact', pk_val))
# If it does already exist, do an UPDATE.
if cursor.fetchone()[0] > 0:
db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks]
db_values = [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, False)) for f in non_pks]
if db_values:
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
(backend.quote_name(self._meta.db_table),
@ -234,11 +234,11 @@ class Model(object):
record_exists = False
if not pk_set or not record_exists:
field_names = [backend.quote_name(f.column) for f in self._meta.fields if not isinstance(f, AutoField)]
db_values = [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)]
db_values = [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)]
# If the PK has been manually set, respect that.
if pk_set:
field_names += [f.column for f in self._meta.fields if isinstance(f, AutoField)]
db_values += [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)]
db_values += [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)]
placeholders = ['%s'] * len(field_names)
if self._meta.order_with_respect_to:
field_names.append(backend.quote_name('_order'))

View File

@ -1,3 +1,4 @@
from django.db import get_creation_module
from django.db.models import signals
from django.dispatch import dispatcher
from django.conf import settings
@ -10,6 +11,7 @@ from django.utils.itercompat import tee
from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy, ugettext as _
from django.utils.encoding import smart_unicode, force_unicode, smart_str
from django.utils.maxlength import LegacyMaxlength
import datetime, os, time
try:
import decimal
@ -61,6 +63,9 @@ def manipulator_validator_unique(f, opts, self, field_data, all_data):
# getattr(obj, opts.pk.attname)
class Field(object):
# Provide backwards compatibility for the maxlength attribute and
# argument for this class and all subclasses.
__metaclass__ = LegacyMaxlength
# Designates whether empty strings fundamentally are allowed at the
# database level.
@ -70,7 +75,7 @@ class Field(object):
creation_counter = 0
def __init__(self, verbose_name=None, name=None, primary_key=False,
maxlength=None, unique=False, blank=False, null=False, db_index=False,
max_length=None, unique=False, blank=False, null=False, db_index=False,
core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True,
unique_for_date=None, unique_for_month=None, unique_for_year=None,
validator_list=None, choices=None, radio_admin=None, help_text='', db_column=None,
@ -78,7 +83,7 @@ class Field(object):
self.name = name
self.verbose_name = verbose_name
self.primary_key = primary_key
self.maxlength, self.unique = maxlength, unique
self.max_length, self.unique = max_length, unique
self.blank, self.null = blank, null
# Oracle treats the empty string ('') as null, so coerce the null
# option whenever '' is a possible value.
@ -115,6 +120,30 @@ class Field(object):
"""
return value
def db_type(self):
"""
Returns the database column data type for this field, taking into
account the DATABASE_ENGINE setting.
"""
# The default implementation of this method looks at the
# backend-specific DATA_TYPES dictionary, looking up the field by its
# "internal type".
#
# A Field class can implement the get_internal_type() method to specify
# which *preexisting* Django Field class it's most similar to -- i.e.,
# an XMLField is represented by a TEXT column type, which is the same
# as the TextField Django field type, which means XMLField's
# get_internal_type() returns 'TextField'.
#
# But the limitation of the get_internal_type() / DATA_TYPES approach
# is that it cannot handle database column types that aren't already
# mapped to one of the built-in Django field types. In this case, you
# can implement db_type() instead of get_internal_type() to specify
# exactly which wacky database column type you want to use.
data_types = get_creation_module().DATA_TYPES
internal_type = self.get_internal_type()
return data_types[internal_type] % self.__dict__
def validate_full(self, field_data, all_data):
"""
Returns a list of errors for this field. This is the main interface,
@ -217,8 +246,8 @@ class Field(object):
def prepare_field_objs_and_params(self, manipulator, name_prefix):
params = {'validator_list': self.validator_list[:]}
if self.maxlength and not self.choices: # Don't give SelectFields a maxlength parameter.
params['maxlength'] = self.maxlength
if self.max_length and not self.choices: # Don't give SelectFields a max_length parameter.
params['max_length'] = self.max_length
if self.choices:
if self.radio_admin:
@ -349,6 +378,9 @@ class Field(object):
return self._choices
choices = property(_get_choices)
def save_form_data(self, instance, data):
setattr(instance, self.name, data)
def formfield(self, form_class=forms.CharField, **kwargs):
"Returns a django.newforms.Field instance for this database Field."
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
@ -434,7 +466,7 @@ class CharField(Field):
return smart_unicode(value)
def formfield(self, **kwargs):
defaults = {'max_length': self.maxlength}
defaults = {'max_length': self.max_length}
defaults.update(kwargs)
return super(CharField, self).formfield(**defaults)
@ -593,7 +625,8 @@ class DecimalField(Field):
try:
return decimal.Decimal(value)
except decimal.InvalidOperation:
raise validators.ValidationError, ugettext("This value must be a decimal number.")
raise validators.ValidationError(
_("This value must be a decimal number."))
def _format(self, value):
if isinstance(value, basestring):
@ -642,7 +675,7 @@ class DecimalField(Field):
class EmailField(CharField):
def __init__(self, *args, **kwargs):
kwargs['maxlength'] = 75
kwargs['max_length'] = 75
CharField.__init__(self, *args, **kwargs)
def get_internal_type(self):
@ -664,6 +697,13 @@ class FileField(Field):
self.upload_to = upload_to
Field.__init__(self, verbose_name, name, **kwargs)
def get_db_prep_save(self, value):
"Returns field's value prepared for saving into a database."
# Need to convert UploadedFile objects provided via a form to unicode for database insertion
if value is None:
return None
return unicode(value)
def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)
if not self.blank:
@ -740,6 +780,19 @@ class FileField(Field):
f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename)))
return os.path.normpath(f)
def save_form_data(self, instance, data):
if data:
getattr(instance, "save_%s_file" % self.name)(data.filename, data.content, save=False)
def formfield(self, **kwargs):
defaults = {'form_class': forms.FileField}
# If a file has been provided previously, then the form doesn't require
# that a new file is provided this time.
if 'initial' in kwargs:
defaults['required'] = False
defaults.update(kwargs)
return super(FileField, self).formfield(**defaults)
class FilePathField(Field):
def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs):
self.path, self.match, self.recursive = path, match, recursive
@ -788,6 +841,10 @@ class ImageField(FileField):
setattr(new_object, self.height_field, getattr(original_object, self.height_field))
new_object.save()
def formfield(self, **kwargs):
defaults = {'form_class': forms.ImageField}
return super(ImageField, self).formfield(**defaults)
class IntegerField(Field):
empty_strings_allowed = False
def get_manipulator_field_objs(self):
@ -801,7 +858,7 @@ class IntegerField(Field):
class IPAddressField(Field):
empty_strings_allowed = False
def __init__(self, *args, **kwargs):
kwargs['maxlength'] = 15
kwargs['max_length'] = 15
Field.__init__(self, *args, **kwargs)
def get_manipulator_field_objs(self):
@ -854,7 +911,7 @@ class PositiveSmallIntegerField(IntegerField):
class SlugField(Field):
def __init__(self, *args, **kwargs):
kwargs['maxlength'] = kwargs.get('maxlength', 50)
kwargs['max_length'] = kwargs.get('max_length', 50)
kwargs.setdefault('validator_list', []).append(validators.isSlug)
# Set db_index=True unless it's been set manually.
if 'db_index' not in kwargs:
@ -940,7 +997,7 @@ class TimeField(Field):
class URLField(CharField):
def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
kwargs['maxlength'] = kwargs.get('maxlength', 200)
kwargs['max_length'] = kwargs.get('max_length', 200)
if verify_exists:
kwargs.setdefault('validator_list', []).append(validators.isExistingURL)
self.verify_exists = verify_exists

View File

@ -1,6 +1,6 @@
from django.db import backend, transaction
from django.db.models import signals, get_model
from django.db.models.fields import AutoField, Field, IntegerField, get_ul_class
from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, get_ul_class
from django.db.models.related import RelatedObject
from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy, string_concat, ungettext, ugettext as _
@ -548,6 +548,16 @@ class ForeignKey(RelatedField, Field):
defaults.update(kwargs)
return super(ForeignKey, self).formfield(**defaults)
def db_type(self):
# The database column type of a ForeignKey is the column type
# of the field to which it points. An exception is if the ForeignKey
# points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField,
# in which case the column type is simply that of an IntegerField.
rel_field = self.rel.get_related_field()
if isinstance(rel_field, (AutoField, PositiveIntegerField, PositiveSmallIntegerField)):
return IntegerField().db_type()
return rel_field.db_type()
class OneToOneField(RelatedField, IntegerField):
def __init__(self, to, to_field=None, **kwargs):
try:
@ -609,6 +619,16 @@ class OneToOneField(RelatedField, IntegerField):
defaults.update(kwargs)
return super(OneToOneField, self).formfield(**defaults)
def db_type(self):
# The database column type of a OneToOneField is the column type
# of the field to which it points. An exception is if the OneToOneField
# points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField,
# in which case the column type is simply that of an IntegerField.
rel_field = self.rel.get_related_field()
if isinstance(rel_field, (AutoField, PositiveIntegerField, PositiveSmallIntegerField)):
return IntegerField().db_type()
return rel_field.db_type()
class ManyToManyField(RelatedField, Field):
def __init__(self, to, **kwargs):
kwargs['verbose_name'] = kwargs.get('verbose_name', None)
@ -710,6 +730,9 @@ class ManyToManyField(RelatedField, Field):
"Returns the value of this field in the given model instance."
return getattr(obj, self.attname).all()
def save_form_data(self, instance, data):
setattr(instance, self.attname, data)
def formfield(self, **kwargs):
defaults = {'form_class': forms.ModelMultipleChoiceField, 'queryset': self.rel.to._default_manager.all()}
defaults.update(kwargs)
@ -719,6 +742,11 @@ class ManyToManyField(RelatedField, Field):
defaults['initial'] = [i._get_pk_val() for i in defaults['initial']]
return super(ManyToManyField, self).formfield(**defaults)
def db_type(self):
# A ManyToManyField is not represented by a single column,
# so return None.
return None
class ManyToOneRel(object):
def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
max_num_in_admin=None, num_extra_on_change=1, edit_inline=False,

View File

@ -3,10 +3,6 @@ from django.dispatch import dispatcher
from django.db.models import signals
from django.db.models.fields import FieldDoesNotExist
# Size of each "chunk" for get_iterator calls.
# Larger values are slightly faster at the expense of more storage space.
GET_ITERATOR_CHUNK_SIZE = 100
def ensure_default_manager(sender):
cls = sender
if not hasattr(cls, '_default_manager'):
@ -47,7 +43,7 @@ class Manager(object):
def get_query_set(self):
"""Returns a new QuerySet object. Subclasses can override this method
to easily customise the behaviour of the Manager.
to easily customize the behavior of the Manager.
"""
return QuerySet(self.model)

View File

@ -579,28 +579,36 @@ class ValuesQuerySet(QuerySet):
except EmptyResultSet:
raise StopIteration
# self._fields is a list of field names to fetch.
# self._select is a dictionary, and dictionaries' key order is
# undefined, so we convert it to a list of tuples.
extra_select = self._select.items()
# Construct two objects -- fields and field_names.
# fields is a list of Field objects to fetch.
# field_names is a list of field names, which will be the keys in the
# resulting dictionaries.
if self._fields:
if not self._select:
if not extra_select:
fields = [self.model._meta.get_field(f, many_to_many=False) for f in self._fields]
field_names = self._fields
else:
fields = []
field_names = []
for f in self._fields:
if f in [field.name for field in self.model._meta.fields]:
fields.append(self.model._meta.get_field(f, many_to_many=False))
elif not self._select.has_key( f ):
raise FieldDoesNotExist, '%s has no field named %r' % ( self.model._meta.object_name, f )
field_names = self._fields
field_names.append(f)
elif not self._select.has_key(f):
raise FieldDoesNotExist('%s has no field named %r' % (self.model._meta.object_name, f))
else: # Default to all fields.
fields = self.model._meta.fields
field_names = [f.attname for f in fields]
columns = [f.column for f in fields]
select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns]
# Add any additional SELECTs.
if self._select:
select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
if extra_select:
select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in extra_select])
field_names.extend([f[0] for f in extra_select])
cursor = connection.cursor()
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)

View File

@ -109,12 +109,11 @@ class QueryDict(MultiValueDict):
# *Important*: do not import settings any earlier because of note
# in core.handlers.modpython.
from django.conf import settings
self.encoding = settings.DEFAULT_CHARSET
else:
self.encoding = encoding
encoding = settings.DEFAULT_CHARSET
self.encoding = encoding
self._mutable = True
for key, value in parse_qsl((query_string or ''), True): # keep_blank_values=True
self.appendlist(force_unicode(key, errors='replace'), force_unicode(value, errors='replace'))
self.appendlist(force_unicode(key, encoding, errors='replace'), force_unicode(value, encoding, errors='replace'))
self._mutable = mutable
def _assert_mutable(self):

View File

@ -39,7 +39,7 @@ class CommonMiddleware(object):
new_url[0] = 'www.' + old_url[0]
# Append a slash if append_slash is set and the URL doesn't have a
# trailing slash or a file extension.
if settings.APPEND_SLASH and (old_url[1][-1] != '/') and ('.' not in old_url[1].split('/')[-1]):
if settings.APPEND_SLASH and (not old_url[1].endswith('/')) and ('.' not in old_url[1].split('/')[-1]):
new_url[1] = new_url[1] + '/'
if settings.DEBUG and request.method == 'POST':
raise RuntimeError, "You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to %s%s (note the trailing slash), or set APPEND_SLASH=False in your Django settings." % (new_url[0], new_url[1])

View File

@ -1,4 +1,4 @@
import datetime
from email.Utils import formatdate
class ConditionalGetMiddleware(object):
"""
@ -11,8 +11,7 @@ class ConditionalGetMiddleware(object):
Also sets the Date and Content-Length response-headers.
"""
def process_response(self, request, response):
now = datetime.datetime.utcnow()
response['Date'] = now.strftime('%a, %d %b %Y %H:%M:%S GMT')
response['Date'] = formatdate()[:26] + "GMT"
if not response.has_header('Content-Length'):
response['Content-Length'] = str(len(response.content))

View File

@ -53,7 +53,7 @@ class SelectDateWidget(Widget):
return u'\n'.join(output)
def value_from_datadict(self, data, name):
def value_from_datadict(self, data, files, name):
y, m, d = data.get(self.year_field % name), data.get(self.month_field % name), data.get(self.day_field % name)
if y and m and d:
return '%s-%s-%s' % (y, m, d)

View File

@ -7,17 +7,22 @@ import re
import time
from django.utils.translation import ugettext
from django.utils.encoding import smart_unicode
from django.utils.encoding import StrAndUnicode, smart_unicode
from util import ErrorList, ValidationError
from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple
from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple
try:
from decimal import Decimal, DecimalException
except ImportError:
from django.utils._decimal import Decimal, DecimalException
__all__ = (
'Field', 'CharField', 'IntegerField',
'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
'DEFAULT_TIME_INPUT_FORMATS', 'TimeField',
'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
'RegexField', 'EmailField', 'URLField', 'BooleanField',
'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField', 'BooleanField',
'ChoiceField', 'NullBooleanField', 'MultipleChoiceField',
'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
'SplitDateTimeField',
@ -106,14 +111,16 @@ class CharField(Field):
if value in EMPTY_VALUES:
return u''
value = smart_unicode(value)
if self.max_length is not None and len(value) > self.max_length:
raise ValidationError(ugettext(u'Ensure this value has at most %d characters.') % self.max_length)
if self.min_length is not None and len(value) < self.min_length:
raise ValidationError(ugettext(u'Ensure this value has at least %d characters.') % self.min_length)
value_length = len(value)
if self.max_length is not None and value_length > self.max_length:
raise ValidationError(ugettext(u'Ensure this value has at most %(max)d characters (it has %(length)d).') % {'max': self.max_length, 'length': value_length})
if self.min_length is not None and value_length < self.min_length:
raise ValidationError(ugettext(u'Ensure this value has at least %(min)d characters (it has %(length)d).') % {'min': self.min_length, 'length': value_length})
return value
def widget_attrs(self, widget):
if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)):
# The HTML attribute is maxlength, not max_length.
return {'maxlength': str(self.max_length)}
class IntegerField(Field):
@ -162,8 +169,6 @@ class FloatField(Field):
raise ValidationError(ugettext('Ensure this value is greater than or equal to %s.') % self.min_value)
return value
decimal_re = re.compile(r'^-?(?P<digits>\d+)(\.(?P<decimals>\d+))?$')
class DecimalField(Field):
def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs):
self.max_value, self.min_value = max_value, min_value
@ -181,13 +186,13 @@ class DecimalField(Field):
if not self.required and value in EMPTY_VALUES:
return None
value = value.strip()
match = decimal_re.search(value)
if not match:
raise ValidationError(ugettext('Enter a number.'))
else:
try:
value = Decimal(value)
digits = len(match.group('digits') or '')
decimals = len(match.group('decimals') or '')
except DecimalException:
raise ValidationError(ugettext('Enter a number.'))
pieces = str(value).split('.')
decimals = (len(pieces) == 2) and len(pieces[1]) or 0
digits = len(pieces[0])
if self.max_value is not None and value > self.max_value:
raise ValidationError(ugettext('Ensure this value is less than or equal to %s.') % self.max_value)
if self.min_value is not None and value < self.min_value:
@ -295,18 +300,17 @@ class DateTimeField(Field):
continue
raise ValidationError(ugettext(u'Enter a valid date/time.'))
class RegexField(Field):
class RegexField(CharField):
def __init__(self, regex, max_length=None, min_length=None, error_message=None, *args, **kwargs):
"""
regex can be either a string or a compiled regular expression object.
error_message is an optional error message to use, if
'Enter a valid value' is too generic for you.
"""
super(RegexField, self).__init__(*args, **kwargs)
super(RegexField, self).__init__(max_length, min_length, *args, **kwargs)
if isinstance(regex, basestring):
regex = re.compile(regex)
self.regex = regex
self.max_length, self.min_length = max_length, min_length
self.error_message = error_message or ugettext(u'Enter a valid value.')
def clean(self, value):
@ -314,16 +318,9 @@ class RegexField(Field):
Validates that the input matches the regular expression. Returns a
Unicode object.
"""
super(RegexField, self).clean(value)
if value in EMPTY_VALUES:
value = u''
value = smart_unicode(value)
value = super(RegexField, self).clean(value)
if value == u'':
return value
if self.max_length is not None and len(value) > self.max_length:
raise ValidationError(ugettext(u'Ensure this value has at most %d characters.') % self.max_length)
if self.min_length is not None and len(value) < self.min_length:
raise ValidationError(ugettext(u'Ensure this value has at least %d characters.') % self.min_length)
if not self.regex.search(value):
raise ValidationError(self.error_message)
return value
@ -351,6 +348,55 @@ except ImportError:
# It's OK if Django settings aren't configured.
URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'
class UploadedFile(StrAndUnicode):
"A wrapper for files uploaded in a FileField"
def __init__(self, filename, content):
self.filename = filename
self.content = content
def __unicode__(self):
"""
The unicode representation is the filename, so that the pre-database-insertion
logic can use UploadedFile objects
"""
return self.filename
class FileField(Field):
widget = FileInput
def __init__(self, *args, **kwargs):
super(FileField, self).__init__(*args, **kwargs)
def clean(self, data):
super(FileField, self).clean(data)
if not self.required and data in EMPTY_VALUES:
return None
try:
f = UploadedFile(data['filename'], data['content'])
except TypeError:
raise ValidationError(ugettext(u"No file was submitted. Check the encoding type on the form."))
except KeyError:
raise ValidationError(ugettext(u"No file was submitted."))
if not f.content:
raise ValidationError(ugettext(u"The submitted file is empty."))
return f
class ImageField(FileField):
def clean(self, data):
"""
Checks that the file-upload field data contains a valid image (GIF, JPG,
PNG, possibly others -- whatever the Python Imaging Library supports).
"""
f = super(ImageField, self).clean(data)
if f is None:
return None
from PIL import Image
from cStringIO import StringIO
try:
Image.open(StringIO(f.content))
except IOError: # Python Imaging Library doesn't recognize it as an image
raise ValidationError(ugettext(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."))
return f
class URLField(RegexField):
def __init__(self, max_length=None, min_length=None, verify_exists=False,
validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs):
@ -446,10 +492,7 @@ class MultipleChoiceField(ChoiceField):
return []
if not isinstance(value, (list, tuple)):
raise ValidationError(ugettext(u'Enter a list of values.'))
new_value = []
for val in value:
val = smart_unicode(val)
new_value.append(val)
new_value = [smart_unicode(val) for val in value]
# Validate that each value in the value list is in self.choices.
valid_values = set([smart_unicode(k) for k, v in self.choices])
for val in new_value:

View File

@ -57,9 +57,10 @@ class BaseForm(StrAndUnicode):
# class is different than Form. See the comments by the Form class for more
# information. Any improvements to the form API should be made to *this*
# class, not to the Form class.
def __init__(self, data=None, auto_id='id_%s', prefix=None, initial=None):
self.is_bound = data is not None
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None):
self.is_bound = data is not None or files is not None
self.data = data or {}
self.files = files or {}
self.auto_id = auto_id
self.prefix = prefix
self.initial = initial or {}
@ -88,7 +89,7 @@ class BaseForm(StrAndUnicode):
return BoundField(self, field, name)
def _get_errors(self):
"Returns an ErrorDict for self.data"
"Returns an ErrorDict for the data provided for the form"
if self._errors is None:
self.full_clean()
return self._errors
@ -182,7 +183,7 @@ class BaseForm(StrAndUnicode):
# value_from_datadict() gets the data from the dictionary.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, self.add_prefix(name))
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
# HACK: ['', ''] and [None, None] deal with SplitDateTimeWidget. This should be more robust.
if value not in (None, '', ['', ''], [None, None]):
return False
@ -198,10 +199,10 @@ class BaseForm(StrAndUnicode):
return
self.cleaned_data = {}
for name, field in self.fields.items():
# value_from_datadict() gets the data from the dictionary.
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, self.add_prefix(name))
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try:
value = field.clean(value)
self.cleaned_data[name] = value
@ -257,16 +258,8 @@ class BoundField(StrAndUnicode):
self.help_text = field.help_text or ''
def __unicode__(self):
"Renders this field as an HTML widget."
# Use the 'widget' attribute on the field to determine which type
# of HTML widget to use.
value = self.as_widget(self.field.widget)
if not isinstance(value, basestring):
# Some Widget render() methods -- notably RadioSelect -- return a
# "special" object rather than a string. Call __unicode__() on that
# object to get its rendered value.
value = unicode(value)
return value
"""Renders this field as an HTML widget."""
return self.as_widget()
def _errors(self):
"""
@ -276,7 +269,14 @@ class BoundField(StrAndUnicode):
return self.form.errors.get(self.name, ErrorList())
errors = property(_errors)
def as_widget(self, widget, attrs=None):
def as_widget(self, widget=None, attrs=None):
"""
Renders the field by rendering the passed widget, adding any HTML
attributes passed as attrs. If no widget is specified, then the
field's default widget will be used.
"""
if not widget:
widget = self.field.widget
attrs = attrs or {}
auto_id = self.auto_id
if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
@ -309,7 +309,7 @@ class BoundField(StrAndUnicode):
"""
Returns the data for this BoundField, or None if it wasn't given.
"""
return self.field.widget.value_from_datadict(self.form.data, self.html_name)
return self.field.widget.value_from_datadict(self.form.data, self.form.files, self.html_name)
data = property(_data)
def label_tag(self, contents=None, attrs=None):

View File

@ -35,18 +35,24 @@ def save_instance(form, instance, fields=None, fail_message='saved', commit=True
continue
if fields and f.name not in fields:
continue
setattr(instance, f.name, cleaned_data[f.name])
if commit:
instance.save()
f.save_form_data(instance, cleaned_data[f.name])
# Wrap up the saving of m2m data as a function
def save_m2m():
opts = instance.__class__._meta
cleaned_data = form.cleaned_data
for f in opts.many_to_many:
if fields and f.name not in fields:
continue
if f.name in cleaned_data:
setattr(instance, f.attname, cleaned_data[f.name])
# GOTCHA: If many-to-many data is given and commit=False, the many-to-many
# data will be lost. This happens because a many-to-many options cannot be
# set on an object until after it's saved. Maybe we should raise an
# exception in that case.
f.save_form_data(instance, cleaned_data[f.name])
if commit:
# If we are committing, save the instance and the m2m data immediately
instance.save()
save_m2m()
else:
# We're not committing. Add a method to the form to allow deferred
# saving of m2m data
form.save_m2m = save_m2m
return instance
def make_model_save(model, fields, fail_message):

View File

@ -47,7 +47,7 @@ class Widget(object):
attrs.update(extra_attrs)
return attrs
def value_from_datadict(self, data, name):
def value_from_datadict(self, data, files, name):
"""
Given a dictionary of data and this widget's name, returns the value
of this widget. Returns None if it's not provided.
@ -113,7 +113,7 @@ class MultipleHiddenInput(HiddenInput):
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
return u'\n'.join([(u'<input%s />' % flatatt(dict(value=force_unicode(v), **final_attrs))) for v in value])
def value_from_datadict(self, data, name):
def value_from_datadict(self, data, files, name):
if isinstance(data, MultiValueDict):
return data.getlist(name)
return data.get(name, None)
@ -121,6 +121,13 @@ class MultipleHiddenInput(HiddenInput):
class FileInput(Input):
input_type = 'file'
def render(self, name, value, attrs=None):
return super(FileInput, self).render(name, None, attrs=attrs)
def value_from_datadict(self, data, files, name):
"File widgets take data from FILES, not POST"
return files.get(name, None)
class Textarea(Widget):
def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness.
@ -188,7 +195,7 @@ class NullBooleanSelect(Select):
value = u'1'
return super(NullBooleanSelect, self).render(name, value, attrs, choices)
def value_from_datadict(self, data, name):
def value_from_datadict(self, data, files, name):
value = data.get(name, None)
return {u'2': True, u'3': False, True: True, False: False}.get(value, None)
@ -210,13 +217,17 @@ class SelectMultiple(Widget):
output.append(u'</select>')
return u'\n'.join(output)
def value_from_datadict(self, data, name):
def value_from_datadict(self, data, files, name):
if isinstance(data, MultiValueDict):
return data.getlist(name)
return data.get(name, None)
class RadioInput(StrAndUnicode):
"An object used by RadioFieldRenderer that represents a single <input type='radio'>."
"""
An object used by RadioFieldRenderer that represents a single
<input type='radio'>.
"""
def __init__(self, name, value, attrs, choice, index):
self.name, self.value = name, value
self.attrs = attrs
@ -239,7 +250,10 @@ class RadioInput(StrAndUnicode):
return u'<input%s />' % flatatt(final_attrs)
class RadioFieldRenderer(StrAndUnicode):
"An object used by RadioSelect to enable customization of radio widgets."
"""
An object used by RadioSelect to enable customization of radio widgets.
"""
def __init__(self, name, value, attrs, choices):
self.name, self.value, self.attrs = name, value, attrs
self.choices = choices
@ -253,16 +267,30 @@ class RadioFieldRenderer(StrAndUnicode):
return RadioInput(self.name, self.value, self.attrs.copy(), choice, idx)
def __unicode__(self):
"Outputs a <ul> for this set of radio fields."
return self.render()
def render(self):
"""Outputs a <ul> for this set of radio fields."""
return u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' % force_unicode(w) for w in self])
class RadioSelect(Select):
def render(self, name, value, attrs=None, choices=()):
"Returns a RadioFieldRenderer instance rather than a Unicode string."
def __init__(self, *args, **kwargs):
self.renderer = kwargs.pop('renderer', None)
if not self.renderer:
self.renderer = RadioFieldRenderer
super(RadioSelect, self).__init__(*args, **kwargs)
def get_renderer(self, name, value, attrs=None, choices=()):
"""Returns an instance of the renderer."""
if value is None: value = ''
str_value = force_unicode(value) # Normalize to string.
final_attrs = self.build_attrs(attrs)
return RadioFieldRenderer(name, str_value, final_attrs, list(chain(self.choices, choices)))
choices = list(chain(self.choices, choices))
return self.renderer(name, str_value, final_attrs, choices)
def render(self, name, value, attrs=None, choices=()):
return self.get_renderer(name, value, attrs, choices).render()
def id_for_label(self, id_):
# RadioSelect is represented by multiple <input type="radio"> fields,
@ -356,8 +384,8 @@ class MultiWidget(Widget):
return id_
id_for_label = classmethod(id_for_label)
def value_from_datadict(self, data, name):
return [widget.value_from_datadict(data, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
def value_from_datadict(self, data, files, name):
return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
def format_output(self, rendered_widgets):
"""

View File

@ -3,7 +3,8 @@ from django.core.exceptions import PermissionDenied
from django.utils.html import escape
from django.conf import settings
from django.utils.translation import ugettext, ungettext
from django.utils.encoding import smart_unicode, force_unicode, smart_str
from django.utils.encoding import smart_unicode, force_unicode
from django.utils.maxlength import LegacyMaxlength
FORM_FIELD_ID_PREFIX = 'id_'
@ -302,6 +303,9 @@ class FormField(object):
Subclasses should also implement a render(data) method, which is responsible
for rending the form field in XHTML.
"""
# Provide backwards compatibility for the maxlength attribute and
# argument for this class and all subclasses.
__metaclass__ = LegacyMaxlength
def __str__(self):
return unicode(self).encode('utf-8')
@ -390,19 +394,19 @@ class FormField(object):
class TextField(FormField):
input_type = "text"
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None, member_name=None):
def __init__(self, field_name, length=30, max_length=None, is_required=False, validator_list=None, member_name=None):
if validator_list is None: validator_list = []
self.field_name = field_name
self.length, self.maxlength = length, maxlength
self.length, self.max_length = length, max_length
self.is_required = is_required
self.validator_list = [self.isValidLength, self.hasNoNewlines] + validator_list
if member_name != None:
self.member_name = member_name
def isValidLength(self, data, form):
if data and self.maxlength and len(smart_unicode(data)) > self.maxlength:
if data and self.max_length and len(smart_unicode(data)) > self.max_length:
raise validators.ValidationError, ungettext("Ensure your text is less than %s character.",
"Ensure your text is less than %s characters.", self.maxlength) % self.maxlength
"Ensure your text is less than %s characters.", self.max_length) % self.max_length
def hasNoNewlines(self, data, form):
if data and '\n' in data:
@ -411,12 +415,12 @@ class TextField(FormField):
def render(self, data):
if data is None:
data = u''
maxlength = u''
if self.maxlength:
maxlength = u'maxlength="%s" ' % self.maxlength
max_length = u''
if self.max_length:
max_length = u'maxlength="%s" ' % self.max_length
return u'<input type="%s" id="%s" class="v%s%s" name="%s" size="%s" value="%s" %s/>' % \
(self.input_type, self.get_id(), self.__class__.__name__, self.is_required and u' required' or '',
self.field_name, self.length, escape(data), maxlength)
self.field_name, self.length, escape(data), max_length)
def html2python(data):
return data
@ -426,14 +430,14 @@ class PasswordField(TextField):
input_type = "password"
class LargeTextField(TextField):
def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=None, maxlength=None):
def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=None, max_length=None):
if validator_list is None: validator_list = []
self.field_name = field_name
self.rows, self.cols, self.is_required = rows, cols, is_required
self.validator_list = validator_list[:]
if maxlength:
if max_length:
self.validator_list.append(self.isValidLength)
self.maxlength = maxlength
self.max_length = max_length
def render(self, data):
if data is None:
@ -502,7 +506,7 @@ class SelectField(FormField):
def isValidChoice(self, data, form):
str_data = smart_unicode(data)
str_choices = [smart_str(item[0]) for item in self.choices]
str_choices = [smart_unicode(item[0]) for item in self.choices]
if str_data not in str_choices:
raise validators.ValidationError, ugettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data': str_data, 'choices': str_choices}
@ -710,12 +714,12 @@ class ImageUploadField(FileUploadField):
####################
class IntegerField(TextField):
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None, member_name=None):
def __init__(self, field_name, length=10, max_length=None, is_required=False, validator_list=None, member_name=None):
if validator_list is None: validator_list = []
validator_list = [self.isInteger] + validator_list
if member_name is not None:
self.member_name = member_name
TextField.__init__(self, field_name, length, maxlength, is_required, validator_list)
TextField.__init__(self, field_name, length, max_length, is_required, validator_list)
def isInteger(self, field_data, all_data):
try:
@ -730,57 +734,57 @@ class IntegerField(TextField):
html2python = staticmethod(html2python)
class SmallIntegerField(IntegerField):
def __init__(self, field_name, length=5, maxlength=5, is_required=False, validator_list=None):
def __init__(self, field_name, length=5, max_length=5, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isSmallInteger] + validator_list
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list)
def isSmallInteger(self, field_data, all_data):
if not -32768 <= int(field_data) <= 32767:
raise validators.CriticalValidationError, ugettext("Enter a whole number between -32,768 and 32,767.")
class PositiveIntegerField(IntegerField):
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None):
def __init__(self, field_name, length=10, max_length=None, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isPositive] + validator_list
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list)
def isPositive(self, field_data, all_data):
if int(field_data) < 0:
raise validators.CriticalValidationError, ugettext("Enter a positive number.")
class PositiveSmallIntegerField(IntegerField):
def __init__(self, field_name, length=5, maxlength=None, is_required=False, validator_list=None):
def __init__(self, field_name, length=5, max_length=None, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isPositiveSmall] + validator_list
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list)
def isPositiveSmall(self, field_data, all_data):
if not 0 <= int(field_data) <= 32767:
raise validators.CriticalValidationError, ugettext("Enter a whole number between 0 and 32,767.")
class FloatField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [validators.isValidFloat] + validator_list
TextField.__init__(self, field_name, is_required=is_required, validator_list=validator_list)
def html2python(data):
if data == '' or data is None:
return None
return float(data)
html2python = staticmethod(html2python)
class DecimalField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [validators.isValidFloat] + validator_list
TextField.__init__(self, field_name, is_required=is_required, validator_list=validator_list)
def html2python(data):
if data == '' or data is None:
return None
return float(data)
html2python = staticmethod(html2python)
class DecimalField(TextField):
def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
self.max_digits, self.decimal_places = max_digits, decimal_places
validator_list = [self.isValidDecimal] + validator_list
# Initialise the TextField, making sure it's large enough to fit the number with a - sign and a decimal point.
super(DecimalField, self).__init__(field_name, max_digits+2, max_digits+2, is_required, validator_list)
validator_list = [self.isValidDecimal] + validator_list
# Initialise the TextField, making sure it's large enough to fit the number with a - sign and a decimal point.
super(DecimalField, self).__init__(field_name, max_digits+2, max_digits+2, is_required, validator_list)
def isValidDecimal(self, field_data, all_data):
v = validators.IsValidDecimal(self.max_digits, self.decimal_places)
def isValidDecimal(self, field_data, all_data):
v = validators.IsValidDecimal(self.max_digits, self.decimal_places)
try:
v(field_data, all_data)
except validators.ValidationError, e:
@ -789,14 +793,14 @@ class DecimalField(TextField):
def html2python(data):
if data == '' or data is None:
return None
try:
import decimal
try:
import decimal
except ImportError:
from django.utils import _decimal as decimal
try:
return decimal.Decimal(data)
except decimal.InvalidOperation, e:
raise ValueError, e
try:
return decimal.Decimal(data)
except decimal.InvalidOperation, e:
raise ValueError, e
html2python = staticmethod(html2python)
####################
@ -806,10 +810,10 @@ class DecimalField(TextField):
class DatetimeField(TextField):
"""A FormField that automatically converts its data to a datetime.datetime object.
The data should be in the format YYYY-MM-DD HH:MM:SS."""
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None):
def __init__(self, field_name, length=30, max_length=None, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
self.field_name = field_name
self.length, self.maxlength = length, maxlength
self.length, self.max_length = length, max_length
self.is_required = is_required
self.validator_list = [validators.isValidANSIDatetime] + validator_list
@ -836,7 +840,7 @@ class DateField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isValidDate] + validator_list
TextField.__init__(self, field_name, length=10, maxlength=10,
TextField.__init__(self, field_name, length=10, max_length=10,
is_required=is_required, validator_list=validator_list)
def isValidDate(self, field_data, all_data):
@ -861,7 +865,7 @@ class TimeField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isValidTime] + validator_list
TextField.__init__(self, field_name, length=8, maxlength=8,
TextField.__init__(self, field_name, length=8, max_length=8,
is_required=is_required, validator_list=validator_list)
def isValidTime(self, field_data, all_data):
@ -893,10 +897,10 @@ class TimeField(TextField):
class EmailField(TextField):
"A convenience FormField for validating e-mail addresses"
def __init__(self, field_name, length=50, maxlength=75, is_required=False, validator_list=None):
def __init__(self, field_name, length=50, max_length=75, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isValidEmail] + validator_list
TextField.__init__(self, field_name, length, maxlength=maxlength,
TextField.__init__(self, field_name, length, max_length=max_length,
is_required=is_required, validator_list=validator_list)
def isValidEmail(self, field_data, all_data):
@ -907,10 +911,10 @@ class EmailField(TextField):
class URLField(TextField):
"A convenience FormField for validating URLs"
def __init__(self, field_name, length=50, maxlength=200, is_required=False, validator_list=None):
def __init__(self, field_name, length=50, max_length=200, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isValidURL] + validator_list
TextField.__init__(self, field_name, length=length, maxlength=maxlength,
TextField.__init__(self, field_name, length=length, max_length=max_length,
is_required=is_required, validator_list=validator_list)
def isValidURL(self, field_data, all_data):
@ -920,10 +924,10 @@ class URLField(TextField):
raise validators.CriticalValidationError, e.messages
class IPAddressField(TextField):
def __init__(self, field_name, length=15, maxlength=15, is_required=False, validator_list=None):
def __init__(self, field_name, length=15, max_length=15, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isValidIPAddress] + validator_list
TextField.__init__(self, field_name, length=length, maxlength=maxlength,
TextField.__init__(self, field_name, length=length, max_length=max_length,
is_required=is_required, validator_list=validator_list)
def isValidIPAddress(self, field_data, all_data):
@ -970,7 +974,7 @@ class PhoneNumberField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isValidPhone] + validator_list
TextField.__init__(self, field_name, length=12, maxlength=12,
TextField.__init__(self, field_name, length=12, max_length=12,
is_required=is_required, validator_list=validator_list)
def isValidPhone(self, field_data, all_data):
@ -984,7 +988,7 @@ class USStateField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isValidUSState] + validator_list
TextField.__init__(self, field_name, length=2, maxlength=2,
TextField.__init__(self, field_name, length=2, max_length=2,
is_required=is_required, validator_list=validator_list)
def isValidUSState(self, field_data, all_data):
@ -1001,10 +1005,10 @@ class USStateField(TextField):
class CommaSeparatedIntegerField(TextField):
"A convenience FormField for validating comma-separated integer fields"
def __init__(self, field_name, maxlength=None, is_required=False, validator_list=None):
def __init__(self, field_name, max_length=None, is_required=False, validator_list=None):
if validator_list is None: validator_list = []
validator_list = [self.isCommaSeparatedIntegerList] + validator_list
TextField.__init__(self, field_name, length=20, maxlength=maxlength,
TextField.__init__(self, field_name, length=20, max_length=max_length,
is_required=is_required, validator_list=validator_list)
def isCommaSeparatedIntegerList(self, field_data, all_data):

View File

@ -1,32 +1,62 @@
# This module collects helper functions and classes that "span" multiple levels
# of MVC. In other words, these functions/classes introduce controlled coupling
# for convenience's sake.
"""
This module collects helper functions and classes that "span" multiple levels
of MVC. In other words, these functions/classes introduce controlled coupling
for convenience's sake.
"""
from django.template import loader
from django.http import HttpResponse, Http404
from django.db.models.manager import Manager
from django.db.models.query import QuerySet
def render_to_response(*args, **kwargs):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
return HttpResponse(loader.render_to_string(*args, **kwargs))
load_and_render = render_to_response # For backwards compatibility.
def get_object_or_404(klass, *args, **kwargs):
if isinstance(klass, Manager):
def _get_queryset(klass):
"""
Returns a QuerySet from a Model, Manager, or QuerySet. Created to make
get_object_or_404 and get_list_or_404 more DRY.
"""
if isinstance(klass, QuerySet):
return klass
elif isinstance(klass, Manager):
manager = klass
klass = manager.model
else:
manager = klass._default_manager
return manager.all()
def get_object_or_404(klass, *args, **kwargs):
"""
Uses get() to return an object, or raises a Http404 exception if the object
does not exist.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.
Note: Like with get(), an AssertionError will be raised if more than one
object is found.
"""
queryset = _get_queryset(klass)
try:
return manager.get(*args, **kwargs)
except klass.DoesNotExist:
raise Http404('No %s matches the given query.' % klass._meta.object_name)
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
def get_list_or_404(klass, *args, **kwargs):
if isinstance(klass, Manager):
manager = klass
else:
manager = klass._default_manager
obj_list = list(manager.filter(*args, **kwargs))
"""
Uses filter() to return a list of objects, or raise a Http404 exception if
the list is empty.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the filter() query.
"""
queryset = _get_queryset(klass)
obj_list = list(queryset.filter(*args, **kwargs))
if not obj_list:
raise Http404('No %s matches the given query.' % manager.model._meta.object_name)
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
return obj_list

View File

@ -512,7 +512,7 @@ filter_raw_string = r"""
)?
)""" % {
'str': r"""[^"\\]*(?:\\.[^"\\]*)*""",
'var_chars': "A-Za-z0-9\_\." ,
'var_chars': "\w\." ,
'filter_sep': re.escape(FILTER_SEPARATOR),
'arg_sep': re.escape(FILTER_ARGUMENT_SEPARATOR),
'i18n_open' : re.escape("_("),
@ -520,7 +520,7 @@ filter_raw_string = r"""
}
filter_raw_string = filter_raw_string.replace("\n", "").replace(" ", "")
filter_re = re.compile(filter_raw_string)
filter_re = re.compile(filter_raw_string, re.UNICODE)
class FilterExpression(object):
"""

View File

@ -556,7 +556,7 @@ def pprint(value):
try:
return pformat(value)
except Exception, e:
return u"Error in formatting:%s" % force_unicode(e)
return u"Error in formatting: %s" % force_unicode(e, errors="replace")
# Syntax: register.filter(name of filter, callback)
register.filter(add)

View File

@ -649,8 +649,8 @@ def do_if(parser, token):
As you can see, the ``if`` tag can take an option ``{% else %}`` clause that
will be displayed if the test fails.
``if`` tags may use ``or`` or ``not`` to test a number of variables or to
negate a given variable::
``if`` tags may use ``or``, ``and`` or ``not`` to test a number of
variables or to negate a given variable::
{% if not athlete_list %}
There are no athletes.
@ -660,19 +660,32 @@ def do_if(parser, token):
There are some athletes or some coaches.
{% endif %}
{% if athlete_list and coach_list %}
Both atheletes and coaches are available.
{% endif %}
{% if not athlete_list or coach_list %}
There are no athletes, or there are some coaches.
{% endif %}
For simplicity, ``if`` tags do not allow ``and`` clauses. Use nested ``if``
tags instead::
{% if athlete_list %}
{% if coach_list %}
Number of athletes: {{ athlete_list|count }}.
Number of coaches: {{ coach_list|count }}.
{% endif %}
{% if athlete_list and not coach_list %}
There are some athletes and absolutely no coaches.
{% endif %}
``if`` tags do not allow ``and`` and ``or`` clauses with the same
tag, because the order of logic would be ambigous. For example,
this is invalid::
{% if athlete_list and coach_list or cheerleader_list %}
If you need to combine and and or to do advanced logic, just use
nested if tags. For example:
{% if athlete_list %}
{% if coach_list or cheerleader_list %}
We have athletes, and either coaches or cheerleaders!
{% endif %}
{% endif %}
"""
bits = token.contents.split()
del bits[0]

View File

@ -1,9 +1,14 @@
# Wrapper for loading templates from "template" directories in installed app packages.
"""
Wrapper for loading templates from "template" directories in INSTALLED_APPS
packages.
"""
import os
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.template import TemplateDoesNotExist
import os
from django.utils._os import safe_join
# At compile time, cache the directories to search.
app_template_dirs = []
@ -28,8 +33,14 @@ for app in settings.INSTALLED_APPS:
app_template_dirs = tuple(app_template_dirs)
def get_template_sources(template_name, template_dirs=None):
for template_dir in app_template_dirs:
yield os.path.join(template_dir, template_name)
if not template_dirs:
template_dirs = app_template_dirs
for template_dir in template_dirs:
try:
yield safe_join(template_dir, template_name)
except ValueError:
# The joined path was located outside of template_dir.
pass
def load_template_source(template_name, template_dirs=None):
for filepath in get_template_sources(template_name, template_dirs):

View File

@ -1,14 +1,20 @@
# Wrapper for loading templates from the filesystem.
"""
Wrapper for loading templates from the filesystem.
"""
from django.conf import settings
from django.template import TemplateDoesNotExist
import os
from django.utils._os import safe_join
def get_template_sources(template_name, template_dirs=None):
if not template_dirs:
template_dirs = settings.TEMPLATE_DIRS
for template_dir in template_dirs:
yield os.path.join(template_dir, template_name)
try:
yield safe_join(template_dir, template_name)
except ValueError:
# The joined path was located outside of template_dir.
pass
def load_template_source(template_name, template_dirs=None):
tried = []

View File

@ -195,7 +195,7 @@ class Client:
'CONTENT_LENGTH': None,
'CONTENT_TYPE': 'text/html; charset=utf-8',
'PATH_INFO': path,
'QUERY_STRING': urlencode(data),
'QUERY_STRING': urlencode(data, doseq=True),
'REQUEST_METHOD': 'GET',
}
r.update(extra)
@ -225,10 +225,11 @@ class Client:
"""Set the Client to appear as if it has sucessfully logged into a site.
Returns True if login is possible; False if the provided credentials
are incorrect, or if the Sessions framework is not available.
are incorrect, or the user is inactive, or if the sessions framework is
not available.
"""
user = authenticate(**credentials)
if user and 'django.contrib.sessions' in settings.INSTALLED_APPS:
if user and user.is_active and 'django.contrib.sessions' in settings.INSTALLED_APPS:
obj = Session.objects.get_new_session_object()
# Create a fake request to store login details

View File

@ -1,5 +1,6 @@
import unittest
from django.conf import settings
from django.db.models import get_app, get_apps
from django.test import _doctest as doctest
from django.test.utils import setup_test_environment, teardown_test_environment
from django.test.utils import create_test_db, destroy_test_db
@ -10,34 +11,10 @@ TEST_MODULE = 'tests'
doctestOutputChecker = OutputChecker()
def build_suite(app_module):
"Create a complete Django test suite for the provided application module"
suite = unittest.TestSuite()
# Load unit and doctests in the models.py file
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(app_module))
try:
suite.addTest(doctest.DocTestSuite(app_module,
checker=doctestOutputChecker,
runner=DocTestRunner))
except ValueError:
# No doc tests in models.py
pass
# Check to see if a separate 'tests' module exists parallel to the
# models module
def get_tests(app_module):
try:
app_path = app_module.__name__.split('.')[:-1]
test_module = __import__('.'.join(app_path + [TEST_MODULE]), {}, {}, TEST_MODULE)
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module))
try:
suite.addTest(doctest.DocTestSuite(test_module,
checker=doctestOutputChecker,
runner=DocTestRunner))
except ValueError:
# No doc tests in tests.py
pass
except ImportError, e:
# Couldn't import tests.py. Was it due to a missing file, or
# due to an import error in a tests.py that actually exists?
@ -47,7 +24,7 @@ def build_suite(app_module):
mod = find_module(TEST_MODULE, [os.path.dirname(app_module.__file__)])
except ImportError:
# 'tests' module doesn't exist. Move on.
pass
test_module = None
else:
# The module exists, so there must be an import error in the
# test module itself. We don't need the module; so if the
@ -57,15 +34,87 @@ def build_suite(app_module):
if mod[0]:
mod[0].close()
raise
return test_module
def build_suite(app_module):
"Create a complete Django test suite for the provided application module"
suite = unittest.TestSuite()
# Load unit and doctests in the models.py module. If module has
# a suite() method, use it. Otherwise build the test suite ourselves.
if hasattr(app_module, 'suite'):
suite.addTest(app_module.suite())
else:
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(app_module))
try:
suite.addTest(doctest.DocTestSuite(app_module,
checker=doctestOutputChecker,
runner=DocTestRunner))
except ValueError:
# No doc tests in models.py
pass
# Check to see if a separate 'tests' module exists parallel to the
# models module
test_module = get_tests(app_module)
if test_module:
# Load unit and doctests in the tests.py module. If module has
# a suite() method, use it. Otherwise build the test suite ourselves.
if hasattr(test_module, 'suite'):
suite.addTest(test_module.suite())
else:
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module))
try:
suite.addTest(doctest.DocTestSuite(test_module,
checker=doctestOutputChecker,
runner=DocTestRunner))
except ValueError:
# No doc tests in tests.py
pass
return suite
def run_tests(module_list, verbosity=1, extra_tests=[]):
def build_test(label):
"""Construct a test case a test with the specified label. Label should
be of the form model.TestClass or model.TestClass.test_method. Returns
an instantiated test or test suite corresponding to the label provided.
"""
Run the unit tests for all the modules in the provided list.
This testrunner will search each of the modules in the provided list,
looking for doctests and unittests in models.py or tests.py within
the module. A list of 'extra' tests may also be provided; these tests
parts = label.split('.')
if len(parts) < 2 or len(parts) > 3:
raise ValueError("Test label '%s' should be of the form app.TestCase or app.TestCase.test_method" % label)
app_module = get_app(parts[0])
TestClass = getattr(app_module, parts[1], None)
# Couldn't find the test class in models.py; look in tests.py
if TestClass is None:
test_module = get_tests(app_module)
if test_module:
TestClass = getattr(test_module, parts[1], None)
if len(parts) == 2: # label is app.TestClass
try:
return unittest.TestLoader().loadTestsFromTestCase(TestClass)
except TypeError:
raise ValueError("Test label '%s' does not refer to a test class" % label)
else: # label is app.TestClass.test_method
return TestClass(parts[2])
def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[]):
"""
Run the unit tests for all the test labels in the provided list.
Labels must be of the form:
- app.TestClass.test_method
Run a single specific test method
- app.TestClass
Run all the test methods in a given class
- app
Search for doctests and unittests in the named application.
When looking for tests, the test runner will look in the models and
tests modules for the application.
A list of 'extra' tests may also be provided; these tests
will be added to the test suite.
Returns the number of tests that failed.
@ -74,15 +123,23 @@ def run_tests(module_list, verbosity=1, extra_tests=[]):
settings.DEBUG = False
suite = unittest.TestSuite()
for module in module_list:
suite.addTest(build_suite(module))
if test_labels:
for label in test_labels:
if '.' in label:
suite.addTest(build_test(label))
else:
app = get_app(label)
suite.addTest(build_suite(app))
else:
for app in get_apps():
suite.addTest(build_suite(app))
for test in extra_tests:
suite.addTest(test)
old_name = settings.DATABASE_NAME
create_test_db(verbosity)
create_test_db(verbosity, autoclobber=not interactive)
result = unittest.TextTestRunner(verbosity=verbosity).run(suite)
destroy_test_db(old_name, verbosity)

Some files were not shown because too many files have changed in this diff Show More