1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

newforms-admin: Merged to [5439]

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@5440 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-06-07 21:49:06 +00:00
parent 659d99b7af
commit d34639b09b
52 changed files with 3250 additions and 2809 deletions

View File

@ -142,6 +142,7 @@ answer newbie questions, and generally made Django that much better:
Joseph Kocherhans
konrad@gwu.edu
lakin.wecker@gmail.com
Nick Lane <nick.lane.au@gmail.com>
Stuart Langridge <http://www.kryogenix.org/>
Nicola Larosa <nico@teknico.net>
Eugene Lazutkin <http://lazutkin.com/blog/>
@ -230,6 +231,7 @@ answer newbie questions, and generally made Django that much better:
viestards.lists@gmail.com
Milton Waddams
wam-djangobug@wamber.net
wangchun <yaohua2000@gmail.com>
Dan Watson <http://theidioteque.net/>
Chris Wesseling <Chris.Wesseling@cwi.nl>
charly.wilhelm@gmail.com

View File

@ -7,13 +7,13 @@ Can be run as a cronjob to clean out old data from the database (only expired
sessions at the moment).
"""
from django.db import backend, connection, transaction
import datetime
from django.db import transaction
from django.contrib.sessions.models import Session
def clean_up():
# Clean up old database records
cursor = connection.cursor()
cursor.execute("DELETE FROM %s WHERE %s < NOW()" % \
(backend.quote_name('django_session'), backend.quote_name('expire_date')))
"""Clean up expired sessions."""
Session.objects.filter(expire_date__lt=datetime.datetime.now()).delete()
transaction.commit_unless_managed()
if __name__ == "__main__":

View File

@ -144,6 +144,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
# 'django.core.context_processors.request',
)
@ -331,6 +332,13 @@ TEST_RUNNER = 'django.test.simple.run_tests'
# If None, a name of 'test_' + DATABASE_NAME will be assumed
TEST_DATABASE_NAME = None
# Strings used to set the character set and collation order for the test
# database. These values are passed literally to the server, so they are
# backend-dependent. If None, no special settings are sent (system defaults are
# used).
TEST_DATABASE_CHARSET = None
TEST_DATABASE_COLLATION = None
############
# FIXTURES #
############

File diff suppressed because it is too large Load Diff

View File

@ -113,8 +113,8 @@ msgstr "Demà"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr ""
msgstr "Mostrar"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr ""
msgstr "Ocultar"

View File

@ -481,8 +481,8 @@ msgid ""
"database tables have been created, and make sure the database is readable by "
"the appropriate user."
msgstr ""
"Etwas stimmt nicht mit der Datenbankkonfiguration. Bitte sicherstellen, das "
"die richtigen Datenbanktabellen angelegt wurden und bitte sicherstellen, das "
"Etwas stimmt nicht mit der Datenbankkonfiguration. Bitte sicherstellen, dass "
"die richtigen Datenbanktabellen angelegt wurden und "
"die Datenbank vom verwendeten Datenbankbenutzer auch lesbar ist."
#: contrib/admin/templates/admin/login.html:17

View File

@ -38,8 +38,9 @@ USE_I18N = True
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = ''
# URL that handles the media served from MEDIA_ROOT.
# Example: "http://media.lawrence.com"
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = ''
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a

View File

@ -1,4 +1,5 @@
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
from django.core.exceptions import ImproperlyConfigured
__all__ = ['handler404', 'handler500', 'include', 'patterns', 'url']
@ -22,7 +23,10 @@ def url(regex, view, kwargs=None, name=None, prefix=''):
# For include(...) processing.
return RegexURLResolver(regex, view[0], kwargs)
else:
if prefix and isinstance(view, basestring):
if isinstance(view, basestring):
if not view:
raise ImproperlyConfigured('Empty URL pattern view name not permitted (for pattern %r)' % regex)
if prefix:
view = prefix + '.' + view
return RegexURLPattern(regex, view, kwargs, name)

View File

@ -23,16 +23,19 @@ class LatestFreeCommentsFeed(Feed):
self._site = Site.objects.get_current()
return "Latest comments on %s" % self._site.name
def get_query_set(self):
return self.comments_class.objects.filter(site__pk=settings.SITE_ID, is_public=True)
def items(self):
return self.comments_class.objects.filter(site__pk=settings.SITE_ID, is_public=True)[:40]
return self.get_query_set()[:40]
class LatestCommentsFeed(LatestFreeCommentsFeed):
"""Feed of latest free comments on the current site"""
comments_class = Comment
def items(self):
qs = LatestFreeCommentsFeed.items(self)
def get_query_set(self):
qs = super(LatestCommentsFeed, self).get_query_set()
qs = qs.filter(is_removed=False)
if settings.COMMENTS_BANNED_USERS_GROUP:
where = ['user_id NOT IN (SELECT user_id FROM auth_users_group WHERE group_id = %s)']

View File

@ -42,6 +42,13 @@ def i18n(request):
return context_extras
def media(request):
"""
Adds media-related context variables to the context.
"""
return {'MEDIA_URL': settings.MEDIA_URL}
def request(request):
return {'request': request}

View File

@ -1141,7 +1141,7 @@ def validate(outfile=sys.stdout, silent_success=False):
return
outfile.write('%s error%s found.\n' % (num_errors, num_errors != 1 and 's' or ''))
except ImproperlyConfigured:
outfile.write("Skipping validation because things aren't configured properly.")
outfile.write("Skipping validation because things aren't configured properly.\n")
validate.args = ''
def _check_for_validation_errors(app=None):

View File

@ -21,6 +21,8 @@ class Serializer(PythonSerializer):
Convert a queryset to JSON.
"""
def end_serialization(self):
self.options.pop('stream', None)
self.options.pop('fields', None)
simplejson.dump(self.objects, self.stream, cls=DjangoJSONEncoder, **self.options)
def getvalue(self):

