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

newforms-admin: Merged to [5300]

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@5301 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-05-20 20:59:24 +00:00
parent 4336591395
commit c2cdd2d4b4
30 changed files with 2954 additions and 1097 deletions

View File

@ -190,7 +190,7 @@ answer newbie questions, and generally made Django that much better:
polpak@yahoo.com polpak@yahoo.com
J. Rademaker J. Rademaker
Michael Radziej <mir@noris.de> Michael Radziej <mir@noris.de>
ramiro Ramiro Morales <rm0@gmx.net>
Massimiliano Ravelli <massimiliano.ravelli@gmail.com> Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
Brian Ray <http://brianray.chipy.org/> Brian Ray <http://brianray.chipy.org/>
remco@diji.biz remco@diji.biz
@ -209,6 +209,7 @@ answer newbie questions, and generally made Django that much better:
sopel sopel
Wiliam Alves de Souza <wiliamsouza83@gmail.com> Wiliam Alves de Souza <wiliamsouza83@gmail.com>
Georgi Stanojevski <glisha@gmail.com> Georgi Stanojevski <glisha@gmail.com>
Vasiliy Stavenko <stavenko@gmail.com>
Thomas Steinacher <http://www.eggdrop.ch/> Thomas Steinacher <http://www.eggdrop.ch/>
nowell strite nowell strite
Radek Švarz <http://www.svarz.cz/translate/> Radek Švarz <http://www.svarz.cz/translate/>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -83,7 +83,7 @@ class FormPreview(object):
""" """
while 1: while 1:
try: try:
f = self.form.fields[name] f = self.form.base_fields[name]
except KeyError: except KeyError:
break # This field name isn't being used by the form. break # This field name isn't being used by the form.
name += '_' name += '_'

View File

@ -1,7 +1,7 @@
from django.core import urlresolvers from django.core import urlresolvers
import urllib import urllib
PING_URL = "http://www.google.com/webmasters/sitemaps/ping" PING_URL = "http://www.google.com/webmasters/tools/ping"
class SitemapNotFound(Exception): class SitemapNotFound(Exception):
pass pass
@ -29,7 +29,7 @@ def ping_google(sitemap_url=None, ping_url=PING_URL):
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
current_site = Site.objects.get_current() current_site = Site.objects.get_current()
url = "%s%s" % (current_site.domain, sitemap_url) url = "http://%s%s" % (current_site.domain, sitemap_url)
params = urllib.urlencode({'sitemap':url}) params = urllib.urlencode({'sitemap':url})
urllib.urlopen("%s?%s" % (ping_url, params)) urllib.urlopen("%s?%s" % (ping_url, params))

View File

@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
r"""
>>> words(7)
'lorem ipsum dolor sit amet consectetur adipisicing'
>>> paragraphs(1)
['Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.']
"""
from django.contrib.webdesign.lorem_ipsum import *
import datetime
if __name__ == '__main__':
import doctest
doctest.testmod()

View File

@ -578,7 +578,7 @@ def syncdb(verbosity=1, interactive=True):
# Install the 'initialdata' fixture, using format discovery # Install the 'initialdata' fixture, using format discovery
load_data(['initial_data'], verbosity=verbosity) 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.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): def get_admin_index(app):
"Returns admin-index template snippet (in list form) for the given 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: else:
print "Reset cancelled." print "Reset cancelled."
reset.help_doc = "Executes ``sqlreset`` for the given app(s) in the current database." 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): def flush(verbosity=1, interactive=True):
"Returns all tables in the database to the same state they were in immediately after syncdb." "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: else:
print "Flush cancelled." print "Flush cancelled."
flush.help_doc = "Executes ``sqlflush`` on the current database." 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=''): def _start_helper(app_or_project, name, directory, other_name=''):
other = {'project': 'app', 'app': 'project'}[app_or_project] other = {'project': 'app', 'app': 'project'}[app_or_project]
@ -1455,7 +1455,7 @@ def dump_data(app_labels, format='json', indent=None):
except Exception, e: except Exception, e:
sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % 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.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 # Utilities for command-line script

View File

