mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	queryset-refactor: Merged from trunk up to [7122].
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7124 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		
							
								
								
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -168,6 +168,7 @@ answer newbie questions, and generally made Django that much better: | ||||
|     Rob Hudson <http://rob.cogit8.org/> | ||||
|     Jason Huggins <http://www.jrandolph.com/blog/> | ||||
|     Hyun Mi Ae | ||||
|     Ibon <ibonso@gmail.com> | ||||
|     Tom Insam | ||||
|     Baurzhan Ismagulov <ibr@radix50.net> | ||||
|     james_027@yahoo.com | ||||
|   | ||||
| @@ -48,6 +48,7 @@ LANGUAGES = ( | ||||
|     ('en', gettext_noop('English')), | ||||
|     ('es', gettext_noop('Spanish')), | ||||
|     ('es-ar', gettext_noop('Argentinean Spanish')), | ||||
|     ('eu', gettext_noop('Basque')), | ||||
|     ('fa', gettext_noop('Persian')), | ||||
|     ('fi', gettext_noop('Finnish')), | ||||
|     ('fr', gettext_noop('French')), | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								django/conf/locale/eu/LC_MESSAGES/django.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								django/conf/locale/eu/LC_MESSAGES/django.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										4248
									
								
								django/conf/locale/eu/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4248
									
								
								django/conf/locale/eu/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								django/conf/locale/eu/LC_MESSAGES/djangojs.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								django/conf/locale/eu/LC_MESSAGES/djangojs.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										117
									
								
								django/conf/locale/eu/LC_MESSAGES/djangojs.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								django/conf/locale/eu/LC_MESSAGES/djangojs.po
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| # Spanish translation for the django-admin JS files. | ||||
| # Copyright (C) | ||||
| # This file is distributed under the same license as the PACKAGE package. | ||||
| # | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: Django JavaScript 1.0\n" | ||||
| "Report-Msgid-Bugs-To: \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=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 "" | ||||
| "Urtarrila Otsaila Martxoa Apirila Maiatza Ekaina Uztaila Abuztua Iraila Urria " | ||||
| "Azaroa Abendua" | ||||
|  | ||||
| #: contrib/admin/media/js/calendar.js:25 | ||||
| msgid "S M T W T F S" | ||||
| msgstr "I A A A O O L" | ||||
|  | ||||
| #: contrib/admin/media/js/dateparse.js:33 | ||||
| msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" | ||||
| msgstr "Igandea Astelehene Asteartea Asteazkena Osteguna Ostirala Larunbata" | ||||
|  | ||||
| #: contrib/admin/media/js/SelectFilter2.js:33 | ||||
| #, perl-format | ||||
| msgid "Available %s" | ||||
| msgstr "%s Erabilgarri" | ||||
|  | ||||
| #: contrib/admin/media/js/SelectFilter2.js:41 | ||||
| msgid "Choose all" | ||||
| msgstr "Denak aukeratu" | ||||
|  | ||||
| #: contrib/admin/media/js/SelectFilter2.js:46 | ||||
| msgid "Add" | ||||
| msgstr "Gehitu" | ||||
|  | ||||
| #: contrib/admin/media/js/SelectFilter2.js:48 | ||||
| msgid "Remove" | ||||
| msgstr "Ezabatu" | ||||
|  | ||||
| #: contrib/admin/media/js/SelectFilter2.js:53 | ||||
| #, perl-format | ||||
| msgid "Chosen %s" | ||||
| msgstr "%s Aukeratuak" | ||||
|  | ||||
| #: contrib/admin/media/js/SelectFilter2.js:54 | ||||
| msgid "Select your choice(s) and click " | ||||
| msgstr "Egin zure aukerak eta click egin " | ||||
|  | ||||
| #: contrib/admin/media/js/SelectFilter2.js:59 | ||||
| msgid "Clear all" | ||||
| msgstr "Denak garbitu" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:47 | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 | ||||
| msgid "Now" | ||||
| msgstr "Orain" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:51 | ||||
| msgid "Clock" | ||||
| msgstr "Erlojua" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:78 | ||||
| msgid "Choose a time" | ||||
| msgstr "Aukeratu ordu bat" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:82 | ||||
| msgid "Midnight" | ||||
| msgstr "Gauerdia" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 | ||||
| msgid "6 a.m." | ||||
| msgstr "6 a.m." | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:84 | ||||
| msgid "Noon" | ||||
| msgstr "Eguerdia" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:88 | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:183 | ||||
| msgid "Cancel" | ||||
| msgstr "Atzera" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:128 | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:177 | ||||
| msgid "Today" | ||||
| msgstr "Gaur" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:132 | ||||
| msgid "Calendar" | ||||
| msgstr "Egutegia" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:175 | ||||
| msgid "Yesterday" | ||||
| msgstr "Atzo" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/DateTimeShortcuts.js:179 | ||||
| msgid "Tomorrow" | ||||
| msgstr "Bihar" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/CollapsedFieldsets.js:34 | ||||
| #: contrib/admin/media/js/admin/CollapsedFieldsets.js:72 | ||||
| msgid "Show" | ||||
| msgstr "Erakutsi" | ||||
|  | ||||
| #: contrib/admin/media/js/admin/CollapsedFieldsets.js:63 | ||||
| msgid "Hide" | ||||
| msgstr "Izkutatu" | ||||
| @@ -1,7 +1,7 @@ | ||||
| from django.core.management.base import AppCommand | ||||
|  | ||||
| class Command(AppCommand): | ||||
|     help = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)." | ||||
|     help = "Prints the CREATE TABLE, custom SQL and CREATE INDEX SQL statements for the given model module name(s)." | ||||
|  | ||||
|     output_transaction = True | ||||
|  | ||||
|   | ||||
| @@ -41,7 +41,9 @@ class ModelBase(type): | ||||
|  | ||||
|         # Build complete list of parents | ||||
|         for base in parents: | ||||
|             if base is not Model: | ||||
|             # Things without _meta aren't functional models, so they're | ||||
|             # uninteresting parents. | ||||
|             if hasattr(base, '_meta'): | ||||
|                 new_class._meta.parents.append(base) | ||||
|                 new_class._meta.parents.extend(base._meta.parents) | ||||
|  | ||||
| @@ -139,7 +141,7 @@ class Model(object): | ||||
|         # There is a rather weird disparity here; if kwargs, it's set, then args | ||||
|         # overrides it. It should be one or the other; don't duplicate the work | ||||
|         # The reason for the kwargs check is that standard iterator passes in by | ||||
|         # args, and nstantiation for iteration is 33% faster. | ||||
|         # args, and instantiation for iteration is 33% faster. | ||||
|         args_len = len(args) | ||||
|         if args_len > len(self._meta.fields): | ||||
|             # Daft, but matches old exception sans the err msg. | ||||
|   | ||||
| @@ -22,23 +22,40 @@ def pretty_name(name): | ||||
|     name = name[0].upper() + name[1:] | ||||
|     return name.replace('_', ' ') | ||||
|  | ||||
| def get_declared_fields(bases, attrs, with_base_fields=True): | ||||
|     """ | ||||
|     Create a list of form field instances from the passed in 'attrs', plus any | ||||
|     similar fields on the base classes (in 'bases'). This is used by both the | ||||
|     Form and ModelForm metclasses. | ||||
|  | ||||
|     If 'with_base_fields' is True, all fields from the bases are used. | ||||
|     Otherwise, only fields in the 'declared_fields' attribute on the bases are | ||||
|     used. The distinction is useful in ModelForm subclassing. | ||||
|     """ | ||||
|     fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)] | ||||
|     fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter)) | ||||
|  | ||||
|     # If this class is subclassing another Form, add that Form's fields. | ||||
|     # Note that we loop over the bases in *reverse*. This is necessary in | ||||
|     # order to preserve the correct order of fields. | ||||
|     if with_base_fields: | ||||
|         for base in bases[::-1]: | ||||
|             if hasattr(base, 'base_fields'): | ||||
|                 fields = base.base_fields.items() + fields | ||||
|     else: | ||||
|         for base in bases[::-1]: | ||||
|             if hasattr(base, 'declared_fields'): | ||||
|                 fields = base.declared_fields.items() + fields | ||||
|  | ||||
|     return SortedDict(fields) | ||||
|  | ||||
| class DeclarativeFieldsMetaclass(type): | ||||
|     """ | ||||
|     Metaclass that converts Field attributes to a dictionary called | ||||
|     'base_fields', taking into account parent class 'base_fields' as well. | ||||
|     """ | ||||
|     def __new__(cls, name, bases, attrs): | ||||
|         fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)] | ||||
|         fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter)) | ||||
|  | ||||
|         # If this class is subclassing another Form, add that Form's fields. | ||||
|         # Note that we loop over the bases in *reverse*. This is necessary in | ||||
|         # order to preserve the correct order of fields. | ||||
|         for base in bases[::-1]: | ||||
|             if hasattr(base, 'base_fields'): | ||||
|                 fields = base.base_fields.items() + fields | ||||
|  | ||||
|         attrs['base_fields'] = SortedDict(fields) | ||||
|         attrs['base_fields'] = get_declared_fields(bases, attrs) | ||||
|         return type.__new__(cls, name, bases, attrs) | ||||
|  | ||||
| class BaseForm(StrAndUnicode): | ||||
|   | ||||
| @@ -11,7 +11,7 @@ from django.utils.datastructures import SortedDict | ||||
| from django.core.exceptions import ImproperlyConfigured | ||||
|  | ||||
| from util import ValidationError, ErrorList | ||||
| from forms import BaseForm | ||||
| from forms import BaseForm, get_declared_fields | ||||
| from fields import Field, ChoiceField, EMPTY_VALUES | ||||
| from widgets import Select, SelectMultiple, MultipleHiddenInput | ||||
|  | ||||
| @@ -211,57 +211,39 @@ class ModelFormOptions(object): | ||||
|         self.fields = getattr(options, 'fields', None) | ||||
|         self.exclude = getattr(options, 'exclude', None) | ||||
|  | ||||
|  | ||||
| class ModelFormMetaclass(type): | ||||
|     def __new__(cls, name, bases, attrs, | ||||
|                 formfield_callback=lambda f: f.formfield()): | ||||
|         fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)] | ||||
|         fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter)) | ||||
|         try: | ||||
|             parents = [b for b in bases if issubclass(b, ModelForm)] | ||||
|         except NameError: | ||||
|             # We are defining ModelForm itself. | ||||
|             parents = None | ||||
|         if not parents: | ||||
|             return super(ModelFormMetaclass, cls).__new__(cls, name, bases, | ||||
|                     attrs) | ||||
|  | ||||
|         # If this class is subclassing another Form, add that Form's fields. | ||||
|         # Note that we loop over the bases in *reverse*. This is necessary in | ||||
|         # order to preserve the correct order of fields. | ||||
|         for base in bases[::-1]: | ||||
|             if hasattr(base, 'base_fields'): | ||||
|                 fields = base.base_fields.items() + fields | ||||
|         declared_fields = SortedDict(fields) | ||||
|  | ||||
|         opts = ModelFormOptions(attrs.get('Meta', None)) | ||||
|         attrs['_meta'] = opts | ||||
|  | ||||
|         # Don't allow more than one Meta model definition in bases. The fields | ||||
|         # would be generated correctly, but the save method won't deal with | ||||
|         # more than one object. | ||||
|         base_models = [] | ||||
|         for base in bases: | ||||
|             base_opts = getattr(base, '_meta', None) | ||||
|             base_model = getattr(base_opts, 'model', None) | ||||
|             if base_model is not None: | ||||
|                 base_models.append(base_model) | ||||
|         if len(base_models) > 1: | ||||
|             raise ImproperlyConfigured("%s's base classes define more than one model." % name) | ||||
|  | ||||
|         # If a model is defined, extract form fields from it and add them to base_fields | ||||
|         if attrs['_meta'].model is not None: | ||||
|             # Don't allow a subclass to define a different Meta model than a | ||||
|             # parent class has. Technically the right fields would be generated, | ||||
|             # but the save method will not deal with more than one model. | ||||
|             for base in bases: | ||||
|                 base_opts = getattr(base, '_meta', None) | ||||
|                 base_model = getattr(base_opts, 'model', None) | ||||
|                 if base_model and base_model is not opts.model: | ||||
|                     raise ImproperlyConfigured('%s defines a different model than its parent.' % name) | ||||
|             model_fields = fields_for_model(opts.model, opts.fields, | ||||
|                     opts.exclude, formfield_callback) | ||||
|             # fields declared in base classes override fields from the model | ||||
|             model_fields.update(declared_fields) | ||||
|             attrs['base_fields'] = model_fields | ||||
|         new_class = type.__new__(cls, name, bases, attrs) | ||||
|         declared_fields = get_declared_fields(bases, attrs, False) | ||||
|         opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None)) | ||||
|         if opts.model: | ||||
|             # If a model is defined, extract form fields from it. | ||||
|             fields = fields_for_model(opts.model, opts.fields, | ||||
|                                       opts.exclude, formfield_callback) | ||||
|             # Override default model fields with any custom declared ones | ||||
|             # (plus, include all the other declared fields). | ||||
|             fields.update(declared_fields) | ||||
|         else: | ||||
|             attrs['base_fields'] = declared_fields | ||||
|         return type.__new__(cls, name, bases, attrs) | ||||
|             fields = declared_fields | ||||
|         new_class.declared_fields = declared_fields | ||||
|         new_class.base_fields = fields | ||||
|         return new_class | ||||
|  | ||||
| class BaseModelForm(BaseForm): | ||||
|     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, | ||||
|                  initial=None, error_class=ErrorList, label_suffix=':', instance=None): | ||||
|                  initial=None, error_class=ErrorList, label_suffix=':', | ||||
|                  instance=None): | ||||
|         opts = self._meta | ||||
|         if instance is None: | ||||
|             # if we didn't get an instance, instantiate a new one | ||||
| @@ -277,7 +259,8 @@ class BaseModelForm(BaseForm): | ||||
|  | ||||
|     def save(self, commit=True): | ||||
|         """ | ||||
|         Saves this ``form``'s cleaned_data into model instance ``self.instance``. | ||||
|         Saves this ``form``'s cleaned_data into model instance | ||||
|         ``self.instance``. | ||||
|  | ||||
|         If commit=True, then the changes to ``instance`` will be saved to the | ||||
|         database. Returns ``instance``. | ||||
|   | ||||
| @@ -3,7 +3,7 @@ class MergeDict(object): | ||||
|     A simple class for creating new "virtual" dictionaries that actually look | ||||
|     up values in more than one dictionary, passed in the constructor. | ||||
|  | ||||
|     If a key appears in more than one of the passed in dictionaries, only the | ||||
|     If a key appears in more than one of the given dictionaries, only the | ||||
|     first occurrence will be used. | ||||
|     """ | ||||
|     def __init__(self, *dicts): | ||||
|   | ||||
| @@ -88,7 +88,7 @@ change: | ||||
|      API changes may be necessary. | ||||
|  | ||||
|    - Generic relations will most likely be moved out of core and into the | ||||
|      content-types contrib package to avoid core dependancies on optional | ||||
|      content-types contrib package to avoid core dependencies on optional | ||||
|      components. | ||||
|  | ||||
|    - The comments framework, which is yet undocumented, will likely get a complete | ||||
|   | ||||
| @@ -215,7 +215,7 @@ each ``TaggedItem`` will have a ``content_object`` field that returns the | ||||
| object it's related to, and you can also assign to that field or use it when | ||||
| creating a ``TaggedItem``:: | ||||
|  | ||||
|     >>> from django.contrib.models.auth import User | ||||
|     >>> from django.contrib.auth.models import User | ||||
|     >>> guido = User.objects.get(username='Guido') | ||||
|     >>> t = TaggedItem(content_object=guido, tag='bdfl') | ||||
|     >>> t.save() | ||||
| @@ -235,7 +235,7 @@ a "reverse" generic relationship to enable an additional API. For example:: | ||||
| ``Bookmark`` instances will each have a ``tags`` attribute, which can | ||||
| be used to retrieve their associated ``TaggedItems``:: | ||||
|  | ||||
|     >>> b = Bookmark('http://www.djangoproject.com/') | ||||
|     >>> b = Bookmark(url='http://www.djangoproject.com/') | ||||
|     >>> b.save() | ||||
|     >>> t1 = TaggedItem(content_object=b, tag='django') | ||||
|     >>> t1.save() | ||||
|   | ||||
| @@ -5,7 +5,7 @@ Third-party distributions of Django | ||||
| Several third-party distributors are now providing versions of Django integrated | ||||
| with their package-management systems. These can make installation and upgrading | ||||
| much easier for users of Django since the integration includes the ability to | ||||
| automatically install dependancies (like database adapters) that Django | ||||
| automatically install dependencies (like database adapters) that Django | ||||
| requires. | ||||
|  | ||||
| Typically, these packages are based on the latest stable release of Django, so | ||||
|   | ||||
| @@ -717,7 +717,7 @@ in Python package syntax, e.g. ``mysite.settings``. If this isn't provided, | ||||
| variable. | ||||
|  | ||||
| Note that this option is unnecessary in ``manage.py``, because it uses | ||||
| ``settings.py`` from the current project by default.  | ||||
| ``settings.py`` from the current project by default. | ||||
|  | ||||
| Extra niceties | ||||
| ============== | ||||
| @@ -765,9 +765,9 @@ a command that can be executed as an action when you run ``manage.py``:: | ||||
|                 __init__.py | ||||
|                 explode.py | ||||
|         views.py | ||||
|          | ||||
|  | ||||
| In this example, the ``explode`` command will be made available to any project | ||||
| that includes the ``fancy_blog`` application in ``settings.INSTALLED_APPS``. | ||||
| that includes the ``blog`` application in ``settings.INSTALLED_APPS``. | ||||
|  | ||||
| The ``explode.py`` module has only one requirement -- it must define a class | ||||
| called ``Command`` that extends ``django.core.management.base.BaseCommand``. | ||||
|   | ||||
| @@ -138,7 +138,7 @@ Installing a distribution-specific package | ||||
| Check the `distribution specific notes`_ to see if your | ||||
| platform/distribution provides official Django packages/installers. | ||||
| Distribution-provided packages will typically allow for automatic | ||||
| installation of dependancies and easy upgrade paths. | ||||
| installation of dependencies and easy upgrade paths. | ||||
|  | ||||
| Installing an official release | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|   | ||||
| @@ -384,7 +384,7 @@ The admin represents this as an ``<input type="text">`` (a single-line input). | ||||
| ``IPAddressField`` | ||||
| ~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| An IP address, in string format (i.e. "24.124.1.30"). | ||||
| An IP address, in string format (e.g. "192.0.2.30"). | ||||
|  | ||||
| The admin represents this as an ``<input type="text">`` (a single-line input). | ||||
|  | ||||
| @@ -952,10 +952,10 @@ the relationship should work. All are optional: | ||||
|     ``limit_choices_to``     See the description under ``ForeignKey`` above. | ||||
|  | ||||
|     ``symmetrical``          Only used in the definition of ManyToManyFields on self. | ||||
|                              Consider the following model: | ||||
|                              Consider the following model:: | ||||
|  | ||||
|                              class Person(models.Model): | ||||
|                                  friends = models.ManyToManyField("self") | ||||
|                                  class Person(models.Model): | ||||
|                                      friends = models.ManyToManyField("self") | ||||
|  | ||||
|                              When Django processes this model, it identifies that it has | ||||
|                              a ``ManyToManyField`` on itself, and as a result, it | ||||
| @@ -1871,7 +1871,7 @@ more simply as:: | ||||
|  | ||||
| If you define a ``__unicode__()`` method on your model and not a ``__str__()`` | ||||
| method, Django will automatically provide you with a ``__str__()`` that calls | ||||
| ``__unicode()__`` and then converts the result correctly to a UTF-8 encoded | ||||
| ``__unicode__()`` and then converts the result correctly to a UTF-8 encoded | ||||
| string object. This is recommended development practice: define only | ||||
| ``__unicode__()`` and let Django take care of the conversion to string objects | ||||
| when required. | ||||
|   | ||||
| @@ -320,3 +320,41 @@ parameter when declaring the form field:: | ||||
|    ... | ||||
|    ...     class Meta: | ||||
|    ...         model = Article | ||||
|  | ||||
| Form inheritance | ||||
| ---------------- | ||||
|  | ||||
| As with basic forms, you can extend and reuse ``ModelForms`` by inheriting | ||||
| them. This is useful if you need to declare extra fields or extra methods on a | ||||
| parent class for use in a number of forms derived from models. For example, | ||||
| using the previous ``ArticleForm`` class:: | ||||
|  | ||||
|     >>> class EnhancedArticleForm(ArticleForm): | ||||
|     ...     def clean_pub_date(self): | ||||
|     ...         ... | ||||
|  | ||||
| This creates a form that behaves identically to ``ArticleForm``, except there's | ||||
| some extra validation and cleaning for the ``pub_date`` field. | ||||
|  | ||||
| You can also subclass the parent's ``Meta`` inner class if you want to change | ||||
| the ``Meta.fields`` or ``Meta.excludes`` lists:: | ||||
|  | ||||
|     >>> class RestrictedArticleForm(EnhancedArticleForm): | ||||
|     ...     class Meta(ArticleForm.Meta): | ||||
|     ...         exclude = ['body'] | ||||
|  | ||||
| This adds the extra method from the ``EnhancedArticleForm`` and modifies | ||||
| the original ``ArticleForm.Meta`` to remove one field. | ||||
|  | ||||
| There are a couple of things to note, however. | ||||
|  | ||||
|  * Normal Python name resolution rules apply. If you have multiple base | ||||
|    classes that declare a ``Meta`` inner class, only the first one will be | ||||
|    used. This means the child's ``Meta``, if it exists, otherwise the | ||||
|    ``Meta`` of the first parent, etc. | ||||
|  | ||||
|  * For technical reasons, a subclass cannot inherit from both a ``ModelForm`` | ||||
|    and a ``Form`` simultaneously. | ||||
|  | ||||
| Chances are these notes won't affect you unless you're trying to do something | ||||
| tricky with subclassing. | ||||
|   | ||||
| @@ -576,7 +576,7 @@ Three things to note about 404 views: | ||||
|       in the 404. | ||||
|  | ||||
|     * The 404 view is passed a ``RequestContext`` and will have access to | ||||
|       variables supplied by your ``TEMPLATE_CONTEXT_PROCESSORS`` (e.g. | ||||
|       variables supplied by your ``TEMPLATE_CONTEXT_PROCESSORS`` setting (e.g., | ||||
|       ``MEDIA_URL``). | ||||
|  | ||||
|     * If ``DEBUG`` is set to ``True`` (in your settings module), then your 404 | ||||
|   | ||||
| @@ -30,9 +30,9 @@ Optional arguments | ||||
| ``context_instance`` | ||||
|     The context instance to render the template with. By default, the template | ||||
|     will be rendered with a ``Context`` instance (filled with values from | ||||
|     ``dictionary``). If you need to use `context processors`_, you will want to | ||||
|     render the template with a ``RequestContext`` instance instead. Your code | ||||
|     might look something like this:: | ||||
|     ``dictionary``). If you need to use `context processors`_, render the | ||||
|     template with a ``RequestContext`` instance instead. Your code might look | ||||
|     something like this:: | ||||
|  | ||||
|         return render_to_response('my_template.html', | ||||
|                                   my_data_dictionary, | ||||
|   | ||||
| @@ -1406,6 +1406,8 @@ Joins a list with a string, like Python's ``str.join(list)``. | ||||
| last | ||||
| ~~~~ | ||||
|  | ||||
| **New in Django development version.** | ||||
|  | ||||
| Returns the last item in a list. | ||||
|  | ||||
| length | ||||
|   | ||||
| @@ -190,6 +190,28 @@ The remaining arguments should be tuples in this format:: | ||||
| ...where ``optional dictionary`` and ``optional name`` are optional. (See | ||||
| `Passing extra options to view functions`_ below.) | ||||
|  | ||||
| .. note:: | ||||
|     Because `patterns()` is a function call, it accepts a maximum of 255 | ||||
|     arguments (URL patterns, in this case). This is a limit for all Python | ||||
|     function calls. This is rarely a problem in practice, because you'll | ||||
|     typically structure your URL patterns modularly by using `include()` | ||||
|     sections. However, on the off-chance you do hit the 255-argument limit, | ||||
|     realize that `patterns()` returns a Python list, so you can split up the | ||||
|     construction of the list. | ||||
|  | ||||
|     :: | ||||
|  | ||||
|         urlpatterns = patterns('', | ||||
|             ... | ||||
|             ) | ||||
|         urlpatterns += patterns('', | ||||
|             ... | ||||
|             ) | ||||
|  | ||||
|     Python lists have unlimited size, so there's no limit to how many URL | ||||
|     patterns you can construct. The only limit is that you can only create 254 | ||||
|     at a time (the 255th argument is the initial prefix argument). | ||||
|  | ||||
| url | ||||
| --- | ||||
|  | ||||
|   | ||||
| @@ -64,11 +64,11 @@ class TextFile(models.Model): | ||||
|  | ||||
|     def __unicode__(self): | ||||
|         return self.description | ||||
|          | ||||
|  | ||||
| class ImageFile(models.Model): | ||||
|     description = models.CharField(max_length=20) | ||||
|     image = models.FileField(upload_to=tempfile.gettempdir()) | ||||
|      | ||||
|  | ||||
|     def __unicode__(self): | ||||
|         return self.description | ||||
|  | ||||
| @@ -155,29 +155,52 @@ familiar with the mechanics. | ||||
| ...     class Meta: | ||||
| ...         model = Category | ||||
|  | ||||
| >>> class BadForm(CategoryForm): | ||||
| >>> class OddForm(CategoryForm): | ||||
| ...     class Meta: | ||||
| ...         model = Article | ||||
| Traceback (most recent call last): | ||||
| ... | ||||
| ImproperlyConfigured: BadForm defines a different model than its parent. | ||||
|  | ||||
| OddForm is now an Article-related thing, because BadForm.Meta overrides | ||||
| CategoryForm.Meta. | ||||
| >>> OddForm.base_fields.keys() | ||||
| ['headline', 'slug', 'pub_date', 'writer', 'article', 'status', 'categories'] | ||||
|  | ||||
| >>> class ArticleForm(ModelForm): | ||||
| ...     class Meta: | ||||
| ...         model = Article | ||||
|  | ||||
| First class with a Meta class wins. | ||||
|  | ||||
| >>> class BadForm(ArticleForm, CategoryForm): | ||||
| ...     pass | ||||
| Traceback (most recent call last): | ||||
| ... | ||||
| ImproperlyConfigured: BadForm's base classes define more than one model. | ||||
| >>> OddForm.base_fields.keys() | ||||
| ['headline', 'slug', 'pub_date', 'writer', 'article', 'status', 'categories'] | ||||
|  | ||||
| This one is OK since the subclass specifies the same model as the parent. | ||||
| Subclassing without specifying a Meta on the class will use the parent's Meta | ||||
| (or the first parent in the MRO if there are multiple parent classes). | ||||
|  | ||||
| >>> class SubCategoryForm(CategoryForm): | ||||
| >>> class CategoryForm(ModelForm): | ||||
| ...     class Meta: | ||||
| ...         model = Category | ||||
| >>> class SubCategoryForm(CategoryForm): | ||||
| ...     pass | ||||
| >>> SubCategoryForm.base_fields.keys() | ||||
| ['name', 'slug', 'url'] | ||||
|  | ||||
| We can also subclass the Meta inner class to change the fields list. | ||||
|  | ||||
| >>> class CategoryForm(ModelForm): | ||||
| ...     checkbox = forms.BooleanField() | ||||
| ... | ||||
| ...     class Meta: | ||||
| ...         model = Category | ||||
| >>> class SubCategoryForm(CategoryForm): | ||||
| ...     class Meta(CategoryForm.Meta): | ||||
| ...         exclude = ['url'] | ||||
|  | ||||
| >>> print SubCategoryForm() | ||||
| <tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr> | ||||
| <tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr> | ||||
| <tr><th><label for="id_checkbox">Checkbox:</label></th><td><input type="checkbox" name="checkbox" id="id_checkbox" /></td></tr> | ||||
|  | ||||
| # Old form_for_x tests ####################################################### | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,8 @@ | ||||
| 6. Specifying ordering | ||||
|  | ||||
| Specify default ordering for a model using the ``ordering`` attribute, which | ||||
| should be a list or tuple of field names. This tells Django how to order the | ||||
| results of ``get_list()`` and other similar functions. | ||||
| should be a list or tuple of field names. This tells Django how to order | ||||
| queryset results. | ||||
|  | ||||
| If a field name in ``ordering`` starts with a hyphen, that field will be | ||||
| ordered in descending order. Otherwise, it'll be ordered in ascending order. | ||||
|   | ||||
| @@ -1,3 +1,5 @@ | ||||
| import sys | ||||
|  | ||||
| tests = """ | ||||
| >>> from django.utils.translation.trans_real import parse_accept_lang_header | ||||
| >>> p = parse_accept_lang_header | ||||
| @@ -83,7 +85,14 @@ source tree. | ||||
| >>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-ar,de'} | ||||
| >>> g(r) | ||||
| 'es-ar' | ||||
| """ | ||||
|  | ||||
| # Python 2.3 returns slightly different results for completely bogus locales, | ||||
| # so we omit this test for that anything below 2.4. It's relatively harmless in | ||||
| # any cases (GIGO). This also means this won't be executed on Jython currently, | ||||
| # but life's like that sometimes. | ||||
| if sys.version_info >= (2, 4): | ||||
|     tests += """ | ||||
| This test assumes there won't be a Django translation to a US variation | ||||
| of the Spanish language, a safe assumption. When the user sets it | ||||
| as the preferred language, the main 'es' translation should be selected | ||||
| @@ -91,7 +100,9 @@ instead. | ||||
| >>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-us'} | ||||
| >>> g(r) | ||||
| 'es' | ||||
| """ | ||||
|  | ||||
| tests += """ | ||||
| This tests the following scenario: there isn't a main language (zh) | ||||
| translation of Django but there is a translation to variation (zh_CN) | ||||
| the user sets zh-cn as the preferred language, it should be selected by | ||||
|   | ||||
		Reference in New Issue
	
	Block a user