From 60424589264285e3127f892ab6bfc38de2c0e4a8 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Thu, 17 May 2007 18:35:22 +0000 Subject: [PATCH] unicode: Merged from trunk up to [5265]. git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5279 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/management.py | 8 +-- django/newforms/extras/widgets.py | 3 +- django/newforms/fields.py | 10 ++-- django/newforms/forms.py | 8 +-- django/newforms/models.py | 9 ++-- django/newforms/util.py | 2 - django/newforms/widgets.py | 30 +++++------ docs/contributing.txt | 83 +++++++++++++++++++++++++++++-- docs/db-api.txt | 50 +++++++++---------- docs/model-api.txt | 9 ++++ docs/syndication_feeds.txt | 5 +- extras/django_bash_completion | 60 +++++++++++----------- 12 files changed, 185 insertions(+), 92 deletions(-) diff --git a/django/core/management.py b/django/core/management.py index 172aaa8b6e..7d9709b1b6 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -578,7 +578,7 @@ def syncdb(verbosity=1, interactive=True): # Install the 'initialdata' fixture, using format discovery load_data(['initial_data'], verbosity=verbosity) syncdb.help_doc = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." -syncdb.args = '[--verbosity] [--interactive]' +syncdb.args = '[--verbosity] [--noinput]' def get_admin_index(app): "Returns admin-index template snippet (in list form) for the given app." @@ -672,7 +672,7 @@ The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n') else: print "Reset cancelled." reset.help_doc = "Executes ``sqlreset`` for the given app(s) in the current database." -reset.args = '[--interactive]' + APP_ARGS +reset.args = '[--noinput]' + APP_ARGS def flush(verbosity=1, interactive=True): "Returns all tables in the database to the same state they were in immediately after syncdb." @@ -733,7 +733,7 @@ The full error: """ % settings.DATABASE_NAME + style.ERROR_OUTPUT(str(e)) + '\n' else: print "Flush cancelled." flush.help_doc = "Executes ``sqlflush`` on the current database." -flush.args = '[--verbosity] [--interactive]' +flush.args = '[--verbosity] [--noinput]' def _start_helper(app_or_project, name, directory, other_name=''): other = {'project': 'app', 'app': 'project'}[app_or_project] @@ -1452,7 +1452,7 @@ def dump_data(app_labels, format='json', indent=None): except Exception, e: sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % e)) dump_data.help_doc = 'Output the contents of the database as a fixture of the given format' -dump_data.args = '[--format]' + APP_ARGS +dump_data.args = '[--format] [--indent]' + APP_ARGS # Utilities for command-line script diff --git a/django/newforms/extras/widgets.py b/django/newforms/extras/widgets.py index 1011934fb8..724dcd9b50 100644 --- a/django/newforms/extras/widgets.py +++ b/django/newforms/extras/widgets.py @@ -2,9 +2,10 @@ Extra HTML Widget classes """ +import datetime + from django.newforms.widgets import Widget, Select from django.utils.dates import MONTHS -import datetime __all__ = ('SelectDateWidget',) diff --git a/django/newforms/fields.py b/django/newforms/fields.py index 970a5185da..d67eefdd3c 100644 --- a/django/newforms/fields.py +++ b/django/newforms/fields.py @@ -2,14 +2,16 @@ Field classes """ -from django.utils.translation import ugettext -from django.utils.encoding import smart_unicode -from util import ErrorList, ValidationError -from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple import datetime import re import time +from django.utils.translation import ugettext +from django.utils.encoding import smart_unicode + +from util import ErrorList, ValidationError +from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple + __all__ = ( 'Field', 'CharField', 'IntegerField', 'DEFAULT_DATE_INPUT_FORMATS', 'DateField', diff --git a/django/newforms/forms.py b/django/newforms/forms.py index f76e1f4462..6bf2c68d1e 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -2,13 +2,15 @@ Form classes """ -from django.utils.datastructures import SortedDict, MultiValueDict +import copy + +from django.utils.datastructures import SortedDict from django.utils.html import escape from django.utils.encoding import StrAndUnicode, smart_unicode + from fields import Field -from widgets import TextInput, Textarea, HiddenInput, MultipleHiddenInput +from widgets import TextInput, Textarea from util import flatatt, ErrorDict, ErrorList, ValidationError -import copy __all__ = ('BaseForm', 'Form') diff --git a/django/newforms/models.py b/django/newforms/models.py index 2fe0e62022..51d9a5c99e 100644 --- a/django/newforms/models.py +++ b/django/newforms/models.py @@ -5,13 +5,16 @@ and database field objects. from django.utils.translation import ugettext from django.utils.encoding import smart_unicode + from util import ValidationError -from forms import BaseForm, DeclarativeFieldsMetaclass, SortedDictFromList +from forms import BaseForm, SortedDictFromList from fields import Field, ChoiceField from widgets import Select, SelectMultiple, MultipleHiddenInput -__all__ = ('save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields', - 'ModelChoiceField', 'ModelMultipleChoiceField') +__all__ = ( + 'save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields', + 'ModelChoiceField', 'ModelMultipleChoiceField' +) def save_instance(form, instance, fields=None, fail_message='saved', commit=True): """ diff --git a/django/newforms/util.py b/django/newforms/util.py index fae2c860a9..455d6c3105 100644 --- a/django/newforms/util.py +++ b/django/newforms/util.py @@ -1,6 +1,4 @@ -from django.conf import settings from django.utils.html import escape -from django.utils.functional import Promise, lazy from django.utils.encoding import smart_unicode # Converts a dictionary to a single string with key="value", XML-style with diff --git a/django/newforms/widgets.py b/django/newforms/widgets.py index 758f703612..1c85a5cf11 100644 --- a/django/newforms/widgets.py +++ b/django/newforms/widgets.py @@ -2,24 +2,26 @@ HTML Widget classes """ -__all__ = ( - 'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput', - 'FileInput', 'Textarea', 'CheckboxInput', - 'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple', - 'MultiWidget', 'SplitDateTimeWidget', -) - -from util import flatatt -from django.utils.datastructures import MultiValueDict -from django.utils.html import escape -from django.utils.translation import ugettext -from django.utils.encoding import StrAndUnicode, smart_unicode -from itertools import chain - try: set # Only available in Python 2.4+ except NameError: from sets import Set as set # Python 2.3 fallback +from itertools import chain + +from django.utils.datastructures import MultiValueDict +from django.utils.html import escape +from django.utils.translation import ugettext +from django.utils.encoding import StrAndUnicode, smart_unicode + +from util import flatatt + +__all__ = ( + 'Widget', 'TextInput', 'PasswordInput', + 'HiddenInput', 'MultipleHiddenInput', + 'FileInput', 'Textarea', 'CheckboxInput', + 'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', + 'CheckboxSelectMultiple', 'MultiWidget', 'SplitDateTimeWidget', +) class Widget(object): is_hidden = False # Determines whether this corresponds to an . diff --git a/docs/contributing.txt b/docs/contributing.txt index d05c166b37..31409f27bd 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt @@ -279,6 +279,15 @@ Please follow these coding standards when writing code for inclusion in Django: * Mark all strings for internationalization; see the `i18n documentation`_ for details. + * Please don't put your name in the code you contribute. Our policy is to + keep contributors' names in the ``AUTHORS`` file distributed with Django + -- not scattered throughout the codebase itself. Feel free to include a + change to the ``AUTHORS`` file in your patch if you make more than a + single trivial change. + +Template style +-------------- + * In Django template code, put one (and only one) space between the curly brackets and the tag contents. @@ -290,6 +299,9 @@ Please follow these coding standards when writing code for inclusion in Django: {{foo}} +View style +---------- + * In Django views, the first parameter in a view function should be called ``request``. @@ -303,11 +315,72 @@ Please follow these coding standards when writing code for inclusion in Django: def my_view(req, foo): # ... - * Please don't put your name in the code you contribute. Our policy is to - keep contributors' names in the ``AUTHORS`` file distributed with Django - -- not scattered throughout the codebase itself. Feel free to include a - change to the ``AUTHORS`` file in your patch if you make more than a - single trivial change. +Model style +----------- + + * Field names should be all lowercase, using underscores instead of + camelCase. + + Do this:: + + class Person(models.Model): + first_name = models.CharField(maxlength=20) + last_name = models.CharField(maxlength=40) + + Don't do this:: + + class Person(models.Model): + FirstName = models.CharField(maxlength=20) + Last_Name = models.CharField(maxlength=40) + + * The ``class Meta`` should appear *after* the fields are defined, with + a single blank line separating the fields and the class definition. + + Do this:: + + class Person(models.Model): + first_name = models.CharField(maxlength=20) + last_name = models.CharField(maxlength=40) + + class Meta: + verbose_name_plural = 'people' + + Don't do this:: + + class Person(models.Model): + first_name = models.CharField(maxlength=20) + last_name = models.CharField(maxlength=40) + class Meta: + verbose_name_plural = 'people' + + Don't do this, either:: + + class Person(models.Model): + class Meta: + verbose_name_plural = 'people' + + first_name = models.CharField(maxlength=20) + last_name = models.CharField(maxlength=40) + + * The order of model inner classes and standard methods should be as + follows (noting that these are not all required): + + * All database fields + * ``class Meta`` + * ``class Admin`` + * ``def __str__()`` + * ``def save()`` + * ``def get_absolute_url()`` + * Any custom methods + + * If ``choices`` is defined for a given model field, define the choices as + a tuple of tuples, with an all-uppercase name, either near the top of the + model module or just above the model class. Example:: + + GENDER_CHOICES = ( + ('M', 'Male'), + ('F', 'Female'), + ) Committing code =============== diff --git a/docs/db-api.txt b/docs/db-api.txt index 9d2f09daf3..de612e0e3d 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -143,8 +143,8 @@ or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django follows this algorithm: * If the object's primary key attribute is set to a value that evaluates to - ``True`` (i.e., a value other than ``None`` or the empty string), Django - executes a ``SELECT`` query to determine whether a record with the given + ``True`` (i.e., a value other than ``None`` or the empty string), Django + executes a ``SELECT`` query to determine whether a record with the given primary key already exists. * If the record with the given primary key does already exist, Django executes an ``UPDATE`` query. @@ -525,19 +525,19 @@ Examples:: [datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)] >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day') [datetime.datetime(2005, 3, 20)] - + ``none()`` ~~~~~~~~~~ **New in Django development version** -Returns an ``EmptyQuerySet`` -- a ``QuerySet`` that always evaluates to +Returns an ``EmptyQuerySet`` -- a ``QuerySet`` that always evaluates to an empty list. This can be used in cases where you know that you should return an empty result set and your caller is expecting a ``QuerySet`` object (instead of returning an empty list, for example.) Examples:: - + >>> Entry.objects.none() [] @@ -610,7 +610,7 @@ follow:: c = p.hometown # Requires a database call. The ``depth`` argument is new in the Django development version. - + ``extra(select=None, where=None, params=None, tables=None)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1136,7 +1136,7 @@ such as January 3, July 3, etc. isnull ~~~~~~ -Takes either ``True`` or ``False``, which correspond to SQL queries of +Takes either ``True`` or ``False``, which correspond to SQL queries of ``IS NULL`` and ``IS NOT NULL``, respectively. Example:: @@ -1149,10 +1149,10 @@ SQL equivalent:: .. admonition:: ``__isnull=True`` vs ``__exact=None`` - There is an important difference between ``__isnull=True`` and + There is an important difference between ``__isnull=True`` and ``__exact=None``. ``__exact=None`` will *always* return an empty result - set, because SQL requires that no value is equal to ``NULL``. - ``__isnull`` determines if the field is currently holding the value + set, because SQL requires that no value is equal to ``NULL``. + ``__isnull`` determines if the field is currently holding the value of ``NULL`` without performing a comparison. search @@ -1181,7 +1181,7 @@ The pk lookup shortcut ---------------------- For convenience, Django provides a ``pk`` lookup type, which stands for -"primary_key". +"primary_key". In the example ``Blog`` model, the primary key is the ``id`` field, so these three statements are equivalent:: @@ -1190,14 +1190,14 @@ three statements are equivalent:: Blog.objects.get(id=14) # __exact is implied Blog.objects.get(pk=14) # pk implies id__exact -The use of ``pk`` isn't limited to ``__exact`` queries -- any query term +The use of ``pk`` isn't limited to ``__exact`` queries -- any query term can be combined with ``pk`` to perform a query on the primary key of a model:: # Get blogs entries with id 1, 4 and 7 Blog.objects.filter(pk__in=[1,4,7]) # Get all blog entries with id > 14 - Blog.objects.filter(pk__gt=14) - + Blog.objects.filter(pk__gt=14) + ``pk`` lookups also work across joins. For example, these three statements are equivalent:: @@ -1754,19 +1754,19 @@ get_object_or_404() ------------------- One common idiom to use ``get()`` and raise ``Http404`` if the -object doesn't exist. This idiom is captured by ``get_object_or_404()``. -This function takes a Django model as its first argument and an -arbitrary number of keyword arguments, which it passes to the manager's +object doesn't exist. This idiom is captured by ``get_object_or_404()``. +This function takes a Django model as its first argument and an +arbitrary number of keyword arguments, which it passes to the manager's ``get()`` function. It raises ``Http404`` if the object doesn't -exist. For example:: - +exist. For example:: + # Get the Entry with a primary key of 3 e = get_object_or_404(Entry, pk=3) -When you provide a model to this shortcut function, the default manager -is used to execute the underlying ``get()`` query. If you don't want to -use the default manager, or you want to search a list of related objects, -you can provide ``get_object_or_404()`` with a manager object, instead. +When you provide a model to this shortcut function, the default manager +is used to execute the underlying ``get()`` query. If you don't want to +use the default manager, or if you want to search a list of related objects, +you can provide ``get_object_or_404()`` with a manager object instead. For example:: # Get the author of blog instance `e` with a name of 'Fred' @@ -1779,8 +1779,8 @@ For example:: get_list_or_404() ----------------- -``get_list_or_404`` behaves the same was as ``get_object_or_404()`` --- except the it uses using ``filter()`` instead of ``get()``. It raises +``get_list_or_404`` behaves the same way as ``get_object_or_404()`` +-- except that it uses ``filter()`` instead of ``get()``. It raises ``Http404`` if the list is empty. Falling back to raw SQL diff --git a/docs/model-api.txt b/docs/model-api.txt index 961269aebd..e7afbfd13a 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -1759,6 +1759,15 @@ But this template code is good:: {{ object.name }} +.. note:: + The string you return from ``get_absolute_url()`` must be use only ASCII + characters (required by the URI spec, `RFC 2396`_) that has been + URL-encoded, if necessary. Code and templates using ``get_absolute_url()`` + should be able to use the result directly without needing to do any + further processing. + +.. _RFC 2396: http://www.ietf.org/rfc/rfc2396.txt + The ``permalink`` decorator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/syndication_feeds.txt b/docs/syndication_feeds.txt index d9d4f53b88..2a03e6d5a6 100644 --- a/docs/syndication_feeds.txt +++ b/docs/syndication_feeds.txt @@ -146,7 +146,10 @@ put into those elements. exist, it tries calling a method ``item_link()`` in the ``Feed`` class, passing it a single parameter, ``item``, which is the object itself. Both ``get_absolute_url()`` and ``item_link()`` should return the item's - URL as a normal Python string. + URL as a normal Python string. As with ``get_absolute_url()``, the + result of ``item_link()`` will be included directly in the URL, so you + are responsible for doing all necessary URL quoting and conversion to + ASCII inside the method itself. * For the LatestEntries example above, we could have very simple feed templates: diff --git a/extras/django_bash_completion b/extras/django_bash_completion index 64d8961ca7..8906609a68 100644 --- a/extras/django_bash_completion +++ b/extras/django_bash_completion @@ -42,13 +42,13 @@ _django_completion() prev="${COMP_WORDS[COMP_CWORD-1]}" # Standalone options - opts="--help --settings --pythonpath --version" + opts="--help --settings --pythonpath --noinput --noreload --format --indent --verbosity --adminmedia --version" # Actions actions="adminindex createcachetable dbshell diffsettings \ - inspectdb install reset runfcgi runserver \ - shell sql sqlall sqlclear sqlindexes sqlinitialdata \ + dumpdata flush inspectdb loaddata reset runfcgi runserver \ + shell sql sqlall sqlclear sqlcustom sqlflush sqlindexes \ sqlreset sqlsequencereset startapp startproject \ - syncdb validate" + syncdb test validate" # Action's options action_shell_opts="--plain" action_runfcgi_opts="host port socket method maxspare minspare maxchildren daemonize pidfile workdir" @@ -84,33 +84,33 @@ _django_completion() esac else case ${prev} in - adminindex|install|reset| \ - sql|sqlall|sqlclear|sqlindexes| \ - sqlinitialdata|sqlreset|sqlsequencereset) - # App completion - settings="" - # If settings.py in the PWD, use that - if [ -e settings.py ] ; then - settings="$PWD/settings.py" - else - # Use the ENV variable if it is set - if [ $DJANGO_SETTINGS_MODULE ] ; then - settings=$DJANGO_SETTINGS_MODULE + adminindex|dumpdata|reset| \ + sql|sqlall|sqlclear|sqlcustom|sqlindexes| \ + sqlreset|sqlsequencereset|test) + # App completion + settings="" + # If settings.py in the PWD, use that + if [ -e settings.py ] ; then + settings="$PWD/settings.py" + else + # Use the ENV variable if it is set + if [ $DJANGO_SETTINGS_MODULE ] ; then + settings=$DJANGO_SETTINGS_MODULE + fi fi - fi - # Couldn't find settings so return nothing - if [ -z $settings ] ; then - COMPREPLY=() - # Otherwise inspect settings.py file - else - apps=`sed -n "/INSTALLED_APPS = (/,/)/p" $settings | \ - grep -v "django.contrib" | - sed -n "s/^[ ]*'\(.*\.\)*\(.*\)'.*$/\2 /pg" | \ - tr -d "\n"` - COMPREPLY=( $(compgen -W "${apps}" -- ${cur}) ) - fi - return 0 - ;; + # Couldn't find settings so return nothing + if [ -z $settings ] ; then + COMPREPLY=() + # Otherwise inspect settings.py file + else + apps=`sed -n "/INSTALLED_APPS = (/,/)/p" $settings | \ + grep -v "django.contrib" | + sed -n "s/^[ ]*'\(.*\.\)*\(.*\)'.*$/\2 /pg" | \ + tr -d "\n"` + COMPREPLY=( $(compgen -W "${apps}" -- ${cur}) ) + fi + return 0 + ;; createcachetable|dbshell|diffsettings| \ inspectdb|runserver|startapp|startproject|syncdb| \