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

newforms-admin: Merged from trunk up to [7668].

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7669 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Brian Rosner 2008-06-16 20:36:34 +00:00
parent d0af06bad8
commit a253ec3743
49 changed files with 5027 additions and 416 deletions

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python
""" """
gather_profile_stats.py /path/to/dir/of/profiles gather_profile_stats.py /path/to/dir/of/profiles

View File

@ -11,9 +11,10 @@ gettext_noop = lambda s: s
DEBUG = False DEBUG = False
TEMPLATE_DEBUG = False TEMPLATE_DEBUG = False
# True if BaseHandler.get_response() should propagate raw exceptions
# rather than catching them. This is useful under some testing siutations, # Whether the framework should propagate raw exceptions rather than catching
# and should never be used on a live site. # them. This is useful under some testing siutations and should never be used
# on a live site.
DEBUG_PROPAGATE_EXCEPTIONS = False DEBUG_PROPAGATE_EXCEPTIONS = False
# Whether to use the "Etag" header. This saves bandwidth but slows down performance. # Whether to use the "Etag" header. This saves bandwidth but slows down performance.
@ -289,7 +290,7 @@ SESSION_COOKIE_DOMAIN = None # A string like ".lawren
SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only). SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only).
SESSION_COOKIE_PATH = '/' # The path of the session cookie. SESSION_COOKIE_PATH = '/' # The path of the session cookie.
SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request. SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request.
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether a user's session cookie expires when they close their browser. SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether a user's session cookie expires when the Web browser is closed.
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # The module to store session data SESSION_ENGINE = 'django.contrib.sessions.backends.db' # The module to store session data
SESSION_FILE_PATH = None # Directory to store session files if using the file session module. If None, the backend will use a sensible default. SESSION_FILE_PATH = None # Directory to store session files if using the file session module. If None, the backend will use a sensible default.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,115 @@
# Estonian translation for the Django Project.
# Copyright (C) 2008, Django Project
# This file is distributed under the same license as the django package.
msgid ""
msgstr ""
"Project-Id-Version: Django"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2008-06-02 19:42+0300\n"
"PO-Revision-Date: 2008-06-16 19:55+0200\n"
"Last-Translator: Erik Allik <removethis-eallik_at_gmail-com>\n"
"Language-Team: Django-i18n <django-i18n@googlegroups.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Saadaval %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Vali kõik"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Lisa"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Eemalda"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Valitud %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Tee valik(ud) ja klõpsa"
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Puhasta kõik"
#: contrib/admin/media/js/calendar.js:24
#: contrib/admin/media/js/dateparse.js:32
msgid ""
"January February March April May June July August September October November "
"December"
msgstr "Jaanuar Veebruar Märts Aprill Mai Juuni Juuli August September Oktoober November Detsember"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "P E T K N R L"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Pühapäev Esmaspäev Teisipäev Kolmapäev Neljapäev Reede Laupäev"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr "Näita"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr "Varja"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr "Praegu"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "Kell"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "Vali aeg"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "Kesköö"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "6 hommikul"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Keskpäev"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr "Tühista"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "Täna"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "Kalender"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "Eile"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Homme"

View File

@ -38,7 +38,8 @@ class FlatPageAdmin(admin.ModelAdmin):
(None, {'fields': ('url', 'title', 'content', 'sites')}), (None, {'fields': ('url', 'title', 'content', 'sites')}),
(_('Advanced options'), {'classes': ('collapse',), 'fields': ('enable_comments', 'registration_required', 'template_name')}), (_('Advanced options'), {'classes': ('collapse',), 'fields': ('enable_comments', 'registration_required', 'template_name')}),
) )
list_filter = ('sites',) list_display = ('url', 'title')
list_filter = ('sites', 'enable_comments', 'registration_required')
search_fields = ('url', 'title') search_fields = ('url', 'title')
admin.site.register(FlatPage, FlatPageAdmin) admin.site.register(FlatPage, FlatPageAdmin)

View File

@ -149,7 +149,7 @@ class FormWizard(object):
data = [(bf.name, bf.data or '') for bf in form] + [settings.SECRET_KEY] data = [(bf.name, bf.data or '') for bf in form] + [settings.SECRET_KEY]
# Use HIGHEST_PROTOCOL because it's the most efficient. It requires # Use HIGHEST_PROTOCOL because it's the most efficient. It requires
# Python 2.3, but Django requires 2.3 anyway, so that's OK. # Python 2.3, but Django requires 2.3 anyway, so that's OK.
pickled = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL) pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
return md5.new(pickled).hexdigest() return md5.new(pickled).hexdigest()
def determine_step(self, request, *args, **kwargs): def determine_step(self, request, *args, **kwargs):

View File

@ -27,7 +27,7 @@ class ITRegionSelect(Select):
class ITProvinceSelect(Select): class ITProvinceSelect(Select):
""" """
A Select widget that uses a list of IT regions as its choices. A Select widget that uses a list of IT provinces as its choices.
""" """
def __init__(self, attrs=None): def __init__(self, attrs=None):
from it_province import PROVINCE_CHOICES from it_province import PROVINCE_CHOICES

View File

@ -26,6 +26,7 @@ class Redirect(models.Model):
from django.contrib import admin from django.contrib import admin
class RedirectAdmin(admin.ModelAdmin): class RedirectAdmin(admin.ModelAdmin):
list_display = ('old_path', 'new_path')
list_filter = ('site',) list_filter = ('site',)
search_fields = ('old_path', 'new_path') search_fields = ('old_path', 'new_path')
radio_fields = {'site': admin.VERTICAL} radio_fields = {'site': admin.VERTICAL}

View File

@ -9,6 +9,8 @@ class Command(BaseCommand):
help='Specifies the output serialization format for fixtures.'), help='Specifies the output serialization format for fixtures.'),
make_option('--indent', default=None, dest='indent', type='int', make_option('--indent', default=None, dest='indent', type='int',
help='Specifies the indent level to use when pretty-printing output'), help='Specifies the indent level to use when pretty-printing output'),
make_option('-e', '--exclude', dest='exclude',action='append', default=[],
help='App to exclude (use multiple --exclude to exclude multiple apps).'),
) )
help = 'Output the contents of the database as a fixture of the given format.' help = 'Output the contents of the database as a fixture of the given format.'
args = '[appname ...]' args = '[appname ...]'
@ -16,12 +18,15 @@ class Command(BaseCommand):
def handle(self, *app_labels, **options): def handle(self, *app_labels, **options):
from django.db.models import get_app, get_apps, get_models from django.db.models import get_app, get_apps, get_models
format = options.get('format', 'json') format = options.get('format','json')
indent = options.get('indent', None) indent = options.get('indent',None)
exclude = options.get('exclude',[])
show_traceback = options.get('traceback', False) show_traceback = options.get('traceback', False)
excluded_apps = [get_app(app_label) for app_label in exclude]
if len(app_labels) == 0: if len(app_labels) == 0:
app_list = get_apps() app_list = [app for app in get_apps() if app not in excluded_apps]
else: else:
app_list = [get_app(app_label) for app_label in app_labels] app_list = [get_app(app_label) for app_label in app_labels]

View File