@ -121,9 +121,9 @@ class QueryDict(MultiValueDict):
self._assert_mutable() self._assert_mutable()
MultiValueDict.update(self, other_dict) MultiValueDict.update(self, other_dict)
def pop(self, key): def pop(self, key, *args):
self._assert_mutable() self._assert_mutable()
return MultiValueDict.pop(self, key) return MultiValueDict.pop(self, key, *args)
def popitem(self): def popitem(self):
self._assert_mutable() self._assert_mutable()

View File

@ -2,9 +2,10 @@
Extra HTML Widget classes Extra HTML Widget classes
""" """
import datetime
from django.newforms.widgets import Widget, Select from django.newforms.widgets import Widget, Select
from django.utils.dates import MONTHS from django.utils.dates import MONTHS
import datetime
__all__ = ('SelectDateWidget',) __all__ = ('SelectDateWidget',)

View File

@ -2,14 +2,16 @@
Field classes Field classes
""" """
from django.utils.translation import gettext
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 datetime
import re import re
import time import time
from django.utils.translation import gettext
from django.utils.encoding import smart_unicode
from util import ErrorList, ValidationError
from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple
__all__ = ( __all__ = (
'Field', 'CharField', 'IntegerField', 'Field', 'CharField', 'IntegerField',
'DEFAULT_DATE_INPUT_FORMATS', 'DateField', 'DEFAULT_DATE_INPUT_FORMATS', 'DateField',

View File

@ -2,13 +2,15 @@
Form classes 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.html import escape
from django.utils.encoding import StrAndUnicode from django.utils.encoding import StrAndUnicode
from fields import Field from fields import Field
from widgets import TextInput, Textarea, HiddenInput, MultipleHiddenInput from widgets import TextInput, Textarea
from util import flatatt, ErrorDict, ErrorList, ValidationError from util import flatatt, ErrorDict, ErrorList, ValidationError
import copy
__all__ = ('BaseForm', 'Form') __all__ = ('BaseForm', 'Form')

View File

@ -4,13 +4,16 @@ and database field objects.
""" """
from django.utils.translation import gettext from django.utils.translation import gettext
from util import ValidationError from util import ValidationError
from forms import BaseForm, DeclarativeFieldsMetaclass, SortedDictFromList from forms import BaseForm, SortedDictFromList
from fields import Field, ChoiceField from fields import Field, ChoiceField
from widgets import Select, SelectMultiple, MultipleHiddenInput from widgets import Select, SelectMultiple, MultipleHiddenInput
__all__ = ('save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields', __all__ = (
'ModelChoiceField', 'ModelMultipleChoiceField') '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): def save_instance(form, instance, fields=None, fail_message='saved', commit=True):
""" """

View File

@ -1,11 +1,14 @@
from django.conf import settings
from django.utils.html import escape from django.utils.html import escape
from django.utils.functional import Promise, lazy
from django.utils.encoding import smart_unicode from django.utils.encoding import smart_unicode
# Converts a dictionary to a single string with key="value", XML-style with def flatatt(attrs):
# a leading space. Assumes keys do not need to be XML-escaped. """
flatatt = lambda attrs: u''.join([u' %s="%s"' % (k, escape(v)) for k, v in attrs.items()]) Convert a dictionary of attributes to a single string.
The returned string will contain a leading space followed by key="value",
XML-style pairs. It is assumed that the keys do not need to be XML-escaped.
If the passed dictionary is empty, then return an empty string.
"""
return u''.join([u' %s="%s"' % (k, escape(v)) for k, v in attrs.items()])
class ErrorDict(dict): class ErrorDict(dict):
""" """

View File

@ -2,24 +2,26 @@
HTML Widget classes 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 gettext
from django.utils.encoding import StrAndUnicode, smart_unicode
from itertools import chain
try: try:
set # Only available in Python 2.4+ set # Only available in Python 2.4+
except NameError: except NameError:
from sets import Set as set # Python 2.3 fallback 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 gettext
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): class Widget(object):
is_hidden = False # Determines whether this corresponds to an <input type="hidden">. is_hidden = False # Determines whether this corresponds to an <input type="hidden">.

View File

@ -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`_ * Mark all strings for internationalization; see the `i18n documentation`_
for details. 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 * In Django template code, put one (and only one) space between the curly
brackets and the tag contents. brackets and the tag contents.
@ -290,6 +299,9 @@ Please follow these coding standards when writing code for inclusion in Django:
{{foo}} {{foo}}
View style
----------
* In Django views, the first parameter in a view function should be called * In Django views, the first parameter in a view function should be called
``request``. ``request``.
@ -303,11 +315,72 @@ Please follow these coding standards when writing code for inclusion in Django:
def my_view(req, foo): def my_view(req, foo):
# ... # ...
* Please don't put your name in the code you contribute. Our policy is to Model style
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 * Field names should be all lowercase, using underscores instead of
single trivial change. 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 Committing code
=============== ===============

View File

@ -143,8 +143,8 @@ or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django
follows this algorithm: follows this algorithm:
* If the object's primary key attribute is set to a value that evaluates to * 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 ``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 executes a ``SELECT`` query to determine whether a record with the given
primary key already exists. primary key already exists.
* If the record with the given primary key does already exist, Django * If the record with the given primary key does already exist, Django
executes an ``UPDATE`` query. executes an ``UPDATE`` query.
@ -525,19 +525,19 @@ Examples::
[datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)] [datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)]
>>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day') >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
[datetime.datetime(2005, 3, 20)] [datetime.datetime(2005, 3, 20)]
``none()`` ``none()``
~~~~~~~~~~ ~~~~~~~~~~
**New in Django development version** **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 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`` return an empty result set and your caller is expecting a ``QuerySet``
object (instead of returning an empty list, for example.) object (instead of returning an empty list, for example.)
Examples:: Examples::
>>> Entry.objects.none() >>> Entry.objects.none()
[] []
@ -610,7 +610,7 @@ follow::
c = p.hometown # Requires a database call. c = p.hometown # Requires a database call.
The ``depth`` argument is new in the Django development version. The ``depth`` argument is new in the Django development version.
``extra(select=None, where=None, params=None, tables=None)`` ``extra(select=None, where=None, params=None, tables=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1136,7 +1136,7 @@ such as January 3, July 3, etc.
isnull 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. ``IS NULL`` and ``IS NOT NULL``, respectively.
Example:: Example::
@ -1149,10 +1149,10 @@ SQL equivalent::
.. admonition:: ``__isnull=True`` vs ``__exact=None`` .. 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 ``__exact=None``. ``__exact=None`` will *always* return an empty result
set, because SQL requires that no value is equal to ``NULL``. set, because SQL requires that no value is equal to ``NULL``.
``__isnull`` determines if the field is currently holding the value ``__isnull`` determines if the field is currently holding the value
of ``NULL`` without performing a comparison. of ``NULL`` without performing a comparison.
search search
@ -1181,7 +1181,7 @@ The pk lookup shortcut
---------------------- ----------------------
For convenience, Django provides a ``pk`` lookup type, which stands for 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 In the example ``Blog`` model, the primary key is the ``id`` field, so these
three statements are equivalent:: three statements are equivalent::
@ -1190,14 +1190,14 @@ three statements are equivalent::
Blog.objects.get(id=14) # __exact is implied Blog.objects.get(id=14) # __exact is implied
Blog.objects.get(pk=14) # pk implies id__exact 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:: 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 # Get blogs entries with id 1, 4 and 7
Blog.objects.filter(pk__in=[1,4,7]) Blog.objects.filter(pk__in=[1,4,7])
# Get all blog entries with id > 14 # 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 ``pk`` lookups also work across joins. For example, these three statements are
equivalent:: equivalent::
@ -1754,19 +1754,19 @@ get_object_or_404()
------------------- -------------------
One common idiom to use ``get()`` and raise ``Http404`` if the One common idiom to use ``get()`` and raise ``Http404`` if the
object doesn't exist. This idiom is captured by ``get_object_or_404()``. 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 This function takes a Django model as its first argument and an
arbitrary number of keyword arguments, which it passes to the manager's arbitrary number of keyword arguments, which it passes to the manager's
``get()`` function. It raises ``Http404`` if the object doesn't ``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 # Get the Entry with a primary key of 3
e = get_object_or_404(Entry, pk=3) e = get_object_or_404(Entry, pk=3)
When you provide a model to this shortcut function, the default manager 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 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, 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. you can provide ``get_object_or_404()`` with a manager object instead.
For example:: For example::
# Get the author of blog instance `e` with a name of 'Fred' # 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()
----------------- -----------------
``get_list_or_404`` behaves the same was as ``get_object_or_404()`` ``get_list_or_404`` behaves the same way as ``get_object_or_404()``
-- except the it uses using ``filter()`` instead of ``get()``. It raises -- except that it uses ``filter()`` instead of ``get()``. It raises
``Http404`` if the list is empty. ``Http404`` if the list is empty.
Falling back to raw SQL Falling back to raw SQL

View File

@ -11,8 +11,8 @@ Being a Python Web framework, Django requires Python.
It works with any Python version 2.3 and higher. It works with any Python version 2.3 and higher.
Get Python at www.python.org. If you're running Linux or Mac OS X, you probably Get Python at http://www.python.org. If you're running Linux or Mac OS X, you
already have it installed. probably already have it installed.
Install Apache and mod_python Install Apache and mod_python
============================= =============================

View File

@ -1759,6 +1759,15 @@ But this template code is good::
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a> <a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
.. note::
The string you return from ``get_absolute_url()`` must contain only ASCII
characters (required by the URI spec, `RFC 2396`_) that have 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 The ``permalink`` decorator
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -602,6 +602,102 @@ when printed::
>>> str(f['subject'].errors) >>> str(f['subject'].errors)
'' ''
Using forms in views and templates
----------------------------------
Let's put this all together and use the ``ContactForm`` example in a Django
view and template. This example view displays the contact form by default and
validates/processes it if accessed via a POST request::
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
# Do form processing here...
return HttpResponseRedirect('/url/on_success/')
else:
form = ContactForm()
return render_to_response('contact.html', {'form': form})
Simple template output
~~~~~~~~~~~~~~~~~~~~~~
The template, ``contact.html``, is responsible for displaying the form as HTML.
To do this, we can use the techniques outlined in the "Outputting forms as HTML"
section above.
The simplest way to display a form's HTML is to use the variable on its own,
like this::
<form method="post">
<table>{{ form }}</table>
<input type="submit" />
</form>
The above template code will display the form as an HTML table, using the
``form.as_table()`` method explained previously. This works because Django's
template system displays an object's ``__str__()`` value, and the ``Form``
class' ``__str__()`` method calls its ``as_table()`` method.
The following is equivalent but a bit more explicit::
<form method="post">
<table>{{ form.as_table }}</table>
<input type="submit" />
</form>
``form.as_ul`` and ``form.as_p`` are also available, as you may expect.
Note that in the above two examples, we included the ``<form>``, ``<table>``
``<input type="submit" />``, ``</table>`` and ``</form>`` tags. The form
convenience methods (``as_table()``, ``as_ul()`` and ``as_p()``) do not include
that HTML.
Complex template output
~~~~~~~~~~~~~~~~~~~~~~~
As we've stressed several times, the ``as_table()``, ``as_ul()`` and ``as_p()``
methods are just shortcuts for the common case. You can also work with the
individual fields for complete template control over the form's design.
The easiest way is to iterate over the form's fields, with
``{% for field in form %}``. For example::
<form method="post">
<dl>
{% for field in form %}
<dt>{{ field.label }}</dt>
<dd>{{ field }}</dd>
{% if field.help_text %}<dd>{{ field.help_text }}</dd>{% endif %}
{% if field.errors %}<dd class="myerrors">{{ field.errors }}</dd>{% endif %}
{% endfor %}
</dl>
<input type="submit" />
</form>
This iteration technique is useful if you want to apply the same HTML
formatting to each field, or if you don't know the names of the form fields
ahead of time. Note that the fields will be listed in the order in which
they're defined in the ``Form`` class.
Alternatively, you can arrange the form's fields explicitly, by name. Do that
by accessing ``{{ form.fieldname }}``, where ``fieldname`` is the field's name.
For example::
<form method="post">
<ul class="myformclass">
<li>{{ form.sender.label }} {{ form.sender.label }}</li>
<li class="helptext">{{ form.sender.help_text }}</li>
{% if form.sender.errors %}<ul class="errorlist">{{ form.sender.errors }}</dd>{% endif %}
<li>{{ form.subject.label }} {{ form.subject.label }}</li>
<li class="helptext">{{ form.subject.help_text }}</li>
{% if form.subject.errors %}<ul class="errorlist">{{ form.subject.errors }}</dd>{% endif %}
...
</ul>
</form>
Subclassing forms Subclassing forms
----------------- -----------------

View File

@ -1055,7 +1055,7 @@ You can tell Django to stop reporting particular 404s by tweaking the
tuple of strings. For example:: tuple of strings. For example::
IGNORABLE_404_ENDS = ('.php', '.cgi') IGNORABLE_404_ENDS = ('.php', '.cgi')
IGNORABLE_404_STARTS = ('/phpmyadmin/') IGNORABLE_404_STARTS = ('/phpmyadmin/',)
In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not* In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not*
be reported. Neither will any URL starting with ``/phpmyadmin/``. be reported. Neither will any URL starting with ``/phpmyadmin/``.

View File

@ -146,7 +146,10 @@ put into those elements.
exist, it tries calling a method ``item_link()`` in the ``Feed`` class, exist, it tries calling a method ``item_link()`` in the ``Feed`` class,
passing it a single parameter, ``item``, which is the object itself. passing it a single parameter, ``item``, which is the object itself.
Both ``get_absolute_url()`` and ``item_link()`` should return the item's 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: * For the LatestEntries example above, we could have very simple feed templates:

View File

@ -42,13 +42,13 @@ _django_completion()
prev="${COMP_WORDS[COMP_CWORD-1]}" prev="${COMP_WORDS[COMP_CWORD-1]}"
# Standalone options # Standalone options
opts="--help --settings --pythonpath --version" opts="--help --settings --pythonpath --noinput --noreload --format --indent --verbosity --adminmedia --version"
# Actions # Actions
actions="adminindex createcachetable dbshell diffsettings \ actions="adminindex createcachetable dbshell diffsettings \
inspectdb install reset runfcgi runserver \ dumpdata flush inspectdb loaddata reset runfcgi runserver \
shell sql sqlall sqlclear sqlindexes sqlinitialdata \ shell sql sqlall sqlclear sqlcustom sqlflush sqlindexes \
sqlreset sqlsequencereset startapp startproject \ sqlreset sqlsequencereset startapp startproject \
syncdb validate" syncdb test validate"
# Action's options # Action's options
action_shell_opts="--plain" action_shell_opts="--plain"
action_runfcgi_opts="host port socket method maxspare minspare maxchildren daemonize pidfile workdir" action_runfcgi_opts="host port socket method maxspare minspare maxchildren daemonize pidfile workdir"
@ -84,33 +84,33 @@ _django_completion()
esac esac
else else
case ${prev} in case ${prev} in
adminindex|install|reset| \ adminindex|dumpdata|reset| \
sql|sqlall|sqlclear|sqlindexes| \ sql|sqlall|sqlclear|sqlcustom|sqlindexes| \
sqlinitialdata|sqlreset|sqlsequencereset) sqlreset|sqlsequencereset|test)
# App completion # App completion
settings="" settings=""
# If settings.py in the PWD, use that # If settings.py in the PWD, use that
if [ -e settings.py ] ; then if [ -e settings.py ] ; then
settings="$PWD/settings.py" settings="$PWD/settings.py"
else else
# Use the ENV variable if it is set # Use the ENV variable if it is set
if [ $DJANGO_SETTINGS_MODULE ] ; then if [ $DJANGO_SETTINGS_MODULE ] ; then
settings=$DJANGO_SETTINGS_MODULE settings=$DJANGO_SETTINGS_MODULE
fi
fi fi
fi # Couldn't find settings so return nothing
# Couldn't find settings so return nothing if [ -z $settings ] ; then
if [ -z $settings ] ; then COMPREPLY=()
COMPREPLY=() # Otherwise inspect settings.py file
# Otherwise inspect settings.py file else
else apps=`sed -n "/INSTALLED_APPS = (/,/)/p" $settings | \
apps=`sed -n "/INSTALLED_APPS = (/,/)/p" $settings | \ grep -v "django.contrib" |
grep -v "django.contrib" | sed -n "s/^[ ]*'\(.*\.\)*\(.*\)'.*$/\2 /pg" | \
sed -n "s/^[ ]*'\(.*\.\)*\(.*\)'.*$/\2 /pg" | \ tr -d "\n"`
tr -d "\n"` COMPREPLY=( $(compgen -W "${apps}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${apps}" -- ${cur}) ) fi
fi return 0
return 0 ;;
;;
createcachetable|dbshell|diffsettings| \ createcachetable|dbshell|diffsettings| \
inspectdb|runserver|startapp|startproject|syncdb| \ inspectdb|runserver|startapp|startproject|syncdb| \

View File

@ -3516,6 +3516,15 @@ u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
u'1' u'1'
>>> smart_unicode('foo') >>> smart_unicode('foo')
u'foo' u'foo'
# flatatt tests
>>> from django.newforms.util import flatatt
>>> flatatt({'id': "header"})
u' id="header"'
>>> flatatt({'class': "news", 'title': "Read this"})
u' class="news" title="Read this"'
>>> flatatt({})
u''
""" """
__test__ = { __test__ = {

View File

@ -166,6 +166,9 @@ True
>>> q.pop('foo') >>> q.pop('foo')
['bar', 'baz', 'another', 'hello'] ['bar', 'baz', 'another', 'hello']
>>> q.pop('foo', 'not there')
'not there'
>>> q.get('foo', 'not there') >>> q.get('foo', 'not there')
'not there' 'not there'

View File

@ -3,11 +3,15 @@
import os, sys, traceback import os, sys, traceback
import unittest import unittest
import django.contrib as contrib
CONTRIB_DIR_NAME = 'django.contrib'
MODEL_TESTS_DIR_NAME = 'modeltests' MODEL_TESTS_DIR_NAME = 'modeltests'
REGRESSION_TESTS_DIR_NAME = 'regressiontests' REGRESSION_TESTS_DIR_NAME = 'regressiontests'
TEST_DATABASE_NAME = 'django_test_db' TEST_DATABASE_NAME = 'django_test_db'
TEST_TEMPLATE_DIR = 'templates' TEST_TEMPLATE_DIR = 'templates'
CONTRIB_DIR = os.path.dirname(contrib.__file__)
MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME) MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME)
REGRESSION_TEST_DIR = os.path.join(os.path.dirname(__file__), REGRESSION_TESTS_DIR_NAME) REGRESSION_TEST_DIR = os.path.join(os.path.dirname(__file__), REGRESSION_TESTS_DIR_NAME)
@ -24,7 +28,7 @@ ALWAYS_INSTALLED_APPS = [
def get_test_models(): def get_test_models():
models = [] models = []
for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR): for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR), (CONTRIB_DIR_NAME, CONTRIB_DIR):
for f in os.listdir(dirpath): for f in os.listdir(dirpath):
if f.startswith('__init__') or f.startswith('.') or f.startswith('sql') or f.startswith('invalid'): if f.startswith('__init__') or f.startswith('.') or f.startswith('sql') or f.startswith('invalid'):
continue continue
@ -33,7 +37,7 @@ def get_test_models():
def get_invalid_models(): def get_invalid_models():
models = [] models = []
for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR): for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR), (CONTRIB_DIR_NAME, CONTRIB_DIR):
for f in os.listdir(dirpath): for f in os.listdir(dirpath):
if f.startswith('__init__') or f.startswith('.') or f.startswith('sql'): if f.startswith('__init__') or f.startswith('.') or f.startswith('sql'):
continue continue
@ -109,8 +113,10 @@ def django_tests(verbosity, tests_to_run):
if verbosity >= 1: if verbosity >= 1:
print "Importing model %s" % model_name print "Importing model %s" % model_name
mod = load_app(model_label) mod = load_app(model_label)
settings.INSTALLED_APPS.append(model_label) if mod:
test_models.append(mod) if model_label not in settings.INSTALLED_APPS:
settings.INSTALLED_APPS.append(model_label)
test_models.append(mod)
except Exception, e: except Exception, e:
sys.stderr.write("Error while importing %s:" % model_name + ''.join(traceback.format_exception(*sys.exc_info())[1:])) sys.stderr.write("Error while importing %s:" % model_name + ''.join(traceback.format_exception(*sys.exc_info())[1:]))
continue continue