View File

@ -37,6 +37,11 @@ class Serializer(base.Serializer):
def handle_fk_field(self, obj, field):
related = getattr(obj, field.name)
if related is not None:
if field.rel.field_name == related._meta.pk.name:
# Related to remote object via primary key
related = related._get_pk_val()
else:
# Related to remote object via other field
related = getattr(related, field.rel.field_name)
self._current[field.name] = related

View File

@ -18,6 +18,8 @@ class Serializer(PythonSerializer):
Convert a queryset to YAML.
"""
def end_serialization(self):
self.options.pop('stream', None)
self.options.pop('fields', None)
yaml.dump(self.objects, self.stream, **self.options)
def getvalue(self):

View File

@ -82,7 +82,13 @@ class Serializer(base.Serializer):
self._start_relational_field(field)
related = getattr(obj, field.name)
if related is not None:
self.xml.characters(str(getattr(related, field.rel.field_name)))
if field.rel.field_name == related._meta.pk.name:
# Related to remote object via primary key
related = related._get_pk_val()
else:
# Related to remote object via other field
related = getattr(related, field.rel.field_name)
self.xml.characters(str(related))
else:
self.xml.addQuickElement("None")
self.xml.endElement("field")

View File

@ -12,6 +12,9 @@ from django.core.exceptions import ImproperlyConfigured
def complain(*args, **kwargs):
raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet."
def ignore(*args, **kwargs):
pass
class DatabaseError(Exception):
pass
@ -21,7 +24,7 @@ class IntegrityError(DatabaseError):
class DatabaseWrapper:
cursor = complain
_commit = complain
_rollback = complain
_rollback = ignore
def __init__(self, **kwargs):
pass

View File

@ -554,9 +554,8 @@ class QuerySet(object):
class ValuesQuerySet(QuerySet):
def __init__(self, *args, **kwargs):
super(ValuesQuerySet, self).__init__(*args, **kwargs)
# select_related and select aren't supported in values().
# select_related isn't supported in values().
self._select_related = False
self._select = {}
def iterator(self):
try:
@ -566,13 +565,28 @@ class ValuesQuerySet(QuerySet):
# self._fields is a list of field names to fetch.
if self._fields:
#columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
if not self._select:
columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
else:
columns = []
for f in self._fields:
if f in [field.name for field in self.model._meta.fields]:
columns.append( self.model._meta.get_field(f, many_to_many=False).column )
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
else: # Default to all fields.
columns = [f.column for f in self.model._meta.fields]
field_names = [f.attname for f in self.model._meta.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()])
cursor = connection.cursor()
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
while 1:

View File

@ -75,7 +75,7 @@ class CommonMiddleware(object):
# Use ETags, if requested.
if settings.USE_ETAGS:
etag = md5.new(response.content).hexdigest()
if request.META.get('HTTP_IF_NONE_MATCH') == etag:
if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
response = http.HttpResponseNotModified()
else:
response['ETag'] = etag

View File

@ -63,7 +63,7 @@ class BaseForm(StrAndUnicode):
self.auto_id = auto_id
self.prefix = prefix
self.initial = initial or {}
self.__errors = None # Stores the errors after clean() has been called.
self._errors = None # Stores the errors after clean() has been called.
# The base_fields class attribute is the *class-wide* definition of
# fields. Because a particular *instance* of the class might want to
@ -87,12 +87,12 @@ class BaseForm(StrAndUnicode):
raise KeyError('Key %r not found in Form' % name)
return BoundField(self, field, name)
def _errors(self):
def _get_errors(self):
"Returns an ErrorDict for self.data"
if self.__errors is None:
if self._errors is None:
self.full_clean()
return self.__errors
errors = property(_errors)
return self._errors
errors = property(_get_errors)
def is_valid(self):
"""
@ -189,11 +189,11 @@ class BaseForm(StrAndUnicode):
def full_clean(self):
"""
Cleans all of self.data and populates self.__errors and self.cleaned_data.
Cleans all of self.data and populates self._errors and
self.cleaned_data.
"""
errors = ErrorDict()
self._errors = ErrorDict()
if not self.is_bound: # Stop further processing.
self.__errors = errors
return
self.cleaned_data = {}
for name, field in self.fields.items():
@ -208,14 +208,15 @@ class BaseForm(StrAndUnicode):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError, e:
errors[name] = e.messages
self._errors[name] = e.messages
if name in self.cleaned_data:
del self.cleaned_data[name]
try:
self.cleaned_data = self.clean()
except ValidationError, e:
errors[NON_FIELD_ERRORS] = e.messages
if errors:
self._errors[NON_FIELD_ERRORS] = e.messages
if self._errors:
delattr(self, 'cleaned_data')
self.__errors = errors
def clean(self):
"""

View File

@ -782,7 +782,7 @@ class DecimalField(TextField):
try:
import decimal
except ImportError:
from django.utils import decimal
from django.utils import _decimal as decimal
try:
return decimal.Decimal(data)
except decimal.InvalidOperation, e:

View File

@ -479,7 +479,7 @@ class TokenParser(object):
while i < len(subject) and subject[i] != c:
i += 1
if i >= len(subject):
raise TemplateSyntaxError, "Searching for value. Unexpected end of string in column %d: %s" % subject
raise TemplateSyntaxError, "Searching for value. Unexpected end of string in column %d: %s" % (i, subject)
i += 1
s = subject[p:i]
while i < len(subject) and subject[i] in (' ', '\t'):

View File

@ -237,7 +237,7 @@ class RegroupNode(Node):
return ''
output = [] # list of dictionaries in the format {'grouper': 'key', 'list': [list of contents]}
for obj in obj_list:
grouper = self.expression.resolve(Context({'var': obj}), True)
grouper = self.expression.resolve(obj, True)
# TODO: Is this a sensible way to determine equality?
if output and repr(output[-1]['grouper']) == repr(grouper):
output[-1]['list'].append(obj)
@ -847,7 +847,7 @@ def regroup(parser, token):
if lastbits_reversed[1][::-1] != 'as':
raise TemplateSyntaxError, "next-to-last argument to 'regroup' tag must be 'as'"
expression = parser.compile_filter('var.%s' % lastbits_reversed[2][::-1])
expression = parser.compile_filter(lastbits_reversed[2][::-1])
var_name = lastbits_reversed[0][::-1]
return RegroupNode(target, expression, var_name)

View File

@ -1,3 +1,8 @@
# This is a slightly modified version of the doctest.py that shipped with Python 2.4
# It incorporates changes that have been submitted the the Python ticket tracker
# as ticket #1521051. These changes allow for a DoctestRunner and Doctest base
# class to be specified when constructing a DoctestSuite.
# Module doctest.
# Released to the public domain 16-Jan-2001, by Tim Peters (tim@python.org).
# Major enhancements and refactoring by:

View File

@ -1,5 +1,6 @@
import unittest, doctest
import unittest
from django.conf import settings
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
from django.test.testcases import OutputChecker, DocTestRunner

View File

@ -1,8 +1,9 @@
import re, doctest, unittest
import re, unittest
from urlparse import urlparse
from django.db import transaction
from django.core import management, mail
from django.db.models import get_apps
from django.test import _doctest as doctest
from django.test.client import Client
normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)

View File

@ -73,6 +73,20 @@ def _set_autocommit(connection):
elif hasattr(connection.connection, "set_isolation_level"):
connection.connection.set_isolation_level(0)
def get_mysql_create_suffix():
suffix = []
if settings.TEST_DATABASE_CHARSET:
suffix.append('CHARACTER SET %s' % settings.TEST_DATABASE_CHARSET)
if settings.TEST_DATABASE_COLLATION:
suffix.append('COLLATE %s' % settings.TEST_DATABASE_COLLATION)
return ' '.join(suffix)
def get_postgresql_create_suffix():
assert settings.TEST_DATABASE_COLLATION is None, "PostgreSQL does not support collation setting at database creation time."
if settings.TEST_DATABASE_CHARSET:
return "WITH ENCODING '%s'" % settings.TEST_DATABASE_CHARSET
return ''
def create_test_db(verbosity=1, autoclobber=False):
if verbosity >= 1:
print "Creating test database..."
@ -81,6 +95,12 @@ def create_test_db(verbosity=1, autoclobber=False):
if settings.DATABASE_ENGINE == "sqlite3":
TEST_DATABASE_NAME = ":memory:"
else:
suffix = {
'postgresql': get_postgresql_create_suffix,
'postgresql_psycopg2': get_postgresql_create_suffix,
'mysql': get_mysql_create_suffix,
'mysql_old': get_mysql_create_suffix,
}.get(settings.DATABASE_ENGINE, lambda: '')()
if settings.TEST_DATABASE_NAME:
TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME
else:
@ -92,7 +112,7 @@ def create_test_db(verbosity=1, autoclobber=False):
cursor = connection.cursor()
_set_autocommit(connection)
try:
cursor.execute("CREATE DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME))
cursor.execute("CREATE DATABASE %s %s" % (backend.quote_name(TEST_DATABASE_NAME), suffix))
except Exception, e:
sys.stderr.write("Got an error creating the test database: %s\n" % e)
if not autoclobber:
@ -104,7 +124,7 @@ def create_test_db(verbosity=1, autoclobber=False):
cursor.execute("DROP DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME))
if verbosity >= 1:
print "Creating test database..."
cursor.execute("CREATE DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME))
cursor.execute("CREATE DATABASE %s %s" % (backend.quote_name(TEST_DATABASE_NAME), suffix))
except Exception, e:
sys.stderr.write("Got an error recreating the test database: %s\n" % e)
sys.exit(2)

View File

@ -168,6 +168,8 @@ class Rss201rev2Feed(RssFeed):
(item['author_email'], item['author_name']))
elif item["author_email"]:
handler.addQuickElement(u"author", item["author_email"])
elif item["author_name"]:
handler.addQuickElement(u"dc:creator", item["author_name"], {"xmlns:dc": u"http://purl.org/dc/elements/1.1/"})
if item['pubdate'] is not None:
handler.addQuickElement(u"pubDate", rfc2822_date(item['pubdate']).decode('ascii'))

View File

@ -6,8 +6,9 @@ Django aims to follow Python's `"batteries included" philosophy`_. It ships
with a variety of extra, optional tools that solve common Web-development
problems.
This code lives in ``django/contrib`` in the Django distribution. Here's a
rundown of the packages in ``contrib``:
This code lives in ``django/contrib`` in the Django distribution. This document
gives a rundown of the packages in ``contrib``, along with any dependencies
those packages have.
.. admonition:: Note
@ -26,6 +27,8 @@ The automatic Django administrative interface. For more information, see
.. _Tutorial 2: ../tutorial02/
Requires the auth_ and contenttypes_ contrib packages to be installed.
auth
====
@ -144,6 +147,8 @@ See the `flatpages documentation`_.
.. _flatpages documentation: ../flatpages/
Requires the sites_ contrib package to be installed as well.
localflavor
===========

View File

@ -134,6 +134,15 @@ the database until you explicitly call ``save()``.
The ``save()`` method has no return value.
Updating ``ForeignKey`` fields works exactly the same way; simply assign an
object of the right type to the field in question::
joe = Author.objects.create(name="Joe")
entry.author = joe
entry.save()
Django will complain if you try to assign an object of the wrong type.
How Django knows to UPDATE vs. INSERT
-------------------------------------
@ -1229,8 +1238,8 @@ whose ``headline`` contains ``'Lennon'``::
Blog.objects.filter(entry__headline__contains='Lennon')
Escaping parenthesis and underscores in LIKE statements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Escaping percent signs and underscores in LIKE statements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The field lookups that equate to ``LIKE`` SQL statements (``iexact``,
``contains``, ``icontains``, ``startswith``, ``istartswith``, ``endswith``
@ -1748,7 +1757,8 @@ Shortcuts
As you develop views, you will discover a number of common idioms in the
way you use the database API. Django encodes some of these idioms as
shortcuts that can be used to simplify the process of writing views.
shortcuts that can be used to simplify the process of writing views. These
functions are in the ``django.shortcuts`` module.
get_object_or_404()
-------------------

View File

@ -295,7 +295,7 @@ Serving static files with the development server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
By default, the development server doesn't serve any static files for your site
(such as CSS files, images, things under ``MEDIA_ROOT_URL`` and so forth). If
(such as CSS files, images, things under ``MEDIA_URL`` and so forth). If
you want to configure Django to serve static media, read the `serving static files`_
documentation.
@ -403,9 +403,10 @@ this command to install the default apps.
If you're installing the ``django.contrib.auth`` application, ``syncdb`` will
give you the option of creating a superuser immediately.
``syncdb`` will also search for and install any fixture named ``initial_data``.
See the documentation for ``loaddata`` for details on the specification of
fixture data files.
``syncdb`` will also search for and install any fixture named ``initial_data``
with an appropriate extension (e.g. ``json`` or ``xml``). See the
documentation for ``loaddata`` for details on the specification of fixture
data files.
test
----

View File

@ -203,7 +203,7 @@ This is probably the most common case, if you're using Django's admin site::
DocumentRoot /home/user/public_html
Alias /media /home/user/python/django/contrib/admin/media
RewriteEngine On
RewriteRule ^/(media.*)$ /$1 [QSA,L]
RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
</VirtualHost>

View File

@ -99,6 +99,9 @@ which is a dictionary of the parameters captured in the URL.
dictionary is callable, the generic view will call it
just before rendering the template.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
**Example:**
Given the following URL patterns::

View File

@ -97,7 +97,9 @@ This file should also be located in your ``site-packages`` directory.
* If you're using Windows: ``C:\Python2.X\lib\site-packages``
* If you're using MacOSX: ``/Library/Python2.X/site-packages``
* If you're using MacOSX: ``/Library/Python2.X/site-packages`` or
``/Library/Frameworks/Python.framework/Versions/2.X/lib/python2.X/site-packages/``
(in later releases).
Install the Django code
=======================

View File

@ -269,6 +269,13 @@ For example, say your ``MEDIA_ROOT`` is set to ``'/home/media'``, and
upload a file on Jan. 15, 2007, it will be saved in the directory
``/home/media/photos/2007/01/15``.
If you want to retrieve the upload file's on-disk filename, or a URL that
refers to that file, or the file's size, you can use the
``get_FOO_filename()``, ``get_FOO_url()`` and ``get_FOO_size()`` methods.
They are all documented here__.
__ ../db-api/#get-foo-filename
Note that whenever you deal with uploaded files, you should pay close attention
to where you're uploading them and what type of files they are, to avoid
security holes. *Validate all uploaded files* so that you're sure the files are
@ -338,9 +345,14 @@ image. Has two extra optional arguments, ``height_field`` and
``width_field``, which, if set, will be auto-populated with the height and
width of the image each time a model instance is saved.
In addition to the special ``get_FOO_*`` methods that are available for
``FileField``, an ``ImageField`` also has ``get_FOO_height()`` and
``get_FOO_width()`` methods. These are documented elsewhere_.
Requires the `Python Imaging Library`_.
.. _Python Imaging Library: http://www.pythonware.com/products/pil/
.. _elsewhere: ../db-api/#get-foo-height-and-get-foo-width
``IntegerField``
~~~~~~~~~~~~~~~~
@ -463,8 +475,10 @@ If ``True``, Django will store empty values as ``NULL`` in the database.
Default is ``False``.
Note that empty string values will always get stored as empty strings, not
as ``NULL`` -- so use ``null=True`` for non-string fields such as integers,
booleans and dates.
as ``NULL``. Only use ``null=True`` for non-string fields such as integers,
booleans and dates. For both types of fields, you will also need to set
``blank=True`` if you wish to permit empty values in forms, as the ``null``
parameter only affects database storage (see blank_, below).
Avoid using ``null`` on string-based fields such as ``CharField`` and
``TextField`` unless you have an excellent reason. If a string-based field
@ -1846,14 +1860,15 @@ rows. Example::
row = cursor.fetchone()
return row
``connection`` and ``cursor`` simply use the standard `Python DB-API`_. If
you're not familiar with the Python DB-API, note that the SQL statement in
``cursor.execute()`` uses placeholders, ``"%s"``, rather than adding parameters
directly within the SQL. If you use this technique, the underlying database
library will automatically add quotes and escaping to your parameter(s) as
necessary. (Also note that Django expects the ``"%s"`` placeholder, *not* the
``"?"`` placeholder, which is used by the SQLite Python bindings. This is for
the sake of consistency and sanity.)
``connection`` and ``cursor`` mostly implement the standard `Python DB-API`_
(except when it comes to `transaction handling`_). If you're not familiar with
the Python DB-API, note that the SQL statement in ``cursor.execute()`` uses
placeholders, ``"%s"``, rather than adding parameters directly within the SQL.
If you use this technique, the underlying database library will automatically
add quotes and escaping to your parameter(s) as necessary. (Also note that
Django expects the ``"%s"`` placeholder, *not* the ``"?"`` placeholder, which is
used by the SQLite Python bindings. This is for the sake of consistency and
sanity.)
A final note: If all you want to do is a custom ``WHERE`` clause, you can just
just the ``where``, ``tables`` and ``params`` arguments to the standard lookup
@ -1861,6 +1876,7 @@ API. See `Other lookup options`_.
.. _Python DB-API: http://www.python.org/peps/pep-0249.html
.. _Other lookup options: ../db-api/#extra-params-select-where-tables
.. _transaction handling: ../transactions/
Overriding default model methods
--------------------------------

View File

@ -51,9 +51,17 @@ whereas ``<Location>`` points at places in the URL structure of a Web site.
``<Directory>`` would be meaningless here.
Also, if you've manually altered your ``PYTHONPATH`` to put your Django project
on it, you'll need to tell mod_python::
on it, you'll need to tell mod_python:
PythonPath "['/path/to/project'] + sys.path"
.. parsed-literal::
<Location "/mysite/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug On
**PythonPath "['/path/to/project'] + sys.path"**
</Location>
.. caution::
@ -211,6 +219,41 @@ Here are two recommended approaches:
2. Or, copy the admin media files so that they live within your Apache
document root.
Using eggs with mod_python
==========================
If you installed Django from a Python egg_ or are using eggs in your Django
project, some extra configuration is required. Create an extra file in your
project (or somewhere else) that contains something like the following::
import os
os.environ['PYTHON_EGG_CACHE'] = '/some/directory'
Here, ``/some/directory`` is a directory that the Apache webserver process can
write to. It will be used as the location for any unpacking of code the eggs
need to do.
Then you have to tell mod_python to import this file before doing anything
else. This is done using the PythonImport_ directive to mod_python. You need
to ensure that you have specified the ``PythonInterpreter`` directive to
mod_python as described above__ (you need to do this even if you aren't
serving multiple installations in this case). Then add the ``PythonImport``
line inside the ``Location`` or ``VirtualHost`` section. For example::
PythonInterpreter my_django
PythonImport /path/to/my/project/file.py my_django
Note that you can use an absolute path here (or a normal dotted import path),
as described in the `mod_python manual`_. We use an absolute path in the
above example because if any Python path modifications are required to access
your project, they will not have been done at the time the ``PythonImport``
line is processed.
.. _Egg: http://peak.telecommunity.com/DevCenter/PythonEggs
.. _PythonImport: http://www.modpython.org/live/current/doc-html/dir-other-pimp.html
.. _mod_python manual: PythonImport_
__ `Multiple Django installations on the same Apache`_
Error handling
==============
@ -256,3 +299,5 @@ as necessary.
.. _Expat Causing Apache Crash: http://www.dscpl.com.au/articles/modpython-006.html
.. _mod_python FAQ entry: http://modpython.org/FAQ/faqw.py?req=show&file=faq02.013.htp
.. _Getting mod_python Working: http://www.dscpl.com.au/articles/modpython-001.html

View File

@ -686,13 +686,13 @@ For example::
<form method="post">
<ul class="myformclass">
<li>{{ form.sender.label }} {{ form.sender.label }}</li>
<li>{{ form.sender.label }} {{ form.sender }}</li>
<li class="helptext">{{ form.sender.help_text }}</li>
{% if form.sender.errors %}<ul class="errorlist">{{ form.sender.errors }}</dd>{% endif %}
{% if form.sender.errors %}<ul class="errorlist">{{ form.sender.errors }}</ul>{% endif %}
<li>{{ form.subject.label }} {{ form.subject.label }}</li>
<li>{{ form.subject.label }} {{ form.subject }}</li>
<li class="helptext">{{ form.subject.help_text }}</li>
{% if form.subject.errors %}<ul class="errorlist">{{ form.subject.errors }}</dd>{% endif %}
{% if form.subject.errors %}<ul class="errorlist">{{ form.subject.errors }}</ul>{% endif %}
...
</ul>

View File

@ -44,6 +44,25 @@ This is useful if you want to serialize data directly to a file-like object
.. _HTTPResponse: ../request_response/#httpresponse-objects
Subset of fields
~~~~~~~~~~~~~~~~
If you only want a subset of fields to be serialized, you can
specify a `fields` argument to the serializer::
from django.core import serializers
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))
In this example, only the `name` and `size` attributes of each model will
be serialized.
.. note::
Depending on your model, you may find that it is not possible to deserialize
a model that only serializes a subset of its fields. If a serialized object
doesn't specify all the fields that are required by a model, the deserializer
will not be able to save deserialized instances.
Deserializing data
------------------
@ -92,10 +111,14 @@ Django "ships" with a few included serializers:
``python`` Translates to and from "simple" Python objects (lists, dicts,
strings, etc.). Not really all that useful on its own, but
used as a base for other serializers.
``yaml`` Serializes to YAML (Yet Another Markup Lanuage). This
serializer is only available if PyYAML_ is installed.
========== ==============================================================
.. _json: http://json.org/
.. _simplejson: http://undefined.org/python/#simplejson
.. _PyYAML: http://www.pyyaml.org/
Notes for specific serialization formats
----------------------------------------

View File

@ -264,6 +264,11 @@ MySQL will connect via a Unix socket to the specified socket. For example::
If you're using MySQL and this value *doesn't* start with a forward slash, then
this value is assumed to be the host.
If you're using PostgreSQL, an empty string means to use a Unix domain socket
for the connection, rather than a network connection to localhost. If you
explictly need to use a TCP/IP connection on the local machine with
PostgreSQL, specify ``localhost`` here.
DATABASE_NAME
-------------
@ -771,7 +776,8 @@ Default::
("django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n")
"django.core.context_processors.i18n",
"django.core.context_processors.media")
A tuple of callables that are used to populate the context in ``RequestContext``.
These callables take a request object as their argument and return a dictionary
@ -820,15 +826,36 @@ misspelled) variables. See `How invalid variables are handled`_.
.. _How invalid variables are handled: ../templates_python/#how-invalid-variables-are-handled
TEST_RUNNER
-----------
TEST_DATABASE_CHARSET
---------------------
Default: ``'django.test.simple.run_tests'``
**New in Django development version**
The name of the method to use for starting the test suite. See
`Testing Django Applications`_.
Default: ``None``
.. _Testing Django Applications: ../testing/
The character set encoding used to create the test database. The value of this
string is passed directly through to the database, so its format is
backend-specific.
Supported for the PostgreSQL_ (``postgresql``, ``postgresql_psycopg2``) and MySQL_ (``mysql``, ``mysql_old``) backends.
.. _PostgreSQL: http://www.postgresql.org/docs/8.2/static/multibyte.html
.. _MySQL: http://www.mysql.org/doc/refman/5.0/en/charset-database.html
TEST_DATABASE_COLLATION
------------------------
**New in Django development version**
Default: ``None``
The collation order to use when creating the test database. This value is
passed directly to the backend, so its format is backend-specific.
Only supported for ``mysql`` and ``mysql_old`` backends (see `section 10.3.2`_
of the MySQL manual for details).
.. _section 10.3.2: http://www.mysql.org/doc/refman/5.0/en/charset-database.html
TEST_DATABASE_NAME
------------------
@ -840,6 +867,16 @@ The name of database to use when running the test suite. If a value of
.. _Testing Django Applications: ../testing/
TEST_RUNNER
-----------
Default: ``'django.test.simple.run_tests'``
The name of the method to use for starting the test suite. See
`Testing Django Applications`_.
.. _Testing Django Applications: ../testing/
TIME_FORMAT
-----------

View File

@ -91,9 +91,12 @@ Filters can be "chained." The output of one filter is applied to the next.
``{{ text|escape|linebreaks }}`` is a common idiom for escaping text contents,
then converting line breaks to ``<p>`` tags.
Some filters take arguments. A filter argument looks like this:
``{{ bio|truncatewords:"30" }}``. This will display the first 30 words of the
``bio`` variable. Filter arguments always are in double quotes.
Some filters take arguments. A filter argument looks like this: ``{{
bio|truncatewords:30 }}``. This will display the first 30 words of the ``bio``
variable.
Filter arguments that contain spaces must be quoted; for example, to join a list
with commas and spaced you'd use ``{{ list|join:", " }}``.
The `Built-in filter reference`_ below describes all the built-in filters.
@ -112,7 +115,7 @@ know how to write Python code.
Comments
========
To comment-out part of a template, use the comment syntax: ``{# #}``.
To comment-out part of a line in a template, use the comment syntax: ``{# #}``.
For example, this template would render as ``'hello'``::
@ -122,6 +125,12 @@ A comment can contain any template code, invalid or not. For example::
{# {% if foo %}bar{% else %} #}
This syntax can only be used for single-line comments (no newlines are
permitted between the ``{#`` and ``#}`` delimiters). If you need to comment
out a multiline portion of the template, see the ``comment`` tag, below__.
__ comment_
Template inheritance
====================
@ -843,10 +852,11 @@ The first argument is a path to a view function in the format
should be comma-separated values that will be used as positional and keyword
arguments in the URL. All arguments required by the URLconf should be present.
For example, suppose you have a view, ``app_name.client``, whose URLconf takes
a client ID. The URLconf line might look like this::
For example, suppose you have a view, ``app_views.client``, whose URLconf
takes a client ID (here, ``client()`` is a method inside the views file
``app_views.py``). The URLconf line might look like this::
('^client/(\d+)/$', 'app_name.client')
('^client/(\d+)/$', 'app_views.client')
If this app's URLconf is included into the project's URLconf under a path
such as this::
@ -855,7 +865,7 @@ such as this::
...then, in a template, you can create a link to this view like this::
{% url app_name.client client.id %}
{% url app_views.client client.id %}
The template tag will output the string ``/clients/client/123/``.

View File

@ -294,7 +294,8 @@ return a dictionary of items to be merged into the context. By default,
("django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n")
"django.core.context_processors.i18n",
"django.core.context_processors.media")
Each processor is applied in order. That means, if one processor adds a
variable to the context and a second processor adds a variable with the same
@ -390,6 +391,15 @@ See the `internationalization docs`_ for more.
.. _LANGUAGE_CODE setting: ../settings/#language-code
.. _internationalization docs: ../i18n/
django.core.context_processors.media
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
``RequestContext`` will contain a variable ``MEDIA_URL``, providing the
value of the `MEDIA_URL setting`_.
.. _MEDIA_URL setting: ../settings/#media-url
django.core.context_processors.request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -4,7 +4,7 @@ Testing Django applications
Automated testing is an extremely useful bug-killing tool for the modern
Web developer. You can use a collection of tests -- a **test suite** -- to
to solve, or avoid, a number of problems:
solve, or avoid, a number of problems:
* When you're writing new code, you can use tests to validate your code
works as expected.
@ -147,7 +147,7 @@ doctests or unit tests are right for you.
If you've been using Python for a while, ``doctest`` will probably feel more
"pythonic". It's designed to make writing tests as easy as possible, so
there's no overhead of writing classes or methods; you simply put tests in
docstrings. This gives the added advantage of given your modules automatic
docstrings. This gives the added advantage of giving your modules automatic
documentation -- well-written doctests can kill both the documentation and the
testing bird with a single stone.
@ -571,6 +571,14 @@ database settings will the same as they would be for the project normally.
If you wish to use a name other than the default for the test database,
you can use the ``TEST_DATABASE_NAME`` setting to provide a name.
**New in Django development version:** For fine-grained control over the
character encoding of your database, use the ``TEST_DATABASE_CHARSET`` setting.
If you're using MySQL, you can also use the ``TEST_DATABASE_COLLATION`` setting
to control the particular collation used by the test database. See the
settings_ documentation for details of these advanced settings.
.. _settings: ../settings/
The test database is created by the user in the ``DATABASE_USER`` setting.
This user needs to have sufficient privileges to create a new database on the
system.

View File

@ -60,9 +60,10 @@ arguments from the dictionary (an optional third item in the tuple).
For more on ``HTTPRequest`` objects, see the `request and response documentation`_.
For more details on URLconfs, see the `URLconf documentation`_.
When you ran ``python manage.py startproject mysite`` at the beginning of
When you ran ``python django-admin.py startproject mysite`` at the beginning of
Tutorial 1, it created a default URLconf in ``mysite/urls.py``. It also
automatically set your ``ROOT_URLCONF`` setting to point at that file::
automatically set your ``ROOT_URLCONF`` setting (in ``settings.py``) to point
at that file::
ROOT_URLCONF = 'mysite.urls'

View File

@ -48,6 +48,7 @@ So let's create a ``vote()`` function in ``mysite/polls/views.py``::
from django.shortcuts import get_object_or_404, render_to_response
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from mysite.polls.models import Choice, Poll
# ...
def vote(request, poll_id):
@ -66,7 +67,7 @@ So let's create a ``vote()`` function in ``mysite/polls/views.py``::
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect('/polls/%s/results/' % p.id)
return HttpResponseRedirect(reverse('mysite.polls.views.results', args=(p.id,)))
This code includes a few things we haven't covered yet in this tutorial:
@ -86,13 +87,29 @@ This code includes a few things we haven't covered yet in this tutorial:
* After incrementing the choice count, the code returns an
``HttpResponseRedirect`` rather than a normal ``HttpResponse``.
``HttpResponseRedirect`` takes a single argument: the URL to which the
user will be redirected. You should leave off the "http://" and domain
name if you can. That helps your app become portable across domains.
user will be redirected (see the following point for how we construct
the URL in this case).
As the Python comment above points out, you should always return an
``HttpResponseRedirect`` after successfully dealing with POST data. This
tip isn't specific to Django; it's just good Web development practice.
* We are using the ``reverse()`` function in the ``HttpResponseRedirect``
constructor in this example. This function helps avoid having to
hardcode a URL in the view function. It is given the name of the view
that we want to pass control to and the variable portion of the URL
pattern that points to that view. In this case, using the URLConf we set
up in Tutorial 3, this ``reverse()`` call will return a string like ::
'/polls/3/results/'
... where the ``3`` is the value of ``p.id``. This redirected URL will
then call the ``'results'`` view to display the final page. Note that
you need to use the full name of the view here (including the prefix).
For more information about ``reverse()``, see the `URL dispatcher`_
documentation.
As mentioned in Tutorial 3, ``request`` is a ``HTTPRequest`` object. For more
on ``HTTPRequest`` objects, see the `request and response documentation`_.
@ -121,6 +138,7 @@ results page that gets updated each time you vote. If you submit the form
without having chosen a choice, you should see the error message.
.. _request and response documentation: ../request_response/
.. _URL dispatcher: ../url_dispatch#reverse
Use generic views: Less code is better
======================================
@ -256,4 +274,8 @@ installments:
* Advanced admin features: Permissions
* Advanced admin features: Custom JavaScript
In the meantime, you can read through the rest of the `Django documentation`_
and start writing your own applications.
.. _Tutorial 3: ../tutorial03/
.. _Django documentation: http://www.djangoproject.com/documentation/

View File

@ -551,3 +551,38 @@ not restricted to valid Python names.
Putting a prefix on your URL names, perhaps derived from the application
name, will decrease the chances of collision. We recommend something like
``myapp-comment`` instead of ``comment``.
Utility methods
===============
reverse()
---------
If you need to use something similar to the ``{% url %}`` template tag in your
code, Django provides the ``django.core.urlresolvers.reverse()``. The
``reverse()`` function has the following signature::
reverse(viewname, urlconf=None, args=None, kwargs=None)
``viewname`` is either the function name (either a function reference, or the
string version of the name, if you used that form in ``urlpatterns``) or the
`URL pattern name`_. Normally, you won't need to worry about the
``urlconf`` parameter and will only pass in the positional and keyword
arguments to use in the URL matching. For example::
from django.core.urlresolvers import reverse
def myview(request):
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
.. _URL pattern name: `Naming URL patterns`_
permalink()
-----------
The ``permalink()`` decorator is useful for writing short methods that return
a full URL path. For example, a model's ``get_absolute_url()`` method. Refer
to the `model API documentation`_ for more information about ``permalink()``.
.. _model API documentation: ../model-api/#the-permalink-decorator

View File

@ -131,6 +131,27 @@ True
[('headline', 'Article 7'), ('id', 7)]
[('headline', 'Article 1'), ('id', 1)]
# you can use values() even on extra fields
>>> for d in Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_one'):
... i = d.items()
... i.sort()
... i
[('id', 5), ('id_plus_one', 6)]
[('id', 6), ('id_plus_one', 7)]
[('id', 4), ('id_plus_one', 5)]
[('id', 2), ('id_plus_one', 3)]
[('id', 3), ('id_plus_one', 4)]
[('id', 7), ('id_plus_one', 8)]
[('id', 1), ('id_plus_one', 2)]
# however, an exception FieldDoesNotExist will still be thrown
# if you try to access non-existent field (field that is neither on the model nor extra)
>>> Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_two')
Traceback (most recent call last):
...
FieldDoesNotExist: Article has no field named 'id_plus_two'
# if you don't specify which fields, all are returned
>>> list(Article.objects.filter(id=5).values()) == [{'id': 5, 'headline': 'Article 5', 'pub_date': datetime(2005, 8, 1, 9, 0)}]
True

View File

@ -159,4 +159,8 @@ __test__ = {'API_TESTS':"""
>>> article.author
<Author: Agnes>
# Serializer output can be restricted to a subset of fields
>>> print serializers.serialize("json", Article.objects.all(), fields=('headline','pub_date'))
[{"pk": "1", "model": "serializers.article", "fields": {"headline": "Just kidding; I love TV poker", "pub_date": "2006-06-16 11:00:00"}}, {"pk": "2", "model": "serializers.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": "3", "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00"}}]
"""}

View File

@ -3656,6 +3656,25 @@ u' id="header"'
u' class="news" title="Read this"'
>>> flatatt({})
u''
####################################
# Test accessing errors in clean() #
####################################
>>> class UserForm(Form):
... username = CharField(max_length=10)
... password = CharField(widget=PasswordInput)
... def clean(self):
... data = self.cleaned_data
... if not self.errors:
... data['username'] = data['username'].lower()
... return data
>>> f = UserForm({'username': 'SirRobin', 'password': 'blue'})
>>> f.is_valid()
True
>>> f.cleaned_data['username']
u'sirrobin'
"""
__test__ = {

View File

@ -129,6 +129,9 @@ class M2MSelfData(models.Model):
class FKDataToField(models.Model):
data = models.ForeignKey(UniqueAnchor, null=True, to_field='data')
class FKDataToO2O(models.Model):
data = models.ForeignKey(O2OData, null=True)
# The following test classes are for validating the
# deserialization of objects that use a user-defined
# field as the primary key.
@ -202,3 +205,7 @@ class USStatePKData(models.Model):
# class XMLPKData(models.Model):
# data = models.XMLField(primary_key=True)
class ComplexModel(models.Model):
field1 = models.CharField(maxlength=10)
field2 = models.CharField(maxlength=10)
field3 = models.CharField(maxlength=10)

View File

@ -9,6 +9,7 @@ forward, backwards and self references.
import unittest, datetime
from cStringIO import StringIO
from django.utils.functional import curry
from django.core import serializers
@ -197,6 +198,8 @@ The end."""),
(fk_obj, 451, FKDataToField, "UAnchor 2"),
(fk_obj, 452, FKDataToField, None),
(fk_obj, 460, FKDataToO2O, 300),
(data_obj, 500, Anchor, "Anchor 3"),
(data_obj, 501, Anchor, "Anchor 4"),
(data_obj, 502, UniqueAnchor, "UAnchor 2"),
@ -276,5 +279,41 @@ def serializerTest(format, self):
for (func, pk, klass, datum) in test_data:
func[1](self, pk, klass, datum)
def fieldsTest(format, self):
# Clear the database first
management.flush(verbosity=0, interactive=False)
obj = ComplexModel(field1='first',field2='second',field3='third')
obj.save()
# Serialize then deserialize the test database
serialized_data = serializers.serialize(format, [obj], indent=2, fields=('field1','field3'))
result = serializers.deserialize(format, serialized_data).next()
# Check that the deserialized object contains data in only the serialized fields.
self.assertEqual(result.object.field1, 'first')
self.assertEqual(result.object.field2, '')
self.assertEqual(result.object.field3, 'third')
def streamTest(format, self):
# Clear the database first
management.flush(verbosity=0, interactive=False)
obj = ComplexModel(field1='first',field2='second',field3='third')
obj.save()
# Serialize the test database to a stream
stream = StringIO()
serializers.serialize(format, [obj], indent=2, stream=stream)
# Serialize normally for a comparison
string_data = serializers.serialize(format, [obj], indent=2)
# Check that the two are the same
self.assertEqual(string_data, stream.buffer())
stream.close()
for format in serializers.get_serializer_formats():
setattr(SerializerTests, 'test_'+format+'_serializer', curry(serializerTest, format))
setattr(SerializerTests, 'test_'+format+'_serializer_fields', curry(fieldsTest, format))
setattr(SerializerTests, 'test_'+format+'_serializer_stream', curry(fieldsTest, format))