@ -111,7 +111,10 @@ class Command(BaseCommand):
models.add(obj.object.__class__) models.add(obj.object.__class__)
obj.save() obj.save()
label_found = True label_found = True
except Exception, e: except (SystemExit, KeyboardInterrupt):
raise
except Exception:
import traceback
fixture.close() fixture.close()
transaction.rollback() transaction.rollback()
transaction.leave_transaction_management() transaction.leave_transaction_management()
@ -121,7 +124,7 @@ class Command(BaseCommand):
else: else:
sys.stderr.write( sys.stderr.write(
self.style.ERROR("Problem installing fixture '%s': %s\n" % self.style.ERROR("Problem installing fixture '%s': %s\n" %
(full_path, str(e)))) (full_path, traceback.format_exc())))
return return
fixture.close() fixture.close()
except: except:

View File

@ -3,8 +3,7 @@ import os
from django.core.management.base import copy_helper, CommandError, LabelCommand from django.core.management.base import copy_helper, CommandError, LabelCommand
class Command(LabelCommand): class Command(LabelCommand):
help = ("Creates a Django app directory structure for the given app name" help = "Creates a Django app directory structure for the given app name in the current directory."
" in the current directory.")
args = "[appname]" args = "[appname]"
label = 'application name' label = 'application name'
@ -16,6 +15,7 @@ class Command(LabelCommand):
def handle_label(self, app_name, directory=None, **options): def handle_label(self, app_name, directory=None, **options):
if directory is None: if directory is None:
directory = os.getcwd() directory = os.getcwd()
# Determine the project_name by using the basename of directory, # Determine the project_name by using the basename of directory,
# which should be the full path of the project directory (or the # which should be the full path of the project directory (or the
# current directory if no directory was passed). # current directory if no directory was passed).
@ -23,6 +23,15 @@ class Command(LabelCommand):
if app_name == project_name: if app_name == project_name:
raise CommandError("You cannot create an app with the same name" raise CommandError("You cannot create an app with the same name"
" (%r) as your project." % app_name) " (%r) as your project." % app_name)
# Check that the app_name cannot be imported.
try:
__import__(app_name)
except ImportError:
pass
else:
raise CommandError("%r conflicts with the name of an existing Python module and cannot be used as an app name. Please try another name." % app_name)
copy_helper(self.style, 'app', app_name, directory, project_name) copy_helper(self.style, 'app', app_name, directory, project_name)
class ProjectCommand(Command): class ProjectCommand(Command):

View File

@ -3,8 +3,6 @@ import os
import re import re
from random import choice from random import choice
INVALID_PROJECT_NAMES = ('django', 'site', 'test')
class Command(LabelCommand): class Command(LabelCommand):
help = "Creates a Django project directory structure for the given project name in the current directory." help = "Creates a Django project directory structure for the given project name in the current directory."
args = "[projectname]" args = "[projectname]"
@ -20,13 +18,13 @@ class Command(LabelCommand):
# the parent directory. # the parent directory.
directory = os.getcwd() directory = os.getcwd()
# Check that the project_name cannot be imported.
try: try:
proj_name = __import__(project_name) __import__(project_name)
if proj_name:
raise CommandError("%r conflicts with the name of an existing Python module and cannot be used as a project name. Please try another name." % project_name)
except ImportError: except ImportError:
if project_name in INVALID_PROJECT_NAMES: pass
raise CommandError("%r contains an invalid project name. Please try another name." % project_name) else:
raise CommandError("%r conflicts with the name of an existing Python module and cannot be used as a project name. Please try another name." % project_name)
copy_helper(self.style, 'project', project_name, directory) copy_helper(self.style, 'project', project_name, directory)

View File

@ -34,7 +34,16 @@ class Command(NoArgsCommand):
try: try:
__import__(app_name + '.management', {}, {}, ['']) __import__(app_name + '.management', {}, {}, [''])
except ImportError, exc: except ImportError, exc:
if not exc.args[0].startswith('No module named management'): # This is slightly hackish. We want to ignore ImportErrors
# if the "management" module itself is missing -- but we don't
# want to ignore the exception if the management module exists
# but raises an ImportError for some reason. The only way we
# can do this is to check the text of the exception. Note that
# we're a bit broad in how we check the text, because different
# Python implementations may not use the same text. CPython
# uses the text "No module named management".
msg = exc.args[0]
if not msg.startswith('No module named management') or 'management' not in msg:
raise raise
cursor = connection.cursor() cursor = connection.cursor()

View File

@ -86,7 +86,7 @@ def reverse_helper(regex, *args, **kwargs):
""" """
# TODO: Handle nested parenthesis in the following regex. # TODO: Handle nested parenthesis in the following regex.
result = re.sub(r'\(([^)]+)\)', MatchChecker(args, kwargs), regex.pattern) result = re.sub(r'\(([^)]+)\)', MatchChecker(args, kwargs), regex.pattern)
return result.replace('^', '').replace('$', '') return result.replace('^', '').replace('$', '').replace('\\', '')
class MatchChecker(object): class MatchChecker(object):
"Class used in reverse RegexURLPattern lookup." "Class used in reverse RegexURLPattern lookup."

View File

