mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
[multi-db] Merge trunk to [3578]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@3581 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
238c6ecd5b
commit
bec235deef
3
AUTHORS
3
AUTHORS
@ -60,6 +60,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Amit Chakradeo <http://amit.chakradeo.net/>
|
Amit Chakradeo <http://amit.chakradeo.net/>
|
||||||
ChaosKCW
|
ChaosKCW
|
||||||
Ian Clelland <clelland@gmail.com>
|
Ian Clelland <clelland@gmail.com>
|
||||||
|
crankycoder@gmail.com
|
||||||
Matt Croydon <http://www.postneo.com/>
|
Matt Croydon <http://www.postneo.com/>
|
||||||
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
|
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
|
||||||
Jason Davies (Esaj) <http://www.jasondavies.com/>
|
Jason Davies (Esaj) <http://www.jasondavies.com/>
|
||||||
@ -125,12 +126,14 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
|
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
|
||||||
David Schein
|
David Schein
|
||||||
sopel
|
sopel
|
||||||
|
Thomas Steinacher <tom@eggdrop.ch>
|
||||||
Radek Švarz <http://www.svarz.cz/translate/>
|
Radek Švarz <http://www.svarz.cz/translate/>
|
||||||
Swaroop C H <http://www.swaroopch.info>
|
Swaroop C H <http://www.swaroopch.info>
|
||||||
Aaron Swartz <http://www.aaronsw.com/>
|
Aaron Swartz <http://www.aaronsw.com/>
|
||||||
Tom Tobin
|
Tom Tobin
|
||||||
Tom Insam
|
Tom Insam
|
||||||
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
||||||
|
Karen Tracey <graybark@bellsouth.net>
|
||||||
Amit Upadhyay
|
Amit Upadhyay
|
||||||
Geert Vanderkelen
|
Geert Vanderkelen
|
||||||
Milton Waddams
|
Milton Waddams
|
||||||
|
@ -14,7 +14,7 @@ def compile_messages():
|
|||||||
print "this script should be run from the django svn tree or your project or app tree"
|
print "this script should be run from the django svn tree or your project or app tree"
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
for (dirpath, dirnames, filenames) in os.walk(basedir):
|
for dirpath, dirnames, filenames in os.walk(basedir):
|
||||||
for f in filenames:
|
for f in filenames:
|
||||||
if f.endswith('.po'):
|
if f.endswith('.po'):
|
||||||
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
|
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
|
||||||
|
@ -255,6 +255,7 @@ MIDDLEWARE_CLASSES = (
|
|||||||
SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want.
|
SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want.
|
||||||
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
|
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
|
||||||
SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie.
|
SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie.
|
||||||
|
SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only).
|
||||||
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 sessions expire when a user closes his browser.
|
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser.
|
||||||
|
|
||||||
|
@ -60,8 +60,9 @@ MIDDLEWARE_CLASSES = (
|
|||||||
ROOT_URLCONF = '{{ project_name }}.urls'
|
ROOT_URLCONF = '{{ project_name }}.urls'
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
TEMPLATE_DIRS = (
|
||||||
# Put strings here, like "/home/html/django_templates".
|
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
||||||
# Always use forward slashes, even on Windows.
|
# Always use forward slashes, even on Windows.
|
||||||
|
# Don't forget to use absolute paths, not relative paths.
|
||||||
)
|
)
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = (
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
|
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}{% endif %}
|
{% endif %}{% endif %}
|
||||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post">{% block form_top %}{% endblock %}
|
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}
|
||||||
<div>
|
<div>
|
||||||
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
|
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
|
||||||
{% if opts.admin.save_on_top %}{% submit_row %}{% endif %}
|
{% if opts.admin.save_on_top %}{% submit_row %}{% endif %}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th>
|
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</tr></thead>
|
||||||
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
||||||
{% if change %}{% if original_row_needed %}
|
{% if change %}{% if original_row_needed %}
|
||||||
{% if fcw.obj.original %}
|
{% if fcw.obj.original %}
|
||||||
|
@ -21,7 +21,6 @@ urlpatterns = patterns('',
|
|||||||
('^doc/tags/$', 'django.contrib.admin.views.doc.template_tag_index'),
|
('^doc/tags/$', 'django.contrib.admin.views.doc.template_tag_index'),
|
||||||
('^doc/filters/$', 'django.contrib.admin.views.doc.template_filter_index'),
|
('^doc/filters/$', 'django.contrib.admin.views.doc.template_filter_index'),
|
||||||
('^doc/views/$', 'django.contrib.admin.views.doc.view_index'),
|
('^doc/views/$', 'django.contrib.admin.views.doc.view_index'),
|
||||||
('^doc/views/jump/$', 'django.contrib.admin.views.doc.jump_to_view'),
|
|
||||||
('^doc/views/(?P<view>[^/]+)/$', 'django.contrib.admin.views.doc.view_detail'),
|
('^doc/views/(?P<view>[^/]+)/$', 'django.contrib.admin.views.doc.view_detail'),
|
||||||
('^doc/models/$', 'django.contrib.admin.views.doc.model_index'),
|
('^doc/models/$', 'django.contrib.admin.views.doc.model_index'),
|
||||||
('^doc/models/(?P<app_label>[^\.]+)\.(?P<model_name>[^/]+)/$', 'django.contrib.admin.views.doc.model_detail'),
|
('^doc/models/(?P<app_label>[^\.]+)\.(?P<model_name>[^/]+)/$', 'django.contrib.admin.views.doc.model_detail'),
|
||||||
|
@ -43,11 +43,11 @@ def template_tag_index(request):
|
|||||||
for tag_name, tag_func in library.tags.items():
|
for tag_name, tag_func in library.tags.items():
|
||||||
title, body, metadata = utils.parse_docstring(tag_func.__doc__)
|
title, body, metadata = utils.parse_docstring(tag_func.__doc__)
|
||||||
if title:
|
if title:
|
||||||
title = utils.parse_rst(title, 'tag', 'tag:' + tag_name)
|
title = utils.parse_rst(title, 'tag', _('tag:') + tag_name)
|
||||||
if body:
|
if body:
|
||||||
body = utils.parse_rst(body, 'tag', 'tag:' + tag_name)
|
body = utils.parse_rst(body, 'tag', _('tag:') + tag_name)
|
||||||
for key in metadata:
|
for key in metadata:
|
||||||
metadata[key] = utils.parse_rst(metadata[key], 'tag', 'tag:' + tag_name)
|
metadata[key] = utils.parse_rst(metadata[key], 'tag', _('tag:') + tag_name)
|
||||||
if library in template.builtins:
|
if library in template.builtins:
|
||||||
tag_library = None
|
tag_library = None
|
||||||
else:
|
else:
|
||||||
@ -74,11 +74,11 @@ def template_filter_index(request):
|
|||||||
for filter_name, filter_func in library.filters.items():
|
for filter_name, filter_func in library.filters.items():
|
||||||
title, body, metadata = utils.parse_docstring(filter_func.__doc__)
|
title, body, metadata = utils.parse_docstring(filter_func.__doc__)
|
||||||
if title:
|
if title:
|
||||||
title = utils.parse_rst(title, 'filter', 'filter:' + filter_name)
|
title = utils.parse_rst(title, 'filter', _('filter:') + filter_name)
|
||||||
if body:
|
if body:
|
||||||
body = utils.parse_rst(body, 'filter', 'filter:' + filter_name)
|
body = utils.parse_rst(body, 'filter', _('filter:') + filter_name)
|
||||||
for key in metadata:
|
for key in metadata:
|
||||||
metadata[key] = utils.parse_rst(metadata[key], 'filter', 'filter:' + filter_name)
|
metadata[key] = utils.parse_rst(metadata[key], 'filter', _('filter:') + filter_name)
|
||||||
if library in template.builtins:
|
if library in template.builtins:
|
||||||
tag_library = None
|
tag_library = None
|
||||||
else:
|
else:
|
||||||
@ -132,11 +132,11 @@ def view_detail(request, view):
|
|||||||
raise Http404
|
raise Http404
|
||||||
title, body, metadata = utils.parse_docstring(view_func.__doc__)
|
title, body, metadata = utils.parse_docstring(view_func.__doc__)
|
||||||
if title:
|
if title:
|
||||||
title = utils.parse_rst(title, 'view', 'view:' + view)
|
title = utils.parse_rst(title, 'view', _('view:') + view)
|
||||||
if body:
|
if body:
|
||||||
body = utils.parse_rst(body, 'view', 'view:' + view)
|
body = utils.parse_rst(body, 'view', _('view:') + view)
|
||||||
for key in metadata:
|
for key in metadata:
|
||||||
metadata[key] = utils.parse_rst(metadata[key], 'model', 'view:' + view)
|
metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view)
|
||||||
return render_to_response('admin_doc/view_detail.html', {
|
return render_to_response('admin_doc/view_detail.html', {
|
||||||
'name': view,
|
'name': view,
|
||||||
'summary': title,
|
'summary': title,
|
||||||
@ -161,14 +161,14 @@ def model_detail(request, app_label, model_name):
|
|||||||
try:
|
try:
|
||||||
app_mod = models.get_app(app_label)
|
app_mod = models.get_app(app_label)
|
||||||
except ImproperlyConfigured:
|
except ImproperlyConfigured:
|
||||||
raise Http404, "App %r not found" % app_label
|
raise Http404, _("App %r not found") % app_label
|
||||||
model = None
|
model = None
|
||||||
for m in models.get_models(app_mod):
|
for m in models.get_models(app_mod):
|
||||||
if m._meta.object_name.lower() == model_name:
|
if m._meta.object_name.lower() == model_name:
|
||||||
model = m
|
model = m
|
||||||
break
|
break
|
||||||
if model is None:
|
if model is None:
|
||||||
raise Http404, "Model %r not found in app %r" % (model_name, app_label)
|
raise Http404, _("Model %r not found in app %r") % (model_name, app_label)
|
||||||
|
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ def model_detail(request, app_label, model_name):
|
|||||||
if isinstance(field, models.ForeignKey):
|
if isinstance(field, models.ForeignKey):
|
||||||
data_type = related_object_name = field.rel.to.__name__
|
data_type = related_object_name = field.rel.to.__name__
|
||||||
app_label = field.rel.to._meta.app_label
|
app_label = field.rel.to._meta.app_label
|
||||||
verbose = utils.parse_rst(("the related `%s.%s` object" % (app_label, data_type)), 'model', 'model:' + data_type)
|
verbose = utils.parse_rst((_("the related `%s.%s` object") % (app_label, data_type)), 'model', _('model:') + data_type)
|
||||||
else:
|
else:
|
||||||
data_type = get_readable_field_data_type(field)
|
data_type = get_readable_field_data_type(field)
|
||||||
verbose = field.verbose_name
|
verbose = field.verbose_name
|
||||||
@ -202,7 +202,7 @@ def model_detail(request, app_label, model_name):
|
|||||||
continue
|
continue
|
||||||
verbose = func.__doc__
|
verbose = func.__doc__
|
||||||
if verbose:
|
if verbose:
|
||||||
verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', 'model:' + opts.module_name)
|
verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.module_name)
|
||||||
fields.append({
|
fields.append({
|
||||||
'name': func_name,
|
'name': func_name,
|
||||||
'data_type': get_return_data_type(func_name),
|
'data_type': get_return_data_type(func_name),
|
||||||
@ -211,17 +211,17 @@ def model_detail(request, app_label, model_name):
|
|||||||
|
|
||||||
# Gather related objects
|
# Gather related objects
|
||||||
for rel in opts.get_all_related_objects():
|
for rel in opts.get_all_related_objects():
|
||||||
verbose = "related `%s.%s` objects" % (rel.opts.app_label, rel.opts.object_name)
|
verbose = _("related `%s.%s` objects") % (rel.opts.app_label, rel.opts.object_name)
|
||||||
accessor = rel.get_accessor_name()
|
accessor = rel.get_accessor_name()
|
||||||
fields.append({
|
fields.append({
|
||||||
'name' : "%s.all" % accessor,
|
'name' : "%s.all" % accessor,
|
||||||
'data_type' : 'List',
|
'data_type' : 'List',
|
||||||
'verbose' : utils.parse_rst("all " + verbose , 'model', 'model:' + opts.module_name),
|
'verbose' : utils.parse_rst(_("all %s") % verbose , 'model', _('model:') + opts.module_name),
|
||||||
})
|
})
|
||||||
fields.append({
|
fields.append({
|
||||||
'name' : "%s.count" % accessor,
|
'name' : "%s.count" % accessor,
|
||||||
'data_type' : 'Integer',
|
'data_type' : 'Integer',
|
||||||
'verbose' : utils.parse_rst("number of " + verbose , 'model', 'model:' + opts.module_name),
|
'verbose' : utils.parse_rst(_("number of %s") % verbose , 'model', _('model:') + opts.module_name),
|
||||||
})
|
})
|
||||||
|
|
||||||
return render_to_response('admin_doc/model_detail.html', {
|
return render_to_response('admin_doc/model_detail.html', {
|
||||||
@ -336,7 +336,7 @@ def extract_views_from_urlpatterns(urlpatterns, base=''):
|
|||||||
elif hasattr(p, '_get_url_patterns'):
|
elif hasattr(p, '_get_url_patterns'):
|
||||||
views.extend(extract_views_from_urlpatterns(p.url_patterns, base + p.regex.pattern))
|
views.extend(extract_views_from_urlpatterns(p.url_patterns, base + p.regex.pattern))
|
||||||
else:
|
else:
|
||||||
raise TypeError, "%s does not appear to be a urlpattern object" % p
|
raise TypeError, _("%s does not appear to be a urlpattern object") % p
|
||||||
return views
|
return views
|
||||||
|
|
||||||
named_group_matcher = re.compile(r'\(\?P(<\w+>).+?\)')
|
named_group_matcher = re.compile(r'\(\?P(<\w+>).+?\)')
|
||||||
|
@ -263,7 +263,7 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
|
|||||||
post_url_continue += "?_popup=1"
|
post_url_continue += "?_popup=1"
|
||||||
return HttpResponseRedirect(post_url_continue % pk_value)
|
return HttpResponseRedirect(post_url_continue % pk_value)
|
||||||
if request.POST.has_key("_popup"):
|
if request.POST.has_key("_popup"):
|
||||||
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
|
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %r, "%s");</script>' % \
|
||||||
(pk_value, str(new_object).replace('"', '\\"')))
|
(pk_value, str(new_object).replace('"', '\\"')))
|
||||||
elif request.POST.has_key("_addanother"):
|
elif request.POST.has_key("_addanother"):
|
||||||
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
|
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
|
||||||
|
@ -2,7 +2,7 @@ This is an optional add-on app, flatpages.
|
|||||||
|
|
||||||
For full documentation, see either of these:
|
For full documentation, see either of these:
|
||||||
|
|
||||||
* The file django/docs/flatpages.txt in the Django distribution
|
* The file docs/flatpages.txt in the Django distribution
|
||||||
* http://www.djangoproject.com/documentation/flatpages/ on the Web
|
* http://www.djangoproject.com/documentation/flatpages/ on the Web
|
||||||
|
|
||||||
Both have identical content.
|
Both have identical content.
|
@ -88,5 +88,6 @@ class SessionMiddleware(object):
|
|||||||
new_session = Session.objects.save(session_key, request.session._session,
|
new_session = Session.objects.save(session_key, request.session._session,
|
||||||
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
|
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
|
||||||
response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,
|
response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,
|
||||||
max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN)
|
max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
|
||||||
|
secure=settings.SESSION_COOKIE_SECURE or None)
|
||||||
return response
|
return response
|
||||||
|
@ -110,9 +110,14 @@ def get_sql_create(app):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Get installed models, so we generate REFERENCES right
|
# Get installed models, so we generate REFERENCES right
|
||||||
|
# We trim models from the current app so that the sqlreset command does
|
||||||
|
# not generate invalid SQL (leaving models out of known_models is
|
||||||
|
# harmless, so we can be conservative).
|
||||||
manager = model._default_manager
|
manager = model._default_manager
|
||||||
tables = manager.get_table_list()
|
tables = manager.get_table_list()
|
||||||
installed_models = manager.get_installed_models(tables)
|
installed_models = [ model for model in
|
||||||
|
manager.get_installed_models(tables)
|
||||||
|
if model not in app_models ]
|
||||||
models_output = set(installed_models)
|
models_output = set(installed_models)
|
||||||
builder = creation.builder
|
builder = creation.builder
|
||||||
builder.models_already_seen.update(models_output)
|
builder.models_already_seen.update(models_output)
|
||||||
@ -136,11 +141,14 @@ def get_sql_create(app):
|
|||||||
# but don't exist physically
|
# but don't exist physically
|
||||||
not_installed_models = set(pending_references.keys())
|
not_installed_models = set(pending_references.keys())
|
||||||
if not_installed_models:
|
if not_installed_models:
|
||||||
final_output.append('-- The following references should be added but depend on non-existant tables:')
|
alter_sql = []
|
||||||
for model in not_installed_models:
|
for model in not_installed_models:
|
||||||
final_output.extend(['-- ' + sql
|
alter_sql.extend(['-- ' + sql
|
||||||
for sql in pending_references.pop(model)])
|
for sql in pending_references.pop(model)])
|
||||||
|
if alter_sql:
|
||||||
|
final_output.append('-- The following references should be added '
|
||||||
|
'but depend on non-existent tables:')
|
||||||
|
final_output.extend(alter_sql)
|
||||||
# convert BoundStatements into strings
|
# convert BoundStatements into strings
|
||||||
final_output = map(str, final_output)
|
final_output = map(str, final_output)
|
||||||
return final_output
|
return final_output
|
||||||
@ -563,9 +571,7 @@ def inspectdb():
|
|||||||
|
|
||||||
introspection_module = get_introspection_module()
|
introspection_module = get_introspection_module()
|
||||||
|
|
||||||
def table2model(table_name):
|
table2model = lambda table_name: table_name.title().replace('_', '')
|
||||||
object_name = table_name.title().replace('_', '')
|
|
||||||
return object_name.endswith('s') and object_name[:-1] or object_name
|
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
yield "# This is an auto-generated Django model module."
|
yield "# This is an auto-generated Django model module."
|
||||||
@ -594,6 +600,10 @@ def inspectdb():
|
|||||||
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
|
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
|
||||||
extra_params = {} # Holds Field parameters such as 'db_column'.
|
extra_params = {} # Holds Field parameters such as 'db_column'.
|
||||||
|
|
||||||
|
if ' ' in att_name:
|
||||||
|
extra_params['db_column'] = att_name
|
||||||
|
att_name = att_name.replace(' ', '')
|
||||||
|
comment_notes.append('Field renamed to remove spaces.')
|
||||||
if keyword.iskeyword(att_name):
|
if keyword.iskeyword(att_name):
|
||||||
extra_params['db_column'] = att_name
|
extra_params['db_column'] = att_name
|
||||||
att_name += '_field'
|
att_name += '_field'
|
||||||
@ -1010,7 +1020,14 @@ def dbshell():
|
|||||||
dbshell.args = ""
|
dbshell.args = ""
|
||||||
|
|
||||||
def runfcgi(args):
|
def runfcgi(args):
|
||||||
"""Run this project as a FastCGI application. requires flup."""
|
"Runs this project as a FastCGI application. Requires flup."
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils import translation
|
||||||
|
# Activate the current language, because it won't get activated later.
|
||||||
|
try:
|
||||||
|
translation.activate(settings.LANGUAGE_CODE)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
from django.core.servers.fastcgi import runfastcgi
|
from django.core.servers.fastcgi import runfastcgi
|
||||||
runfastcgi(args)
|
runfastcgi(args)
|
||||||
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
|
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
|
||||||
@ -1167,7 +1184,11 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
|||||||
if action not in NO_SQL_TRANSACTION:
|
if action not in NO_SQL_TRANSACTION:
|
||||||
print style.SQL_KEYWORD("COMMIT;")
|
print style.SQL_KEYWORD("COMMIT;")
|
||||||
|
|
||||||
def execute_manager(settings_mod, argv=None):
|
def setup_environ(settings_mod):
|
||||||
|
"""
|
||||||
|
Configure the runtime environment. This can also be used by external
|
||||||
|
scripts wanting to set up a similar environment to manage.py.
|
||||||
|
"""
|
||||||
# Add this project to sys.path so that it's importable in the conventional
|
# Add this project to sys.path so that it's importable in the conventional
|
||||||
# way. For example, if this file (manage.py) lives in a directory
|
# way. For example, if this file (manage.py) lives in a directory
|
||||||
# "myproject", this code would add "/path/to/myproject" to sys.path.
|
# "myproject", this code would add "/path/to/myproject" to sys.path.
|
||||||
@ -1179,7 +1200,10 @@ def execute_manager(settings_mod, argv=None):
|
|||||||
|
|
||||||
# Set DJANGO_SETTINGS_MODULE appropriately.
|
# Set DJANGO_SETTINGS_MODULE appropriately.
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
|
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
|
||||||
|
return project_directory
|
||||||
|
|
||||||
|
def execute_manager(settings_mod, argv=None):
|
||||||
|
project_directory = setup_environ(settings_mod)
|
||||||
action_mapping = DEFAULT_ACTION_MAPPING.copy()
|
action_mapping = DEFAULT_ACTION_MAPPING.copy()
|
||||||
|
|
||||||
# Remove the "startproject" command from the action_mapping, because that's
|
# Remove the "startproject" command from the action_mapping, because that's
|
||||||
|
@ -547,10 +547,6 @@ class WSGIRequestHandler(BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
env['PATH_INFO'] = urllib.unquote(path)
|
env['PATH_INFO'] = urllib.unquote(path)
|
||||||
env['QUERY_STRING'] = query
|
env['QUERY_STRING'] = query
|
||||||
|
|
||||||
host = self.address_string()
|
|
||||||
if host != self.client_address[0]:
|
|
||||||
env['REMOTE_HOST'] = host
|
|
||||||
env['REMOTE_ADDR'] = self.client_address[0]
|
env['REMOTE_ADDR'] = self.client_address[0]
|
||||||
|
|
||||||
if self.headers.typeheader is None:
|
if self.headers.typeheader is None:
|
||||||
|
@ -86,10 +86,15 @@ class MatchChecker(object):
|
|||||||
class RegexURLPattern(object):
|
class RegexURLPattern(object):
|
||||||
def __init__(self, regex, callback, default_args=None):
|
def __init__(self, regex, callback, default_args=None):
|
||||||
# regex is a string representing a regular expression.
|
# regex is a string representing a regular expression.
|
||||||
# callback is something like 'foo.views.news.stories.story_detail',
|
# callback is either a string like 'foo.views.news.stories.story_detail'
|
||||||
# which represents the path to a module and a view function name.
|
# which represents the path to a module and a view function name, or a
|
||||||
|
# callable object (view).
|
||||||
self.regex = re.compile(regex)
|
self.regex = re.compile(regex)
|
||||||
self.callback = callback
|
if callable(callback):
|
||||||
|
self._callback = callback
|
||||||
|
else:
|
||||||
|
self._callback = None
|
||||||
|
self._callback_str = callback
|
||||||
self.default_args = default_args or {}
|
self.default_args = default_args or {}
|
||||||
|
|
||||||
def resolve(self, path):
|
def resolve(self, path):
|
||||||
@ -106,23 +111,28 @@ class RegexURLPattern(object):
|
|||||||
# In both cases, pass any extra_kwargs as **kwargs.
|
# In both cases, pass any extra_kwargs as **kwargs.
|
||||||
kwargs.update(self.default_args)
|
kwargs.update(self.default_args)
|
||||||
|
|
||||||
try: # Lazily load self.func.
|
return self.callback, args, kwargs
|
||||||
return self.func, args, kwargs
|
|
||||||
except AttributeError:
|
|
||||||
self.func = self.get_callback()
|
|
||||||
return self.func, args, kwargs
|
|
||||||
|
|
||||||
def get_callback(self):
|
def _get_callback(self):
|
||||||
mod_name, func_name = get_mod_func(self.callback)
|
if self._callback is not None:
|
||||||
|
return self._callback
|
||||||
|
mod_name, func_name = get_mod_func(self._callback_str)
|
||||||
try:
|
try:
|
||||||
return getattr(__import__(mod_name, '', '', ['']), func_name)
|
self._callback = getattr(__import__(mod_name, '', '', ['']), func_name)
|
||||||
except ImportError, e:
|
except ImportError, e:
|
||||||
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
|
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
|
||||||
except AttributeError, e:
|
except AttributeError, e:
|
||||||
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
|
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
|
||||||
|
return self._callback
|
||||||
|
callback = property(_get_callback)
|
||||||
|
|
||||||
def reverse(self, viewname, *args, **kwargs):
|
def reverse(self, viewname, *args, **kwargs):
|
||||||
if viewname != self.callback:
|
mod_name, func_name = get_mod_func(viewname)
|
||||||
|
try:
|
||||||
|
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
raise NoReverseMatch
|
||||||
|
if lookup_view != self.callback:
|
||||||
raise NoReverseMatch
|
raise NoReverseMatch
|
||||||
return self.reverse_helper(*args, **kwargs)
|
return self.reverse_helper(*args, **kwargs)
|
||||||
|
|
||||||
@ -185,22 +195,28 @@ class RegexURLResolver(object):
|
|||||||
def resolve500(self):
|
def resolve500(self):
|
||||||
return self._resolve_special('500')
|
return self._resolve_special('500')
|
||||||
|
|
||||||
def reverse(self, viewname, *args, **kwargs):
|
def reverse(self, lookup_view, *args, **kwargs):
|
||||||
|
if not callable(lookup_view):
|
||||||
|
mod_name, func_name = get_mod_func(lookup_view)
|
||||||
|
try:
|
||||||
|
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
raise NoReverseMatch
|
||||||
for pattern in self.urlconf_module.urlpatterns:
|
for pattern in self.urlconf_module.urlpatterns:
|
||||||
if isinstance(pattern, RegexURLResolver):
|
if isinstance(pattern, RegexURLResolver):
|
||||||
try:
|
try:
|
||||||
return pattern.reverse_helper(viewname, *args, **kwargs)
|
return pattern.reverse_helper(lookup_view, *args, **kwargs)
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
continue
|
continue
|
||||||
elif pattern.callback == viewname:
|
elif pattern.callback == lookup_view:
|
||||||
try:
|
try:
|
||||||
return pattern.reverse_helper(*args, **kwargs)
|
return pattern.reverse_helper(*args, **kwargs)
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
continue
|
continue
|
||||||
raise NoReverseMatch
|
raise NoReverseMatch
|
||||||
|
|
||||||
def reverse_helper(self, viewname, *args, **kwargs):
|
def reverse_helper(self, lookup_view, *args, **kwargs):
|
||||||
sub_match = self.reverse(viewname, *args, **kwargs)
|
sub_match = self.reverse(lookup_view, *args, **kwargs)
|
||||||
result = reverse_helper(self.regex, *args, **kwargs)
|
result = reverse_helper(self.regex, *args, **kwargs)
|
||||||
return result + sub_match
|
return result + sub_match
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ class SchemaBuilder(object):
|
|||||||
col = opts.get_field(f.rel.field_name).column
|
col = opts.get_field(f.rel.field_name).column
|
||||||
# For MySQL, r_name must be unique in the first 64
|
# For MySQL, r_name must be unique in the first 64
|
||||||
# characters. So we are careful with character usage here.
|
# characters. So we are careful with character usage here.
|
||||||
r_name = '%s_refs_%s_%x' % (r_col, col,
|
r_name = '%s_refs_%s_%x' % (col, r_col,
|
||||||
abs(hash((r_table, table))))
|
abs(hash((r_table, table))))
|
||||||
sql = style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
|
sql = style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
|
||||||
(quote_name(table), quote_name(r_name),
|
(quote_name(table), quote_name(r_name),
|
||||||
@ -262,8 +262,10 @@ class SchemaBuilder(object):
|
|||||||
style.SQL_TABLE(qn(table)),
|
style.SQL_TABLE(qn(table)),
|
||||||
style.SQL_KEYWORD(
|
style.SQL_KEYWORD(
|
||||||
backend.get_drop_foreignkey_sql()),
|
backend.get_drop_foreignkey_sql()),
|
||||||
style.SQL_FIELD(qn("%s_referencing_%s_%s" %
|
style.SQL_FIELD(qn("%s_refs_%s_%x" %
|
||||||
(col, r_table, r_col)))),
|
(col, r_col,
|
||||||
|
abs(hash((table, r_table)))))
|
||||||
|
)),
|
||||||
db.connection))
|
db.connection))
|
||||||
del references_to_delete[model]
|
del references_to_delete[model]
|
||||||
# many to many: drop any many-many tables that are my
|
# many to many: drop any many-many tables that are my
|
||||||
|
@ -11,6 +11,10 @@ except ImportError, e:
|
|||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
raise ImproperlyConfigured, "Error loading psycopg2 module: %s" % e
|
raise ImproperlyConfigured, "Error loading psycopg2 module: %s" % e
|
||||||
|
|
||||||
|
# Register Unicode conversions
|
||||||
|
import psycopg2.extensions
|
||||||
|
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
||||||
|
|
||||||
DatabaseError = Database.DatabaseError
|
DatabaseError = Database.DatabaseError
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -25,7 +25,7 @@ def permalink(func):
|
|||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
bits = func(*args, **kwargs)
|
bits = func(*args, **kwargs)
|
||||||
viewname = bits[0]
|
viewname = bits[0]
|
||||||
return reverse(bits[0], None, *bits[1:2])
|
return reverse(bits[0], None, *bits[1:3])
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
class LazyDate(object):
|
class LazyDate(object):
|
||||||
@ -47,7 +47,7 @@ class LazyDate(object):
|
|||||||
return "<LazyDate: %s>" % self.delta
|
return "<LazyDate: %s>" % self.delta
|
||||||
|
|
||||||
def __get_value__(self):
|
def __get_value__(self):
|
||||||
return datetime.datetime.now() + self.delta
|
return (datetime.datetime.now() + self.delta).date()
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
return getattr(self.__get_value__(), attr)
|
return getattr(self.__get_value__(), attr)
|
||||||
|
@ -180,11 +180,12 @@ class Model(object):
|
|||||||
# If it does already exist, do an UPDATE.
|
# If it does already exist, do an UPDATE.
|
||||||
if cursor.fetchone():
|
if cursor.fetchone():
|
||||||
db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks]
|
db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks]
|
||||||
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
|
if db_values:
|
||||||
(qn(self._meta.db_table),
|
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
|
||||||
','.join(['%s=%%s' % qn(f.column) for f in non_pks]),
|
(qn(self._meta.db_table),
|
||||||
qn(self._meta.pk.column)),
|
','.join(['%s=%%s' % qn(f.column) for f in non_pks]),
|
||||||
db_values + [pk_val])
|
qn(self._meta.pk.column)),
|
||||||
|
db_values + [pk_val])
|
||||||
else:
|
else:
|
||||||
record_exists = False
|
record_exists = False
|
||||||
if not pk_set or not record_exists:
|
if not pk_set or not record_exists:
|
||||||
|
@ -20,7 +20,7 @@ BLANK_CHOICE_DASH = [("", "---------")]
|
|||||||
BLANK_CHOICE_NONE = [("", "None")]
|
BLANK_CHOICE_NONE = [("", "None")]
|
||||||
|
|
||||||
# prepares a value for use in a LIKE query
|
# prepares a value for use in a LIKE query
|
||||||
prep_for_like_query = lambda x: str(x).replace("%", "\%").replace("_", "\_")
|
prep_for_like_query = lambda x: str(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")
|
||||||
|
|
||||||
# returns the <ul> class for a given radio_admin value
|
# returns the <ul> class for a given radio_admin value
|
||||||
get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '')
|
get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '')
|
||||||
|
@ -35,7 +35,7 @@ def get_apps():
|
|||||||
_app_errors[app_name] = e
|
_app_errors[app_name] = e
|
||||||
return _app_list
|
return _app_list
|
||||||
|
|
||||||
def get_app(app_label, emptyOK = False):
|
def get_app(app_label, emptyOK=False):
|
||||||
"Returns the module containing the models for the given app_label. If the app has no models in it and 'emptyOK' is True, returns None."
|
"Returns the module containing the models for the given app_label. If the app has no models in it and 'emptyOK' is True, returns None."
|
||||||
get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish.
|
get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish.
|
||||||
for app_name in settings.INSTALLED_APPS:
|
for app_name in settings.INSTALLED_APPS:
|
||||||
@ -83,7 +83,7 @@ def get_models(app_mod=None, creation_order=False):
|
|||||||
model_list.extend(get_models(app_mod))
|
model_list.extend(get_models(app_mod))
|
||||||
return model_list
|
return model_list
|
||||||
|
|
||||||
def get_model(app_label, model_name, seed_cache = True):
|
def get_model(app_label, model_name, seed_cache=True):
|
||||||
"""
|
"""
|
||||||
Returns the model matching the given app_label and case-insensitive
|
Returns the model matching the given app_label and case-insensitive
|
||||||
model_name.
|
model_name.
|
||||||
|
@ -138,7 +138,7 @@ class AutomaticManipulator(forms.Manipulator):
|
|||||||
child_follow = self.follow.get(related.name, None)
|
child_follow = self.follow.get(related.name, None)
|
||||||
|
|
||||||
if child_follow:
|
if child_follow:
|
||||||
obj_list = expanded_data[related.var_name].items()
|
obj_list = expanded_data.get(related.var_name, {}).items()
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -203,11 +203,14 @@ class HttpResponse(object):
|
|||||||
if val is not None:
|
if val is not None:
|
||||||
self.cookies[key][var.replace('_', '-')] = val
|
self.cookies[key][var.replace('_', '-')] = val
|
||||||
|
|
||||||
def delete_cookie(self, key):
|
def delete_cookie(self, key, path='/', domain=None):
|
||||||
try:
|
self.cookies[key] = ''
|
||||||
self.cookies[key]['max_age'] = 0
|
if path is not None:
|
||||||
except KeyError:
|
self.cookies[key]['path'] = path
|
||||||
pass
|
if domain is not None:
|
||||||
|
self.cookies[key]['domain'] = path
|
||||||
|
self.cookies[key]['expires'] = 0
|
||||||
|
self.cookies[key]['max-age'] = 0
|
||||||
|
|
||||||
def _get_content(self):
|
def _get_content(self):
|
||||||
content = ''.join(self._iterator)
|
content = ''.join(self._iterator)
|
||||||
|
@ -339,7 +339,7 @@ def date(value, arg=None):
|
|||||||
def time(value, arg=None):
|
def time(value, arg=None):
|
||||||
"Formats a time according to the given format"
|
"Formats a time according to the given format"
|
||||||
from django.utils.dateformat import time_format
|
from django.utils.dateformat import time_format
|
||||||
if not value:
|
if value in (None, ''):
|
||||||
return ''
|
return ''
|
||||||
if arg is None:
|
if arg is None:
|
||||||
arg = settings.TIME_FORMAT
|
arg = settings.TIME_FORMAT
|
||||||
|
@ -17,7 +17,7 @@ def load_template_source(template_name, template_dirs=None):
|
|||||||
return (open(filepath).read(), filepath)
|
return (open(filepath).read(), filepath)
|
||||||
except IOError:
|
except IOError:
|
||||||
tried.append(filepath)
|
tried.append(filepath)
|
||||||
if template_dirs:
|
if tried:
|
||||||
error_msg = "Tried %s" % tried
|
error_msg = "Tried %s" % tried
|
||||||
else:
|
else:
|
||||||
error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
|
error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
|
||||||
|
@ -6,6 +6,7 @@ from django.contrib.auth.views import redirect_to_login
|
|||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||||
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
|
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
|
||||||
|
from django.utils.translation import gettext
|
||||||
|
|
||||||
def create_object(request, model, template_name=None,
|
def create_object(request, model, template_name=None,
|
||||||
template_loader=loader, extra_context=None, post_save_redirect=None,
|
template_loader=loader, extra_context=None, post_save_redirect=None,
|
||||||
@ -39,7 +40,7 @@ def create_object(request, model, template_name=None,
|
|||||||
new_object = manipulator.save(new_data)
|
new_object = manipulator.save(new_data)
|
||||||
|
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
request.user.message_set.create(message="The %s was created successfully." % model._meta.verbose_name)
|
request.user.message_set.create(message=gettext("The %(verbose_name)s was created successfully.") % {"verbose_name": model._meta.verbose_name})
|
||||||
|
|
||||||
# Redirect to the new object: first by trying post_save_redirect,
|
# Redirect to the new object: first by trying post_save_redirect,
|
||||||
# then by obj.get_absolute_url; fail if neither works.
|
# then by obj.get_absolute_url; fail if neither works.
|
||||||
@ -113,7 +114,7 @@ def update_object(request, model, object_id=None, slug=None,
|
|||||||
object = manipulator.save(new_data)
|
object = manipulator.save(new_data)
|
||||||
|
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
request.user.message_set.create(message="The %s was updated successfully." % model._meta.verbose_name)
|
request.user.message_set.create(message=gettext("The %(verbose_name)s was updated successfully.") % {"verbose_name": model._meta.verbose_name})
|
||||||
|
|
||||||
# Do a post-after-redirect so that reload works, etc.
|
# Do a post-after-redirect so that reload works, etc.
|
||||||
if post_save_redirect:
|
if post_save_redirect:
|
||||||
@ -180,7 +181,7 @@ def delete_object(request, model, post_delete_redirect,
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
object.delete()
|
object.delete()
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
request.user.message_set.create(message="The %s was deleted." % model._meta.verbose_name)
|
request.user.message_set.create(message=gettext("The %(verbose_name)s was deleted.") % {"verbose_name": model._meta.verbose_name})
|
||||||
return HttpResponseRedirect(post_delete_redirect)
|
return HttpResponseRedirect(post_delete_redirect)
|
||||||
else:
|
else:
|
||||||
if not template_name:
|
if not template_name:
|
||||||
|
@ -1471,11 +1471,12 @@ the ``ForeignKey`` ``Manager`` has these additional methods:
|
|||||||
b.entry_set.remove(e) # Disassociates Entry e from Blog b.
|
b.entry_set.remove(e) # Disassociates Entry e from Blog b.
|
||||||
|
|
||||||
In order to prevent database inconsistency, this method only exists on
|
In order to prevent database inconsistency, this method only exists on
|
||||||
``ForeignKey``s where ``null=True``. If the related field can't be set to
|
``ForeignKey`` objects where ``null=True``. If the related field can't be
|
||||||
``None`` (``NULL``), then an object can't be removed from a relation
|
set to ``None`` (``NULL``), then an object can't be removed from a
|
||||||
without being added to another. In the above example, removing ``e`` from
|
relation without being added to another. In the above example, removing
|
||||||
``b.entry_set()`` is equivalent to doing ``e.blog = None``, and because
|
``e`` from ``b.entry_set()`` is equivalent to doing ``e.blog = None``,
|
||||||
the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this is invalid.
|
and because the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this
|
||||||
|
is invalid.
|
||||||
|
|
||||||
* ``clear()``: Removes all objects from the related object set.
|
* ``clear()``: Removes all objects from the related object set.
|
||||||
|
|
||||||
|
148
docs/documentation.txt
Normal file
148
docs/documentation.txt
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
====================================
|
||||||
|
How to read the Django documentation
|
||||||
|
====================================
|
||||||
|
|
||||||
|
We've put a lot of effort into making Django's documentation useful, easy to
|
||||||
|
read and as complete as possible. Here are a few tips on how to make the best
|
||||||
|
of it, along with some style guidelines.
|
||||||
|
|
||||||
|
(Yes, this is documentation about documentation. Rest assured we have no plans
|
||||||
|
to write a document about how to read the document about documentation.)
|
||||||
|
|
||||||
|
How documentation is updated
|
||||||
|
============================
|
||||||
|
|
||||||
|
Just as the Django code base is developed and improved on a daily basis, our
|
||||||
|
documentation is consistently improving. We improve documentation for several
|
||||||
|
reasons:
|
||||||
|
|
||||||
|
* To make content fixes, such as grammar/typo corrections.
|
||||||
|
* To add information and/or examples to existing sections that need to be
|
||||||
|
expanded.
|
||||||
|
* To document Django features that aren't yet documented. (The list of
|
||||||
|
such features is shrinking but exists nonetheless.)
|
||||||
|
* To add documentation for new features as new features get added, or as
|
||||||
|
Django APIs or behaviors change.
|
||||||
|
|
||||||
|
Django's documentation is kept in the same source control system as its code.
|
||||||
|
It lives in the `django/trunk/docs`_ directory of our Subversion repository.
|
||||||
|
Each document is a separate text file that covers a narrowly focused topic,
|
||||||
|
such as the "generic views" framework or how to construct a database model.
|
||||||
|
|
||||||
|
.. _django/trunk/docs: http://code.djangoproject.com/browser/django/trunk/docs
|
||||||
|
|
||||||
|
Where to get it
|
||||||
|
===============
|
||||||
|
|
||||||
|
You can read Django documentation in several ways. They are, in order of
|
||||||
|
preference:
|
||||||
|
|
||||||
|
On the Web
|
||||||
|
----------
|
||||||
|
|
||||||
|
The most recent version of the Django documentation lives at
|
||||||
|
http://www.djangoproject.com/documentation/ . These HTML pages are generated
|
||||||
|
automatically from the text files in source control every 15 minutes. That
|
||||||
|
means they reflect the "latest and greatest" in Django -- they include the very
|
||||||
|
latest corrections and additions, and they discuss the latest Django features,
|
||||||
|
which may only be available to users of the Django development version. (See
|
||||||
|
"Differences between versions" below.)
|
||||||
|
|
||||||
|
A key advantage of the Web-based documentation is the comment section at the
|
||||||
|
bottom of each document. This is an area for anybody to submit changes,
|
||||||
|
corrections and suggestions about the given document. The Django developers
|
||||||
|
frequently monitor the comments there and use them to improve the documentation
|
||||||
|
for everybody.
|
||||||
|
|
||||||
|
We encourage you to help improve the docs: it's easy! Note, however, that
|
||||||
|
comments should explicitly relate to the documentation, rather than asking
|
||||||
|
broad tech-support questions. If you need help with your particular Django
|
||||||
|
setup, try the `django-users mailing list`_ instead of posting a comment to the
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
.. _django-users mailing list: http://groups.google.com/group/django-users
|
||||||
|
|
||||||
|
In plain text
|
||||||
|
-------------
|
||||||
|
|
||||||
|
For offline reading, or just for convenience, you can read the Django
|
||||||
|
documentation in plain text.
|
||||||
|
|
||||||
|
If you're using an official release of Django, note that the zipped package
|
||||||
|
(tarball) of the code includes a ``docs/`` directory, which contains all the
|
||||||
|
documentation for that release.
|
||||||
|
|
||||||
|
If you're using the development version of Django (aka the Subversion "trunk"),
|
||||||
|
note that the ``docs/`` directory contains all of the documentation. You can
|
||||||
|
``svn update`` it, just as you ``svn update`` the Python code, in order to get
|
||||||
|
the latest changes.
|
||||||
|
|
||||||
|
You can check out the latest Django documentation from Subversion using this
|
||||||
|
shell command::
|
||||||
|
|
||||||
|
svn co http://code.djangoproject.com/svn/django/trunk/docs/ django_docs
|
||||||
|
|
||||||
|
One low-tech way of taking advantage of the text documentation is by using the
|
||||||
|
Unix ``grep`` utility to search for a phrase in all of the documentation. For
|
||||||
|
example, this will show you each mention of the phrase "edit_inline" in any
|
||||||
|
Django document::
|
||||||
|
|
||||||
|
grep edit_inline /path/to/django/docs/*.txt
|
||||||
|
|
||||||
|
Formatting
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
The text documentation is written in ReST (ReStructured Text) format. That
|
||||||
|
means it's easy to read but is also formatted in a way that makes it easy to
|
||||||
|
convert into other formats, such as HTML. If you're interested, the script that
|
||||||
|
converts the ReST text docs into djangoproject.com's HTML lives at
|
||||||
|
`djangoproject.com/django_website/apps/docs/parts/build_documentation.py`_ in
|
||||||
|
the Django Subversion repository.
|
||||||
|
|
||||||
|
.. _djangoproject.com/django_website/apps/docs/parts/build_documentation.py: http://code.djangoproject.com/browser/djangoproject.com/django_website/apps/docs/parts/build_documentation.py
|
||||||
|
|
||||||
|
Differences between versions
|
||||||
|
============================
|
||||||
|
|
||||||
|
As previously mentioned, the text documentation in our Subversion repository
|
||||||
|
contains the "latest and greatest" changes and additions. These changes often
|
||||||
|
include documentation of new features added in the Django development version
|
||||||
|
-- the Subversion ("trunk") version of Django. For that reason, it's worth
|
||||||
|
pointing out our policy on keeping straight the documentation for various
|
||||||
|
versions of the framework.
|
||||||
|
|
||||||
|
We follow this policy:
|
||||||
|
|
||||||
|
* The primary documentation on djangoproject.com is an HTML version of the
|
||||||
|
latest docs in Subversion. These docs always correspond to the latest
|
||||||
|
official Django release, plus whatever features we've added/changed in
|
||||||
|
the framework *since* the latest release.
|
||||||
|
|
||||||
|
* As we add features to Django's development version, we try to update the
|
||||||
|
documentation in the same Subversion commit transaction.
|
||||||
|
|
||||||
|
* To distinguish feature changes/additions in the docs, we use the phrase
|
||||||
|
**New in Django development version**. In practice, this means that the
|
||||||
|
current documentation on djangoproject.com can be used by users of either
|
||||||
|
the latest release *or* the development version.
|
||||||
|
|
||||||
|
* Documentation for a particular Django release is frozen once the version
|
||||||
|
has been released officially. It remains a snapshot of the docs as of the
|
||||||
|
moment of the release. We will make exceptions to this rule in
|
||||||
|
the case of retroactive security updates or other such retroactive
|
||||||
|
changes. Once documentation is frozen, we add a note to the top of each
|
||||||
|
frozen document that says "These docs are frozen for Django version XXX"
|
||||||
|
and links to the current version of that document.
|
||||||
|
|
||||||
|
* Once a document is frozen for a Django release, we remove comments from
|
||||||
|
that page, in favor of having comments on the latest version of that
|
||||||
|
document. This is for the sake of maintainability and usability, so that
|
||||||
|
users have one, and only one, place to leave comments on a particular
|
||||||
|
document. We realize that some people may be stuck on a previous version
|
||||||
|
of Django, but we believe the usability problems with multiple versions
|
||||||
|
of a document the outweigh the benefits.
|
||||||
|
|
||||||
|
* The `main documentation Web page`_ includes links to documentation for
|
||||||
|
all previous versions.
|
||||||
|
|
||||||
|
.. _main documentation Web page: http://www.djangoproject.com/documentation/
|
@ -127,7 +127,7 @@ If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410).
|
|||||||
This example redirects from ``/foo/<id>/`` to ``/bar/<id>/``::
|
This example redirects from ``/foo/<id>/`` to ``/bar/<id>/``::
|
||||||
|
|
||||||
urlpatterns = patterns('django.views.generic.simple',
|
urlpatterns = patterns('django.views.generic.simple',
|
||||||
('^foo/(?p<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}),
|
('^foo/(?P<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}),
|
||||||
)
|
)
|
||||||
|
|
||||||
This example returns a 410 HTTP error for requests to ``/bar/``::
|
This example returns a 410 HTTP error for requests to ``/bar/``::
|
||||||
|
@ -223,6 +223,13 @@ steps:
|
|||||||
the absolute URL to your image in a template with ``{{
|
the absolute URL to your image in a template with ``{{
|
||||||
object.get_mug_shot_url }}``.
|
object.get_mug_shot_url }}``.
|
||||||
|
|
||||||
|
For example, say your ``MEDIA_ROOT`` is set to ``'/home/media'``, and
|
||||||
|
``upload_to`` is set to ``'photos/%Y/%m/%d'``. The ``'%Y/%m/%d'`` part of
|
||||||
|
``upload_to`` is strftime formatting; ``'%Y'`` is the four-digit year,
|
||||||
|
``'%m'`` is the two-digit month and ``'%d'`` is the two-digit day. If you
|
||||||
|
upload a file on Jan. 15, 2007, it will be saved in the directory
|
||||||
|
``/home/media/photos/2007/01/15``.
|
||||||
|
|
||||||
.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941
|
.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941
|
||||||
|
|
||||||
``FilePathField``
|
``FilePathField``
|
||||||
|
@ -380,10 +380,14 @@ Methods
|
|||||||
|
|
||||||
.. _`cookie Morsel`: http://www.python.org/doc/current/lib/morsel-objects.html
|
.. _`cookie Morsel`: http://www.python.org/doc/current/lib/morsel-objects.html
|
||||||
|
|
||||||
``delete_cookie(key)``
|
``delete_cookie(key, path='/', domain=None)``
|
||||||
Deletes the cookie with the given key. Fails silently if the key doesn't
|
Deletes the cookie with the given key. Fails silently if the key doesn't
|
||||||
exist.
|
exist.
|
||||||
|
|
||||||
|
The ``path`` and ``domain`` arguments are new in the Django development version.
|
||||||
|
Due to the way cookies work, ``path`` and ``domain`` should be the same
|
||||||
|
values you used in ``set_cookie()`` -- otherwise the cookie may not be deleted.
|
||||||
|
|
||||||
``content``
|
``content``
|
||||||
Returns the content as a Python string, encoding it from a Unicode object
|
Returns the content as a Python string, encoding it from a Unicode object
|
||||||
if necessary. Note this is a property, not a method, so use ``r.content``
|
if necessary. Note this is a property, not a method, so use ``r.content``
|
||||||
|
@ -245,6 +245,17 @@ Default: ``'sessionid'``
|
|||||||
|
|
||||||
The name of the cookie to use for sessions. This can be whatever you want.
|
The name of the cookie to use for sessions. This can be whatever you want.
|
||||||
|
|
||||||
|
SESSION_COOKIE_SECURE
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
Whether to use a secure cookie for the session cookie. If this is set to
|
||||||
|
``True``, the cookie will be marked as "secure," which means browsers may
|
||||||
|
ensure that the cookie is only sent under an HTTPS connection.
|
||||||
|
|
||||||
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
@ -647,6 +647,18 @@ Default: ``'sessionid'``
|
|||||||
The name of the cookie to use for sessions. This can be whatever you want.
|
The name of the cookie to use for sessions. This can be whatever you want.
|
||||||
See the `session docs`_.
|
See the `session docs`_.
|
||||||
|
|
||||||
|
SESSION_COOKIE_SECURE
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
Whether to use a secure cookie for the session cookie. If this is set to
|
||||||
|
``True``, the cookie will be marked as "secure," which means browsers may
|
||||||
|
ensure that the cookie is only sent under an HTTPS connection.
|
||||||
|
See the `session docs`_.
|
||||||
|
|
||||||
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
@ -431,3 +431,48 @@ Note that extra options will *always* be passed to *every* line in the included
|
|||||||
URLconf, regardless of whether the line's view actually accepts those options
|
URLconf, regardless of whether the line's view actually accepts those options
|
||||||
as valid. For this reason, this technique is only useful if you're certain that
|
as valid. For this reason, this technique is only useful if you're certain that
|
||||||
every view in the the included URLconf accepts the extra options you're passing.
|
every view in the the included URLconf accepts the extra options you're passing.
|
||||||
|
|
||||||
|
Passing callable objects instead of strings
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
**New in the Django development version.**
|
||||||
|
|
||||||
|
Some developers find it more natural to pass the actual Python function object
|
||||||
|
rather than a string containing the path to its module. This alternative is
|
||||||
|
supported -- you can pass any callable object as the view.
|
||||||
|
|
||||||
|
For example, given this URLconf in "string" notation::
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^archive/$', 'mysite.views.archive'),
|
||||||
|
(r'^about/$', 'mysite.views.about'),
|
||||||
|
(r'^contact/$', 'mysite.views.contact'),
|
||||||
|
)
|
||||||
|
|
||||||
|
You can accomplish the same thing by passing objects rather than strings. Just
|
||||||
|
be sure to import the objects::
|
||||||
|
|
||||||
|
from mysite.views import archive, about, contact
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^archive/$', archive),
|
||||||
|
(r'^about/$', about),
|
||||||
|
(r'^contact/$', contact),
|
||||||
|
)
|
||||||
|
|
||||||
|
The following example is functionally identical. It's just a bit more compact
|
||||||
|
because it imports the module that contains the views, rather than importing
|
||||||
|
each view individually::
|
||||||
|
|
||||||
|
from mysite import views
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^archive/$', views.archive),
|
||||||
|
(r'^about/$', views.about),
|
||||||
|
(r'^contact/$', views.contact),
|
||||||
|
)
|
||||||
|
|
||||||
|
The style you use is up to you.
|
||||||
|
|
||||||
|
Note that if you use this technique -- passing objects rather than strings --
|
||||||
|
the view prefix (as explained in "The view prefix" above) will have no effect.
|
||||||
|
1
setup.py
1
setup.py
@ -16,6 +16,7 @@ setup(
|
|||||||
'': ['*.TXT'],
|
'': ['*.TXT'],
|
||||||
'django.conf': ['locale/*/LC_MESSAGES/*'],
|
'django.conf': ['locale/*/LC_MESSAGES/*'],
|
||||||
'django.contrib.admin': ['templates/admin/*.html',
|
'django.contrib.admin': ['templates/admin/*.html',
|
||||||
|
'templates/admin/auth/user/*.html',
|
||||||
'templates/admin_doc/*.html',
|
'templates/admin_doc/*.html',
|
||||||
'templates/registration/*.html',
|
'templates/registration/*.html',
|
||||||
'templates/widget/*.html',
|
'templates/widget/*.html',
|
||||||
|
@ -20,5 +20,7 @@ API_TESTS = """
|
|||||||
2
|
2
|
||||||
>>> m.id is not None
|
>>> m.id is not None
|
||||||
True
|
True
|
||||||
|
>>> existing = Empty(m.id)
|
||||||
|
>>> existing.save()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -15,7 +15,7 @@ class Article(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = r"""
|
||||||
# Create a couple of Articles.
|
# Create a couple of Articles.
|
||||||
>>> from datetime import datetime
|
>>> from datetime import datetime
|
||||||
>>> a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26))
|
>>> a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26))
|
||||||
@ -161,13 +161,14 @@ DoesNotExist: Article matching query does not exist.
|
|||||||
<Article: Article 1>
|
<Article: Article 1>
|
||||||
|
|
||||||
# Underscores and percent signs have special meaning in the underlying
|
# Underscores and percent signs have special meaning in the underlying
|
||||||
# database library, but Django handles the quoting of them automatically.
|
# SQL code, but Django handles the quoting of them automatically.
|
||||||
>>> a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
|
>>> a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
|
||||||
>>> a8.save()
|
>>> a8.save()
|
||||||
>>> Article.objects.filter(headline__startswith='Article')
|
>>> Article.objects.filter(headline__startswith='Article')
|
||||||
[<Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
[<Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
||||||
>>> Article.objects.filter(headline__startswith='Article_')
|
>>> Article.objects.filter(headline__startswith='Article_')
|
||||||
[<Article: Article_ with underscore>]
|
[<Article: Article_ with underscore>]
|
||||||
|
|
||||||
>>> a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
|
>>> a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
|
||||||
>>> a9.save()
|
>>> a9.save()
|
||||||
>>> Article.objects.filter(headline__startswith='Article')
|
>>> Article.objects.filter(headline__startswith='Article')
|
||||||
@ -182,4 +183,12 @@ DoesNotExist: Article matching query does not exist.
|
|||||||
[<Article: Article% with percent sign>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
[<Article: Article% with percent sign>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
||||||
>>> Article.objects.exclude(headline="Article 7")
|
>>> Article.objects.exclude(headline="Article 7")
|
||||||
[<Article: Article% with percent sign>, <Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 1>]
|
[<Article: Article% with percent sign>, <Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 1>]
|
||||||
|
|
||||||
|
# Backslashes also have special meaning in the underlying SQL code, but Django
|
||||||
|
# automatically quotes them appropriately.
|
||||||
|
>>> a10 = Article(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22))
|
||||||
|
>>> a10.save()
|
||||||
|
>>> Article.objects.filter(headline__contains='\\')
|
||||||
|
[<Article: Article with \ backslash>]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -231,6 +231,9 @@ False
|
|||||||
>>> time(datetime.time(13), "h")
|
>>> time(datetime.time(13), "h")
|
||||||
'01'
|
'01'
|
||||||
|
|
||||||
|
>>> time(datetime.time(0), "h")
|
||||||
|
'12'
|
||||||
|
|
||||||
# real testing is done in timesince.py, where we can provide our own 'now'
|
# real testing is done in timesince.py, where we can provide our own 'now'
|
||||||
>>> timesince(datetime.datetime.now() - datetime.timedelta(1))
|
>>> timesince(datetime.datetime.now() - datetime.timedelta(1))
|
||||||
'1 day'
|
'1 day'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user