@ -52,6 +52,10 @@ class BaseDatabaseFeatures(object):
uses_custom_query_class = False uses_custom_query_class = False
empty_fetchmany_value = [] empty_fetchmany_value = []
update_can_self_select = True update_can_self_select = True
supports_usecs = True
time_field_needs_date = False
interprets_empty_strings_as_nulls = False
date_field_supports_time_value = True
class BaseDatabaseOperations(object): class BaseDatabaseOperations(object):
""" """
@ -202,8 +206,8 @@ class BaseDatabaseOperations(object):
def query_class(self, DefaultQueryClass): def query_class(self, DefaultQueryClass):
""" """
Given the default QuerySet class, returns a custom QuerySet class Given the default Query class, returns a custom Query class
to use for this backend. Returns None if a custom QuerySet isn't used. to use for this backend. Returns None if a custom Query isn't used.
See also BaseDatabaseFeatures.uses_custom_query_class, which regulates See also BaseDatabaseFeatures.uses_custom_query_class, which regulates
whether this method is called at all. whether this method is called at all.
""" """
@ -266,3 +270,8 @@ class BaseDatabaseOperations(object):
tablespaces. tablespaces.
""" """
return None return None
def prep_for_like_query(self, x):
"""Prepares a value for use in a LIKE query."""
from django.utils.encoding import smart_unicode
return smart_unicode(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")

View File

@ -64,6 +64,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
inline_fk_references = False inline_fk_references = False
empty_fetchmany_value = () empty_fetchmany_value = ()
update_can_self_select = False update_can_self_select = False
supports_usecs = False
class DatabaseOperations(BaseDatabaseOperations): class DatabaseOperations(BaseDatabaseOperations):
def date_extract_sql(self, lookup_type, field_name): def date_extract_sql(self, lookup_type, field_name):

View File

@ -68,6 +68,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
inline_fk_references = False inline_fk_references = False
empty_fetchmany_value = () empty_fetchmany_value = ()
update_can_self_select = False update_can_self_select = False
supports_usecs = False
class DatabaseOperations(BaseDatabaseOperations): class DatabaseOperations(BaseDatabaseOperations):
def date_extract_sql(self, lookup_type, field_name): def date_extract_sql(self, lookup_type, field_name):

View File

@ -31,6 +31,9 @@ class DatabaseFeatures(BaseDatabaseFeatures):
supports_tablespaces = True supports_tablespaces = True
uses_case_insensitive_names = True uses_case_insensitive_names = True
uses_custom_query_class = True uses_custom_query_class = True
time_field_needs_date = True
interprets_empty_strings_as_nulls = True
date_field_supports_time_value = False
class DatabaseOperations(BaseDatabaseOperations): class DatabaseOperations(BaseDatabaseOperations):
def autoinc_sql(self, table, column): def autoinc_sql(self, table, column):

View File

@ -7,7 +7,7 @@ try:
except ImportError: except ImportError:
from django.utils import _decimal as decimal # for Python 2.3 from django.utils import _decimal as decimal # for Python 2.3
from django.db import get_creation_module from django.db import connection, get_creation_module
from django.db.models import signals from django.db.models import signals
from django.db.models.query_utils import QueryWrapper from django.db.models.query_utils import QueryWrapper
from django.dispatch import dispatcher from django.dispatch import dispatcher
@ -30,9 +30,6 @@ class NOT_PROVIDED:
BLANK_CHOICE_DASH = [("", "---------")] BLANK_CHOICE_DASH = [("", "---------")]
BLANK_CHOICE_NONE = [("", "None")] BLANK_CHOICE_NONE = [("", "None")]
# prepares a value for use in a LIKE query
prep_for_like_query = lambda x: smart_unicode(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")
class FieldDoesNotExist(Exception): class FieldDoesNotExist(Exception):
pass pass
@ -91,7 +88,7 @@ class Field(object):
self.blank, self.null = blank, null self.blank, self.null = blank, null
# Oracle treats the empty string ('') as null, so coerce the null # Oracle treats the empty string ('') as null, so coerce the null
# option whenever '' is a possible value. # option whenever '' is a possible value.
if self.empty_strings_allowed and settings.DATABASE_ENGINE == 'oracle': if self.empty_strings_allowed and connection.features.interprets_empty_strings_as_nulls:
self.null = True self.null = True
self.core, self.rel, self.default = core, rel, default self.core, self.rel, self.default = core, rel, default
self.editable = editable self.editable = editable
@ -227,13 +224,13 @@ class Field(object):
elif lookup_type in ('range', 'in'): elif lookup_type in ('range', 'in'):
return value return value
elif lookup_type in ('contains', 'icontains'): elif lookup_type in ('contains', 'icontains'):
return ["%%%s%%" % prep_for_like_query(value)] return ["%%%s%%" % connection.ops.prep_for_like_query(value)]
elif lookup_type == 'iexact': elif lookup_type == 'iexact':
return [prep_for_like_query(value)] return [connection.ops.prep_for_like_query(value)]
elif lookup_type in ('startswith', 'istartswith'): elif lookup_type in ('startswith', 'istartswith'):
return ["%s%%" % prep_for_like_query(value)] return ["%s%%" % connection.ops.prep_for_like_query(value)]
elif lookup_type in ('endswith', 'iendswith'): elif lookup_type in ('endswith', 'iendswith'):
return ["%%%s" % prep_for_like_query(value)] return ["%%%s" % connection.ops.prep_for_like_query(value)]
elif lookup_type == 'isnull': elif lookup_type == 'isnull':
return [] return []
elif lookup_type == 'year': elif lookup_type == 'year':
@ -244,9 +241,12 @@ class Field(object):
if settings.DATABASE_ENGINE == 'sqlite3': if settings.DATABASE_ENGINE == 'sqlite3':
first = '%s-01-01' first = '%s-01-01'
second = '%s-12-31 23:59:59.999999' second = '%s-12-31 23:59:59.999999'
elif settings.DATABASE_ENGINE == 'oracle' and self.get_internal_type() == 'DateField': elif not connection.features.date_field_supports_time_value and self.get_internal_type() == 'DateField':
first = '%s-01-01' first = '%s-01-01'
second = '%s-12-31' second = '%s-12-31'
elif not connection.features.supports_usecs:
first = '%s-01-01 00:00:00'
second = '%s-12-31 23:59:59.99'
else: else:
first = '%s-01-01 00:00:00' first = '%s-01-01 00:00:00'
second = '%s-12-31 23:59:59.999999' second = '%s-12-31 23:59:59.999999'
@ -263,7 +263,7 @@ class Field(object):
if callable(self.default): if callable(self.default):
return self.default() return self.default()
return force_unicode(self.default, strings_only=True) return force_unicode(self.default, strings_only=True)
if not self.empty_strings_allowed or (self.null and settings.DATABASE_ENGINE != 'oracle'): if not self.empty_strings_allowed or (self.null and not connection.features.interprets_empty_strings_as_nulls):
return None return None
return "" return ""
@ -614,7 +614,7 @@ class DateTimeField(DateField):
if value is not None: if value is not None:
# MySQL will throw a warning if microseconds are given, because it # MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds. # doesn't support microseconds.
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): if not connection.features.supports_usecs and hasattr(value, 'microsecond'):
value = value.replace(microsecond=0) value = value.replace(microsecond=0)
value = smart_unicode(value) value = smart_unicode(value)
return Field.get_db_prep_save(self, value) return Field.get_db_prep_save(self, value)
@ -1060,7 +1060,7 @@ class TimeField(Field):
return "TimeField" return "TimeField"
def get_db_prep_lookup(self, lookup_type, value): def get_db_prep_lookup(self, lookup_type, value):
if settings.DATABASE_ENGINE == 'oracle': if connection.features.time_field_needs_date:
# Oracle requires a date in order to parse. # Oracle requires a date in order to parse.
def prep(value): def prep(value):
if isinstance(value, datetime.time): if isinstance(value, datetime.time):
@ -1087,9 +1087,9 @@ class TimeField(Field):
if value is not None: if value is not None:
# MySQL will throw a warning if microseconds are given, because it # MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds. # doesn't support microseconds.
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): if not connection.features.supports_usecs and hasattr(value, 'microsecond'):
value = value.replace(microsecond=0) value = value.replace(microsecond=0)
if settings.DATABASE_ENGINE == 'oracle': if connection.features.time_field_needs_date:
# cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field. # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field.
if isinstance(value, datetime.time): if isinstance(value, datetime.time):
value = datetime.datetime(1900, 1, 1, value.hour, value.minute, value = datetime.datetime(1900, 1, 1, value.hour, value.minute,

View File

@ -351,7 +351,7 @@ def create_many_related_manager(superclass):
self.target_col_name = target_col_name self.target_col_name = target_col_name
self._pk_val = self.instance._get_pk_val() self._pk_val = self.instance._get_pk_val()
if self._pk_val is None: if self._pk_val is None:
raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % model) raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % instance.__class__.__name__)
def get_query_set(self): def get_query_set(self):
return superclass.get_query_set(self).filter(**(self.core_filters)) return superclass.get_query_set(self).filter(**(self.core_filters))

View File

@ -513,7 +513,9 @@ class ValuesQuerySet(QuerySet):
# names of the model fields to select. # names of the model fields to select.
def iterator(self): def iterator(self):
self.query.trim_extra_select(self.extra_names) if (not self.extra_names and
len(self.field_names) != len(self.model._meta.fields)):
self.query.trim_extra_select(self.extra_names)
names = self.query.extra_select.keys() + self.field_names names = self.query.extra_select.keys() + self.field_names
for row in self.query.results_iter(): for row in self.query.results_iter():
yield dict(zip(names, row)) yield dict(zip(names, row))

View File

@ -2,10 +2,9 @@
Query subclasses which provide extra functionality beyond simple data retrieval. Query subclasses which provide extra functionality beyond simple data retrieval.
""" """
from django.contrib.contenttypes import generic
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.db.models.sql.constants import * from django.db.models.sql.constants import *
from django.db.models.sql.datastructures import RawValue, Date from django.db.models.sql.datastructures import Date
from django.db.models.sql.query import Query from django.db.models.sql.query import Query
from django.db.models.sql.where import AND from django.db.models.sql.where import AND
@ -43,6 +42,7 @@ class DeleteQuery(Query):
More than one physical query may be executed if there are a More than one physical query may be executed if there are a
lot of values in pk_list. lot of values in pk_list.
""" """
from django.contrib.contenttypes import generic
cls = self.model cls = self.model
for related in cls._meta.get_all_related_many_to_many_objects(): for related in cls._meta.get_all_related_many_to_many_objects():
if not isinstance(related.field, generic.GenericRelation): if not isinstance(related.field, generic.GenericRelation):
@ -382,4 +382,3 @@ class CountQuery(Query):
def get_ordering(self): def get_ordering(self):
return () return ()

View File

@ -18,7 +18,7 @@ class WhereNode(tree.Node):
Used to represent the SQL where-clause. Used to represent the SQL where-clause.
The class is tied to the Query class that created it (in order to create The class is tied to the Query class that created it (in order to create
the corret SQL). the correct SQL).
The children in this tree are usually either Q-like objects or lists of The children in this tree are usually either Q-like objects or lists of
[table_alias, field_name, field_class, lookup_type, value]. However, a [table_alias, field_name, field_class, lookup_type, value]. However, a

View File

@ -108,7 +108,7 @@ class CommonMiddleware(object):
if response.has_header('ETag'): if response.has_header('ETag'):
etag = response['ETag'] etag = response['ETag']
else: else:
etag = md5.new(response.content).hexdigest() etag = '"%s"' % md5.new(response.content).hexdigest()
if response.status_code >= 200 and response.status_code < 300 and 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:
cookies = response.cookies cookies = response.cookies
response = http.HttpResponseNotModified() response = http.HttpResponseNotModified()

View File

@ -514,7 +514,6 @@ class URLField(RegexField):
return value return value
if self.verify_exists: if self.verify_exists:
import urllib2 import urllib2
from django.conf import settings
headers = { headers = {
"Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
"Accept-Language": "en-us,en;q=0.5", "Accept-Language": "en-us,en;q=0.5",

View File

@ -544,13 +544,7 @@ class ModelChoiceField(ChoiceField):
# the queryset. # the queryset.
return ModelChoiceIterator(self) return ModelChoiceIterator(self)
def _set_choices(self, value): choices = property(_get_choices, ChoiceField._set_choices)
# This method is copied from ChoiceField._set_choices(). It's necessary
# because property() doesn't allow a subclass to overwrite only
# _get_choices without implementing _set_choices.
self._choices = self.widget.choices = list(value)
choices = property(_get_choices, _set_choices)
def clean(self, value): def clean(self, value):
Field.clean(self, value) Field.clean(self, value)

View File

@ -104,7 +104,7 @@ def patch_response_headers(response, cache_timeout=None):
if cache_timeout < 0: if cache_timeout < 0:
cache_timeout = 0 # Can't have max-age negative cache_timeout = 0 # Can't have max-age negative
if not response.has_header('ETag'): if not response.has_header('ETag'):
response['ETag'] = md5.new(response.content).hexdigest() response['ETag'] = '"%s"' % md5.new(response.content).hexdigest()
if not response.has_header('Last-Modified'): if not response.has_header('Last-Modified'):
response['Last-Modified'] = http_date() response['Last-Modified'] = http_date()
if not response.has_header('Expires'): if not response.has_header('Expires'):

View File

@ -68,8 +68,7 @@ def shortcut(request, content_type_id, object_id):
def page_not_found(request, template_name='404.html'): def page_not_found(request, template_name='404.html'):
""" """
Default 404 handler, which looks for the requested URL in the redirects Default 404 handler.
table, redirects if found, and displays 404 page if not redirected.
Templates: `404.html` Templates: `404.html`
Context: Context:

View File

@ -270,17 +270,17 @@ to create a superuser at a later date, you can use a command line utility.
manage.py createsuperuser --username=joe --email=joe@example.com manage.py createsuperuser --username=joe --email=joe@example.com
You will be prompted for a password. Once entered, the user is created. If you You will be prompted for a password. After you enter one, the user will be
leave off the ``--username`` or the ``--email`` option, It will prompt you for created immediately. If you leave off the ``--username`` or the ``--email``
those values as well. options, it will prompt you for those values.
If you're using an older release of Django, the old way of creating a superuser If you're using an older release of Django, the old way of creating a superuser
on the command line still works:: on the command line still works::
python /path/to/django/contrib/auth/create_superuser.py python /path/to/django/contrib/auth/create_superuser.py
Where ``/path/to`` is the path to the Django codebase on your filesystem. The ...where ``/path/to`` is the path to the Django codebase on your filesystem. The
``manage.py`` command is prefered since it'll figure out the correct path and ``manage.py`` command is preferred because it figures out the correct path and
environment for you. environment for you.
Storing additional information about users Storing additional information about users

View File

@ -148,15 +148,17 @@ Once you've claimed a ticket, you have a responsibility to work on that ticket
in a reasonably timely fashion. If you don't have time to work on it, either in a reasonably timely fashion. If you don't have time to work on it, either
unclaim it or don't claim it in the first place! unclaim it or don't claim it in the first place!
Core Django developers go through the list of claimed tickets from time to Ticket triagers go through the list of claimed tickets from time to
time, checking whether any progress has been made. If there's no sign of time, checking whether any progress has been made. If there's no sign of
progress on a particular claimed ticket for a week or two after it's been progress on a particular claimed ticket for a week or two, a triager may ask
claimed, we will unclaim it for you so that it's no longer monopolized and you to relinquish the ticket claim so that it's no longer monopolized and
somebody else can claim it. somebody else can claim it.
If you've claimed a ticket and it's taking a long time (days or weeks) to code, If you've claimed a ticket and it's taking a long time (days or weeks) to code,
keep everybody updated by posting comments on the ticket. That way, we'll know keep everybody updated by posting comments on the ticket. If you don't provide
not to unclaim it. More communication is better than less communication! regular updates, and you don't respond to a request for a progress report,
your claim on the ticket may be revoked. As always, more communication is
better than less communication!
Which tickets should be claimed? Which tickets should be claimed?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -177,10 +179,10 @@ Patch style
English than in code. Indentation is the most common example; it's hard to English than in code. Indentation is the most common example; it's hard to
read patches when the only difference in code is that it's indented. read patches when the only difference in code is that it's indented.
* When creating patches, always run ``svn diff`` from the top-level * When creating patches, always run ``svn diff`` from the top-level
``trunk`` directory -- i.e., the one that contains ``django``, ``docs``, ``trunk`` directory -- i.e., the one that contains ``django``, ``docs``,
``tests``, ``AUTHORS``, etc. This makes it easy for other people to apply ``tests``, ``AUTHORS``, etc. This makes it easy for other people to apply
your patches. your patches.
* Attach patches to a ticket in the `ticket tracker`_, using the "attach file" * Attach patches to a ticket in the `ticket tracker`_, using the "attach file"
button. Please *don't* put the patch in the ticket description or comment button. Please *don't* put the patch in the ticket description or comment
@ -234,22 +236,28 @@ Since a picture is worth a thousand words, let's start there:
:width: 590 :width: 590
:alt: Django's ticket workflow :alt: Django's ticket workflow
We've got two roles here: We've got two official roles here:
* Core developers: people with commit access who make the decisions and * Core developers: people with commit access who make the big decisions
write the bulk of the code. and write the bulk of the code.
* Ticket triagers: community members who keep track of tickets, making * Ticket triagers: trusted community members with a proven history of
sure the tickets are always categorized correctly. working with the Django community. As a result of this history, they
have been entrusted by the core developers to make some of the smaller
decisions about tickets.
Second, note the five triage stages: Second, note the five triage stages:
1. A ticket starts as "Unreviewed", meaning that a triager has yet to 1. A ticket starts as "Unreviewed", meaning that nobody has examined
examine the ticket and move it along. the ticket.
2. "Design decision needed" means "this concept requires a design 2. "Design decision needed" means "this concept requires a design
decision," which should be discussed either in the ticket comments or on decision," which should be discussed either in the ticket comments or on
django-developers. `django-developers`_. The "Design decision needed" step will generally
only be used for feature requests. It can also be used for issues
that *might* be bugs, depending on opinion or interpretation. Obvious
bugs (such as crashes, incorrect query results, or non-compliance with a
standard) skip this step and move straight to "Accepted".
3. Once a ticket is ruled to be approved for fixing, it's moved into the 3. Once a ticket is ruled to be approved for fixing, it's moved into the
"Accepted" stage. This stage is where all the real work gets done. "Accepted" stage. This stage is where all the real work gets done.
@ -269,7 +277,7 @@ ticket has or needs in order to be "ready for checkin":
"Has patch" "Has patch"
This means the ticket has an associated patch_. These will be This means the ticket has an associated patch_. These will be
reviewed to see if the patch is "good". reviewed by the triage team to see if the patch is "good".
"Needs documentation" "Needs documentation"
This flag is used for tickets with patches that need associated This flag is used for tickets with patches that need associated
@ -292,7 +300,11 @@ A ticket can be resolved in a number of ways:
Django and the issue is fixed. Django and the issue is fixed.
"invalid" "invalid"
Used if the ticket is found to be incorrect or a user error. Used if the ticket is found to be incorrect. This means that the
issue in the ticket is actually the result of a user error, or
describes a problem with something other than Django, or isn't
a bug report or feature request at all (for example, some new users
submit support queries as tickets).
"wontfix" "wontfix"
Used when a core developer decides that this request is not Used when a core developer decides that this request is not
@ -305,7 +317,8 @@ A ticket can be resolved in a number of ways:
tickets, we keep all the discussion in one place, which helps everyone. tickets, we keep all the discussion in one place, which helps everyone.
"worksforme" "worksforme"
Used when the triage team is unable to replicate the original bug. Used when the the ticket doesn't contain enough detail to replicate
the original bug.
If you believe that the ticket was closed in error -- because you're If you believe that the ticket was closed in error -- because you're
still having the issue, or it's popped up somewhere else, or the triagers have still having the issue, or it's popped up somewhere else, or the triagers have
@ -316,6 +329,55 @@ reopen tickets that have been marked as "wontfix" by core developers.
.. _good patch: `Patch style`_ .. _good patch: `Patch style`_
.. _patch: `Submitting patches`_ .. _patch: `Submitting patches`_
Triage by the general community
-------------------------------
Although the Core Developers and Ticket Triagers make the big decisions in
the ticket triage process, there is also a lot that general community
members can do to help the triage process. In particular, you can help out by:
* Closing "Unreviewed" tickets as "invalid", "worksforme", or "duplicate".
* Promoting "Unreviewed" tickets to "Design Decision Required" if there
is a design decision that needs to be made, or "Accepted" if they are
an obvious bug.
* Correcting the "Needs Tests", "Needs documentation", or "Has Patch" flags
for tickets where they are incorrectly set.
* Checking that old tickets are still valid. If a ticket hasn't seen
any activity in a long time, it's possible that the problem has been
fixed, but the ticket hasn't been closed.
* Contact the owners of tickets that have been claimed, but have not seen
any recent activity. If the owner doesn't respond after a week or so,
remove the owner's claim on the ticket.
* Identifying trends and themes in the tickets. If there a lot of bug reports
about a particular part of Django, it possibly indicates that we need
to consider refactoring that part of the code. If a trend is emerging,
you should raise it for discussion (referencing the relevant tickets)
on `django-developers`_.
However, we do ask that as a general community member working in the
ticket database:
* Please **don't** close tickets as "wontfix". The core developers will
make the final determination of the fate of a ticket, usually after
consultation with the community.
* Please **don't** promote tickets to "Ready for checkin" unless they are
*trivial* changes - for example, spelling mistakes or
broken links in documentation.
* Please **don't** reverse a decision that has been made by a core
developer. If you disagree with a discussion that has been made,
please post a message to `django-developers`_.
* Please be conservative in your actions. If you're unsure if you should
be making a change, don't make the change - leave a comment with your
concerns on the ticket, or post a message to `django-developers`_.
Submitting and maintaining translations Submitting and maintaining translations
======================================= =======================================

View File

@ -1373,6 +1373,17 @@ SQL equivalent::
SELECT ... WHERE id IN (1, 3, 4); SELECT ... WHERE id IN (1, 3, 4);
You can also use a queryset to dynamically evaluate the list of values
instead of providing a list of literal values. The queryset must be
reduced to a list of individual values using the ``values()`` method,
and then converted into a query using the ``query`` attribute::
Entry.objects.filter(blog__in=Blog.objects.filter(name__contains='Cheddar').values('pk').query)
This queryset will be evaluated as subselect statement::
SELET ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')
startswith startswith
~~~~~~~~~~ ~~~~~~~~~~
@ -2026,6 +2037,37 @@ Each "reverse" operation described in this section has an immediate effect on
the database. Every addition, creation and deletion is immediately and the database. Every addition, creation and deletion is immediately and
automatically saved to the database. automatically saved to the database.
One-to-one relationships
------------------------
One-to-one relationships are very similar to Many-to-one relationships.
If you define a OneToOneField on your model, instances of that model will have
access to the related object via a simple attribute of the model.
For example::
class EntryDetail(models.Model):
entry = models.OneToOneField(Entry)
details = models.TextField()
ed = EntryDetail.objects.get(id=2)
ed.entry # Returns the related Entry object.
The difference comes in reverse queries. The related model in a One-to-one
relationship also has access to a ``Manager`` object; however, that ``Manager``
represents a single object, rather than a collection of objects::
e = Entry.objects.get(id=2)
e.entrydetail # returns the related EntryDetail object
If no object has been assigned to this relationship, Django will raise
a ``DoesNotExist`` exception.
Instances can be assigned to the reverse relationship in the same way as
you would assign the forward relationship::
e.entrydetail = ed
Many-to-many relationships Many-to-many relationships
-------------------------- --------------------------
@ -2053,12 +2095,6 @@ above example, if the ``ManyToManyField`` in ``Entry`` had specified
``related_name='entries'``, then each ``Author`` instance would have an ``related_name='entries'``, then each ``Author`` instance would have an
``entries`` attribute instead of ``entry_set``. ``entries`` attribute instead of ``entry_set``.
One-to-one relationships
------------------------
The semantics of one-to-one relationships will be changing soon, so we don't
recommend you use them.
How are the backward relationships possible? How are the backward relationships possible?
-------------------------------------------- --------------------------------------------

View File

@ -93,6 +93,31 @@ backend. See the `cache documentation`_ for more information.
.. _cache documentation: ../cache/ .. _cache documentation: ../cache/
createsuperuser
---------------
**New in Django development version**
Creates a superuser account (a user who has all permissions). This is
useful if you need to create an initial superuser account but did not
do so during ``syncdb``, or if you need to programmatically generate
superuser accounts for your site(s).
When run interactively, this command will prompt for a password for
the new superuser account. When run non-interactively, no password
will be set, and the superuser account will not be able to log in until
a password has been manually set for it.
The username and e-mail address for the new account can be supplied by
using the ``--username`` and ``--email`` arguments on the command
line. If either of those is not supplied, ``createsuperuser`` will prompt for
it when running interactively.
This command is only available if Django's `authentication system`_
(``django.contrib.auth``) is installed.
.. _authentication system: ../authentication/
dbshell dbshell
------- -------
@ -109,31 +134,6 @@ the program name (``psql``, ``mysql``, ``sqlite3``) will find the program in
the right place. There's no way to specify the location of the program the right place. There's no way to specify the location of the program
manually. manually.
createsuperuser
---------------
**New in Django development version**
Creates a superuser account (a user who has all permissions). This is
useful if you need to create an initial superuser account but did not
do so during ``syncdb``, or if you need to programmatically generate
superuser accounts for your site(s).
When run interactively, this command will prompt for a password for
the new superuser account; when run non-interactively, no password
will be set and the superuser account will not be able to log in until
a password has been manually set for it.
The username and e-mail address for the new account can be supplied by
using the ``--username`` and ``--email`` arguments on the command
line; if not supplied, ``createsuperuser`` will prompt for them when
running interactively.
This command is only available if Django's `authentication system`_
(``django.contrib.auth``) is installed.
.. _authentication system: ../authentication/
diffsettings diffsettings
------------ ------------
@ -164,6 +164,22 @@ dumped.
.. _custom manager: ../model-api/#custom-managers .. _custom manager: ../model-api/#custom-managers
--exclude
~~~~~~~~~
**New in Django development version**
Exclude a specific application from the applications whose contents is
output. For example, to specifically exclude the `auth` application from
the output, you would call::
django-admin.py dumpdata --exclude=auth
If you want to exclude multiple applications, use multiple ``--exclude``
directives::
django-admin.py dumpdata --exclude=auth --exclude=contenttype
--format --format
~~~~~~~~ ~~~~~~~~
@ -338,9 +354,9 @@ The ``dumpdata`` command can be used to generate input for ``loaddata``.
Use ``--verbosity`` to specify the amount of notification and debug information Use ``--verbosity`` to specify the amount of notification and debug information
that ``django-admin.py`` should print to the console. that ``django-admin.py`` should print to the console.
* ``0`` means no input. * ``0`` means no output.
* ``1`` means normal input (default). * ``1`` means normal output (default).
* ``2`` means verbose input. * ``2`` means verbose output.
Example usage:: Example usage::
@ -422,6 +438,10 @@ means any Python code changes you make while the server is running will *not*
take effect if the particular Python modules have already been loaded into take effect if the particular Python modules have already been loaded into
memory. memory.
Example usage::
django-admin.py runserver --noreload
Examples of using different ports and addresses Examples of using different ports and addresses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -451,14 +471,6 @@ documentation.
.. _serving static files: ../static_files/ .. _serving static files: ../static_files/
Turning off auto-reload
~~~~~~~~~~~~~~~~~~~~~~~
To disable auto-reloading of code while the development server is running, use the
``--noreload`` option, like so::
django-admin.py runserver --noreload
shell shell
----- -----
@ -581,9 +593,9 @@ data files.
Use ``--verbosity`` to specify the amount of notification and debug information Use ``--verbosity`` to specify the amount of notification and debug information
that ``django-admin.py`` should print to the console. that ``django-admin.py`` should print to the console.
* ``0`` means no input. * ``0`` means no output.
* ``1`` means normal input (default). * ``1`` means normal output (default).
* ``2`` means verbose input. * ``2`` means verbose output.
Example usage:: Example usage::
@ -617,9 +629,9 @@ is being executed as an unattended, automated script.
Use ``--verbosity`` to specify the amount of notification and debug information Use ``--verbosity`` to specify the amount of notification and debug information
that ``django-admin.py`` should print to the console. that ``django-admin.py`` should print to the console.
* ``0`` means no input. * ``0`` means no output.
* ``1`` means normal input (default). * ``1`` means normal output (default).
* ``2`` means verbose input. * ``2`` means verbose output.
Example usage:: Example usage::
@ -693,9 +705,9 @@ To run on 1.2.3.4:7000 with a ``test`` fixture::
Use ``--verbosity`` to specify the amount of notification and debug information Use ``--verbosity`` to specify the amount of notification and debug information
that ``django-admin.py`` should print to the console. that ``django-admin.py`` should print to the console.
* ``0`` means no input. * ``0`` means no output.
* ``1`` means normal input (default). * ``1`` means normal output (default).
* ``2`` means verbose input. * ``2`` means verbose output.
Example usage:: Example usage::

View File

@ -646,7 +646,7 @@ You can also use the Python API. See `creating users`_ for full info.
.. _creating users: ../authentication/#creating-users .. _creating users: ../authentication/#creating-users
Getting Help Getting help
============ ============
How do I do X? Why doesn't Y work? Where can I go to get help? How do I do X? Why doesn't Y work? Where can I go to get help?
@ -656,8 +656,8 @@ If this FAQ doesn't contain an answer to your question, you might want to
try the `django-users mailing list`_. Feel free to ask any question related try the `django-users mailing list`_. Feel free to ask any question related
to installing, using, or debugging Django. to installing, using, or debugging Django.
If you prefer IRC, the `#django IRC channel`_ on freenode is an active If you prefer IRC, the `#django IRC channel`_ on the Freenode IRC network is an
community of helpful individuals who may be able to solve your problem. active community of helpful individuals who may be able to solve your problem.
.. _`django-users mailing list`: http://groups.google.com/group/django-users .. _`django-users mailing list`: http://groups.google.com/group/django-users
.. _`#django IRC channel`: irc://irc.freenode.net/django .. _`#django IRC channel`: irc://irc.freenode.net/django
@ -666,7 +666,7 @@ Why hasn't my message appeared on django-users?
----------------------------------------------- -----------------------------------------------
django-users_ has a lot of subscribers. This is good for the community, as django-users_ has a lot of subscribers. This is good for the community, as
there are lot of people that can contribute answers to questions. it means many people are available to contribute answers to questions.
Unfortunately, it also means that django-users_ is an attractive target for Unfortunately, it also means that django-users_ is an attractive target for
spammers. spammers.
@ -678,23 +678,24 @@ inconvenience that this policy may cause.
.. _django-users: http://groups.google.com/group/django-users .. _django-users: http://groups.google.com/group/django-users
Nobody on django-users answered my question? What should I do? Nobody on django-users answered my question! What should I do?
-------------------------------------------------------------- --------------------------------------------------------------
Wait. Ask again later. Try making your question more specific, or provide Try making your question more specific, or provide a better example of your
a better example of your problem. problem.
Remember, the readers of django-users_ are all volunteers. If nobody has As with most open-source mailing lists, the folks on django-users_ are
answered your question, it may be because nobody knows the answer, it may volunteers. If nobody has answered your question, it may be because nobody
be because nobody can understand the question, or it may be that everybody knows the answer, it may be because nobody can understand the question, or it
that can help is extremely busy. may be that everybody that can help is busy. One thing you might try is to ask
the question on IRC -- visit the `#django IRC channel`_ on the Freenode IRC
network.
Resist any temptation to mail the `django-developers mailing list`_ in an You might notice we have a second mailing list, called django-developers_ --
attempt to get an answer to your question. django-developers_ is for discussing but please don't e-mail support questions to this mailing list. This list is
the development of Django itself. Attempts to use django-developers_ as for discussion of the development of Django itself. Asking a tech support
a second-tier support mechanism will not be met an enthusiastic response. question there is considered quite impolite.
.. _`django-developers mailing list`: http://groups.google.com/group/django-developers
.. _django-developers: http://groups.google.com/group/django-developers .. _django-developers: http://groups.google.com/group/django-developers
I think I've found a bug! What should I do? I think I've found a bug! What should I do?
@ -708,10 +709,9 @@ Detailed instructions on how to handle a potential bug can be found in our
I think I've found a security problem! What should I do? I think I've found a security problem! What should I do?
-------------------------------------------------------- --------------------------------------------------------
If you think you have found a security problem with Django, please send If you think you've found a security problem with Django, please send a message
a message to security@djangoproject.com. This is a private list only to security@djangoproject.com. This is a private list only open to long-time,
open to long-time, highly trusted Django developers, and its archives highly trusted Django developers, and its archives are not publicly readable.
are not publicly readable.
Due to the sensitive nature of security issues, we ask that if you think you Due to the sensitive nature of security issues, we ask that if you think you
have found a security problem, *please* don't send a message to one of the have found a security problem, *please* don't send a message to one of the
@ -742,10 +742,10 @@ ignored" and "a ticket has not been attended to yet." Django's ticket system
contains hundreds of open tickets, of various degrees of impact on end-user contains hundreds of open tickets, of various degrees of impact on end-user
functionality, and Django's developers have to review and prioritize. functionality, and Django's developers have to review and prioritize.
On top of that - the team working on Django are all volunteers. As a result, On top of that: the people who work on Django are all volunteers. As a result,
the amount of time that we have to work on Django is limited, and will vary the amount of time that we have to work on the framework is limited and will
from week to week depending on how much spare time we have. If we are busy, we vary from week to week depending on our spare time. If we're busy, we may not
may not be able to spend as much time on Django as we might want. be able to spend as much time on Django as we might want.
Besides, if your feature request stands no chance of inclusion in Django, we Besides, if your feature request stands no chance of inclusion in Django, we
won't ignore it -- we'll just close the ticket. So if your ticket is still won't ignore it -- we'll just close the ticket. So if your ticket is still

View File

@ -669,7 +669,7 @@ unless you want to override the default primary-key behavior.
If ``True``, this field must be unique throughout the table. If ``True``, this field must be unique throughout the table.
This is enforced at the database level and at the Django admin-form level. If This is enforced at the database level and at the Django admin-form level. If
you try to add save a model with a duplicate value in a ``unique`` field, a you try to save a model with a duplicate value in a ``unique`` field, a
``django.db.IntegrityError`` will be raised by the model's ``save()`` method. ``django.db.IntegrityError`` will be raised by the model's ``save()`` method.
``unique_for_date`` ``unique_for_date``

View File

@ -112,7 +112,7 @@ It also has these methods:
Sets a test cookie to determine whether the user's browser supports Sets a test cookie to determine whether the user's browser supports
cookies. Due to the way cookies work, you won't be able to test this cookies. Due to the way cookies work, you won't be able to test this
until the user's next page request. See "Setting test cookies" below for until the user's next page request. See `Setting test cookies`_ below for
more information. more information.
* ``test_cookie_worked()`` * ``test_cookie_worked()``
@ -120,7 +120,7 @@ It also has these methods:
Returns either ``True`` or ``False``, depending on whether the user's Returns either ``True`` or ``False``, depending on whether the user's
browser accepted the test cookie. Due to the way cookies work, you'll browser accepted the test cookie. Due to the way cookies work, you'll
have to call ``set_test_cookie()`` on a previous, separate page request. have to call ``set_test_cookie()`` on a previous, separate page request.
See "Setting test cookies" below for more information. See `Setting test cookies`_ below for more information.
* ``delete_test_cookie()`` * ``delete_test_cookie()``
@ -139,10 +139,10 @@ It also has these methods:
in 5 minutes. in 5 minutes.
* If ``value`` is a ``datetime`` or ``timedelta`` object, the * If ``value`` is a ``datetime`` or ``timedelta`` object, the
session will expire at that specific time. session will expire at that specific date/time.
* If ``value`` is ``0`` then the user's session cookie will expire * If ``value`` is ``0``, the user's session cookie will expire
when their browser is closed. when the user's Web browser is closed.
* If ``value`` is ``None``, the session reverts to using the global * If ``value`` is ``None``, the session reverts to using the global
session expiry policy. session expiry policy.
@ -168,7 +168,7 @@ It also has these methods:
**New in Django development version** **New in Django development version**
Returns either ``True`` or ``False``, depending on whether the user's Returns either ``True`` or ``False``, depending on whether the user's
session cookie will expire when their browser is closed. session cookie will expire when the user's Web browser is closed.
You can edit ``request.session`` at any point in your view. You can edit it You can edit ``request.session`` at any point in your view. You can edit it
multiple times. multiple times.

View File

@ -394,6 +394,8 @@ site with ``DEBUG`` turned on.
DEBUG_PROPAGATE_EXCEPTIONS DEBUG_PROPAGATE_EXCEPTIONS
-------------------------- --------------------------
**New in Django development version**
Default: ``False`` Default: ``False``
If set to True, Django's normal exception handling of view functions If set to True, Django's normal exception handling of view functions

View File

@ -819,7 +819,7 @@ The 'ifchanged' block tag is used within a loop. It has two possible uses.
2. If given a variable, check whether that variable has changed. For 2. If given a variable, check whether that variable has changed. For
example, the following shows the date every time it changes, but example, the following shows the date every time it changes, but
only shows the hour if both the hour and the date has changed:: only shows the hour if both the hour and the date have changed::
{% for date in days %} {% for date in days %}
{% ifchanged date.date %} {{ date.date }} {% endifchanged %} {% ifchanged date.date %} {{ date.date }} {% endifchanged %}

View File

@ -1059,8 +1059,8 @@ Passing template variables to the tag
Although you can pass any number of arguments to a template tag using Although you can pass any number of arguments to a template tag using
``token.split_contents()``, the arguments are all unpacked as ``token.split_contents()``, the arguments are all unpacked as
string literals. A little more work is required in order to dynamic content (a string literals. A little more work is required in order to pass dynamic
template variable) to a template tag as an argument. content (a template variable) to a template tag as an argument.
While the previous examples have formatted the current time into a string and While the previous examples have formatted the current time into a string and
returned the string, suppose you wanted to pass in a ``DateTimeField`` from an returned the string, suppose you wanted to pass in a ``DateTimeField`` from an
@ -1169,10 +1169,11 @@ Our earlier ``current_time`` function could thus be written like this::
In Python 2.4, the decorator syntax also works:: In Python 2.4, the decorator syntax also works::
@register.simple_tag @register.simple_tag
def current_time(token): def current_time(format_string):
... ...
A couple of things to note about the ``simple_tag`` helper function: A couple of things to note about the ``simple_tag`` helper function:
* Checking for the required number of arguments, etc, has already been * Checking for the required number of arguments, etc, has already been
done by the time our function is called, so we don't need to do that. done by the time our function is called, so we don't need to do that.
* The quotes around the argument (if any) have already been stripped away, * The quotes around the argument (if any) have already been stripped away,

View File

@ -22,8 +22,8 @@ installed.
.. admonition:: Where to get help: .. admonition:: Where to get help:
If you're having trouble going through this tutorial, please post a message If you're having trouble going through this tutorial, please post a message
to `django-users`_ or drop by `#django`_ on ``irc.freenode.net`` and we'll to `django-users`_ or drop by `#django`_ on ``irc.freenode.net`` to chat
try to help. with other Django users who might be able to help.
.. _django-users: http://groups.google.com/group/django-users .. _django-users: http://groups.google.com/group/django-users
.. _#django: irc://irc.freenode.net/django .. _#django: irc://irc.freenode.net/django

View File

@ -39,6 +39,14 @@ __test__ = {'API_TESTS':"""
# Create an Article. # Create an Article.
>>> a1 = Article(id=None, headline='Django lets you build Web apps easily') >>> a1 = Article(id=None, headline='Django lets you build Web apps easily')
# You can't associate it with a Publication until it's been saved.
>>> a1.publications.add(p1)
Traceback (most recent call last):
...
ValueError: 'Article' instance needs to have a primary key value before a many-to-many relationship can be used.
# Save it!
>>> a1.save() >>> a1.save()
# Associate the Article with a Publication. # Associate the Article with a Publication.

View File

@ -175,6 +175,12 @@ False
>>> Article.objects.filter(reporter__in=[r,r2]).distinct() >>> Article.objects.filter(reporter__in=[r,r2]).distinct()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
# You can also use a queryset instead of a literal list of instances.
# The queryset must be reduced to a list of values using values(),
# then converted into a query
>>> Article.objects.filter(reporter__in=Reporter.objects.filter(first_name='John').values('pk').query).distinct()
[<Article: John's second story>, <Article: This is a test>]
# You need two underscores between "reporter" and "id" -- not one. # You need two underscores between "reporter" and "id" -- not one.
>>> Article.objects.filter(reporter_id__exact=1) >>> Article.objects.filter(reporter_id__exact=1)
Traceback (most recent call last): Traceback (most recent call last):

View File

@ -772,7 +772,7 @@ True
False False
>>> r[1].name, r[1].value, r[1].choice_value, r[1].choice_label >>> r[1].name, r[1].value, r[1].choice_value, r[1].choice_label
('beatle', u'J', u'P', u'Paul') ('beatle', u'J', u'P', u'Paul')
>>> r[10] >>> r[10] # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last): Traceback (most recent call last):
... ...
IndexError: list index out of range IndexError: list index out of range

View File

@ -507,6 +507,12 @@ True
>>> [sorted(d.items()) for d in dicts] >>> [sorted(d.items()) for d in dicts]
[[('id', 1), ('rank', 2)], [('id', 2), ('rank', 1)], [('id', 3), ('rank', 3)]] [[('id', 1), ('rank', 2)], [('id', 2), ('rank', 1)], [('id', 3), ('rank', 3)]]
Bug #7256
# An empty values() call includes all aliases, including those from an extra()
>>> dicts = qs.values().order_by('id')
>>> [sorted(d.items()) for d in dicts]
[[('author_id', 2), ('good', 0), ('id', 1), ('rank', 2)], [('author_id', 3), ('good', 0), ('id', 2), ('rank', 1)], [('author_id', 1), ('good', 1), ('id', 3), ('rank', 3)]]
Bugs #2874, #3002 Bugs #2874, #3002
>>> qs = Item.objects.select_related().order_by('note__note', 'name') >>> qs = Item.objects.select_related().order_by('note__note', 'name')
>>> list(qs) >>> list(qs)

View File

@ -17,6 +17,7 @@ test_data = (
('^hardcoded/$', 'hardcoded/', [], {}), ('^hardcoded/$', 'hardcoded/', [], {}),
('^hardcoded/$', 'hardcoded/', ['any arg'], {}), ('^hardcoded/$', 'hardcoded/', ['any arg'], {}),
('^hardcoded/$', 'hardcoded/', [], {'kwarg': 'foo'}), ('^hardcoded/$', 'hardcoded/', [], {'kwarg': 'foo'}),
('^hardcoded/doc\\.pdf$', 'hardcoded/doc.pdf', [], {}),
('^people/(?P<state>\w\w)/(?P<name>\w+)/$', 'people/il/adrian/', [], {'state': 'il', 'name': 'adrian'}), ('^people/(?P<state>\w\w)/(?P<name>\w+)/$', 'people/il/adrian/', [], {'state': 'il', 'name': 'adrian'}),
('^people/(?P<state>\w\w)/(?P<name>\d)/$', NoReverseMatch, [], {'state': 'il', 'name': 'adrian'}), ('^people/(?P<state>\w\w)/(?P<name>\d)/$', NoReverseMatch, [], {'state': 'il', 'name': 'adrian'}),
('^people/(?P<state>\w\w)/(?P<name>\w+)/$', NoReverseMatch, [], {'state': 'il'}), ('^people/(?P<state>\w\w)/(?P<name>\w+)/$', NoReverseMatch, [], {'state': 'il'}),