mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
[multi-db] Merge trunk to [3522]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@3523 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
08c4207182
commit
238c6ecd5b
2
AUTHORS
2
AUTHORS
@ -70,6 +70,8 @@ answer newbie questions, and generally made Django that much better:
|
||||
Clint Ecker
|
||||
gandalf@owca.info
|
||||
Baishampayan Ghose
|
||||
martin.glueck@gmail.com
|
||||
Simon Greenhill <dev@simon.net.nz>
|
||||
Espen Grindhaug <http://grindhaug.org/>
|
||||
Brant Harris
|
||||
hipertracker@gmail.com
|
||||
|
Binary file not shown.
@ -141,6 +141,7 @@ msgid "score date"
|
||||
msgstr "счёт времени"
|
||||
|
||||
#: contrib/comments/models.py:237
|
||||
#, fuzzy
|
||||
msgid "karma score"
|
||||
msgstr "Карма счёт"
|
||||
|
||||
@ -735,7 +736,7 @@ msgstr "К сожалению, запрашиваемая вами страни
|
||||
#: contrib/admin/templates/admin/index.html:17
|
||||
#, python-format
|
||||
msgid "Models available in the %(name)s application."
|
||||
msgstr "Модели доступны в %(name)s приложении."
|
||||
msgstr "Модели доступны в %(name) приложении."
|
||||
|
||||
#: contrib/admin/templates/admin/index.html:28
|
||||
#: contrib/admin/templates/admin/change_form.html:15
|
||||
|
@ -10,8 +10,10 @@ include = lambda urlconf_module: [urlconf_module]
|
||||
def patterns(prefix, *tuples):
|
||||
pattern_list = []
|
||||
for t in tuples:
|
||||
if type(t[1]) == list:
|
||||
pattern_list.append(RegexURLResolver(t[0], t[1][0]))
|
||||
regex, view_or_include = t[:2]
|
||||
default_kwargs = t[2:]
|
||||
if type(view_or_include) == list:
|
||||
pattern_list.append(RegexURLResolver(regex, view_or_include[0], *default_kwargs))
|
||||
else:
|
||||
pattern_list.append(RegexURLPattern(t[0], prefix and (prefix + '.' + t[1]) or t[1], *t[2:]))
|
||||
pattern_list.append(RegexURLPattern(regex, prefix and (prefix + '.' + view_or_include) or view_or_include, *default_kwargs))
|
||||
return pattern_list
|
||||
|
@ -8,7 +8,9 @@ var DateTimeShortcuts = {
|
||||
clockInputs: [],
|
||||
calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
|
||||
calendarDivName2: 'calendarin', // name of <div> that contains calendar
|
||||
calendarLinkName: 'calendarlink',// name of the link that is used to toggle
|
||||
clockDivName: 'clockbox', // name of clock <div> that gets toggled
|
||||
clockLinkName: 'clocklink', // name of the link that is used to toggle
|
||||
admin_media_prefix: '',
|
||||
init: function() {
|
||||
// Deduce admin_media_prefix by looking at the <script>s in the
|
||||
@ -46,6 +48,7 @@ var DateTimeShortcuts = {
|
||||
now_link.appendChild(document.createTextNode(gettext('Now')));
|
||||
var clock_link = document.createElement('a');
|
||||
clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
|
||||
clock_link.id = DateTimeShortcuts.clockLinkName + num;
|
||||
quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_clock.gif', 'alt', gettext('Clock'));
|
||||
shortcuts_span.appendChild(document.createTextNode('\240'));
|
||||
shortcuts_span.appendChild(now_link);
|
||||
@ -69,17 +72,6 @@ var DateTimeShortcuts = {
|
||||
var clock_box = document.createElement('div');
|
||||
clock_box.style.display = 'none';
|
||||
clock_box.style.position = 'absolute';
|
||||
if (getStyle(document.body,'direction')!='rtl') {
|
||||
clock_box.style.left = findPosX(clock_link) + 17 + 'px';
|
||||
}
|
||||
else {
|
||||
// since style's width is in em, it'd be tough to calculate
|
||||
// px value of it. let's use an estimated px for now
|
||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||
// (it returns as it was left aligned), needs to be fixed.
|
||||
clock_box.style.left = findPosX(clock_link) - 110 + 'px';
|
||||
}
|
||||
clock_box.style.top = findPosY(clock_link) - 30 + 'px';
|
||||
clock_box.className = 'clockbox module';
|
||||
clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
|
||||
document.body.appendChild(clock_box);
|
||||
@ -98,7 +90,25 @@ var DateTimeShortcuts = {
|
||||
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
|
||||
},
|
||||
openClock: function(num) {
|
||||
document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'block';
|
||||
var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
|
||||
var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
|
||||
|
||||
// Recalculate the clockbox position
|
||||
// is it left-to-right or right-to-left layout ?
|
||||
if (getStyle(document.body,'direction')!='rtl') {
|
||||
clock_box.style.left = findPosX(clock_link) + 17 + 'px';
|
||||
}
|
||||
else {
|
||||
// since style's width is in em, it'd be tough to calculate
|
||||
// px value of it. let's use an estimated px for now
|
||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||
// (it returns as it was left aligned), needs to be fixed.
|
||||
clock_box.style.left = findPosX(clock_link) - 110 + 'px';
|
||||
}
|
||||
clock_box.style.top = findPosY(clock_link) - 30 + 'px';
|
||||
|
||||
// Show the clock box
|
||||
clock_box.style.display = 'block';
|
||||
addEvent(window, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
|
||||
},
|
||||
dismissClock: function(num) {
|
||||
@ -123,6 +133,7 @@ var DateTimeShortcuts = {
|
||||
today_link.appendChild(document.createTextNode(gettext('Today')));
|
||||
var cal_link = document.createElement('a');
|
||||
cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
|
||||
cal_link.id = DateTimeShortcuts.calendarLinkName + num;
|
||||
quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar'));
|
||||
shortcuts_span.appendChild(document.createTextNode('\240'));
|
||||
shortcuts_span.appendChild(today_link);
|
||||
@ -149,18 +160,6 @@ var DateTimeShortcuts = {
|
||||
var cal_box = document.createElement('div');
|
||||
cal_box.style.display = 'none';
|
||||
cal_box.style.position = 'absolute';
|
||||
// is it left-to-right or right-to-left layout ?
|
||||
if (getStyle(document.body,'direction')!='rtl') {
|
||||
cal_box.style.left = findPosX(cal_link) + 17 + 'px';
|
||||
}
|
||||
else {
|
||||
// since style's width is in em, it'd be tough to calculate
|
||||
// px value of it. let's use an estimated px for now
|
||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||
// (it returns as it was left aligned), needs to be fixed.
|
||||
cal_box.style.left = findPosX(cal_link) - 180 + 'px';
|
||||
}
|
||||
cal_box.style.top = findPosY(cal_link) - 75 + 'px';
|
||||
cal_box.className = 'calendarbox module';
|
||||
cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
|
||||
document.body.appendChild(cal_box);
|
||||
@ -195,7 +194,24 @@ var DateTimeShortcuts = {
|
||||
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
|
||||
},
|
||||
openCalendar: function(num) {
|
||||
document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'block';
|
||||
var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
|
||||
var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
|
||||
|
||||
// Recalculate the clockbox position
|
||||
// is it left-to-right or right-to-left layout ?
|
||||
if (getStyle(document.body,'direction')!='rtl') {
|
||||
cal_box.style.left = findPosX(cal_link) + 17 + 'px';
|
||||
}
|
||||
else {
|
||||
// since style's width is in em, it'd be tough to calculate
|
||||
// px value of it. let's use an estimated px for now
|
||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||
// (it returns as it was left aligned), needs to be fixed.
|
||||
cal_box.style.left = findPosX(cal_link) - 180 + 'px';
|
||||
}
|
||||
cal_box.style.top = findPosY(cal_link) - 75 + 'px';
|
||||
|
||||
cal_box.style.display = 'block';
|
||||
addEvent(window, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
|
||||
},
|
||||
dismissCalendar: function(num) {
|
||||
|
@ -11,7 +11,7 @@ function showRelatedObjectLookupPopup(triggeringLink) {
|
||||
} else {
|
||||
href = triggeringLink.href + '?pop=1';
|
||||
}
|
||||
var win = window.open(href, name, 'height=500,width=740,resizable=yes,scrollbars=yes');
|
||||
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||
win.focus();
|
||||
return false;
|
||||
}
|
||||
|
28
django/contrib/admin/templates/admin/auth/user/add_form.html
Normal file
28
django/contrib/admin/templates/admin/auth/user/add_form.html
Normal file
@ -0,0 +1,28 @@
|
||||
{% extends "admin/change_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block after_field_sets %}
|
||||
|
||||
<p>{% trans "First, enter a username and password. Then, you'll be able to edit more user options." %}</p>
|
||||
|
||||
<fieldset class="module aligned">
|
||||
|
||||
<div class="form-row">
|
||||
{{ form.username.html_error_list }}
|
||||
<label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }}
|
||||
<p class="help">{{ username_help_text }}</p>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
{{ form.password1.html_error_list }}
|
||||
<label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
{{ form.password2.html_error_list }}
|
||||
<label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
|
||||
<p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
{% endblock %}
|
@ -28,6 +28,9 @@ urlpatterns = patterns('',
|
||||
# ('^doc/templates/$', 'django.views.admin.doc.template_index'),
|
||||
('^doc/templates/(?P<template>.*)/$', 'django.contrib.admin.views.doc.template_detail'),
|
||||
|
||||
# "Add user" -- a special-case view
|
||||
('^auth/user/add/$', 'django.contrib.admin.views.auth.user_add_stage'),
|
||||
|
||||
# Add/change/delete/history
|
||||
('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'),
|
||||
('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
|
||||
|
39
django/contrib/admin/views/auth.py
Normal file
39
django/contrib/admin/views/auth.py
Normal file
@ -0,0 +1,39 @@
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from django.contrib.auth.models import User
|
||||
from django import forms, template
|
||||
from django.shortcuts import render_to_response
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
def user_add_stage(request):
|
||||
manipulator = UserCreationForm()
|
||||
if request.method == 'POST':
|
||||
new_data = request.POST.copy()
|
||||
errors = manipulator.get_validation_errors(new_data)
|
||||
if not errors:
|
||||
new_user = manipulator.save(new_data)
|
||||
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user}
|
||||
if request.POST.has_key("_addanother"):
|
||||
request.user.message_set.create(message=msg)
|
||||
return HttpResponseRedirect(request.path)
|
||||
else:
|
||||
request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
|
||||
return HttpResponseRedirect('../%s/' % new_user.id)
|
||||
else:
|
||||
errors = new_data = {}
|
||||
form = forms.FormWrapper(manipulator, new_data, errors)
|
||||
return render_to_response('admin/auth/user/add_form.html', {
|
||||
'title': _('Add user'),
|
||||
'form': form,
|
||||
'is_popup': request.REQUEST.has_key('_popup'),
|
||||
'add': True,
|
||||
'change': False,
|
||||
'has_delete_permission': False,
|
||||
'has_change_permission': True,
|
||||
'has_file_field': False,
|
||||
'has_absolute_url': False,
|
||||
'auto_populated_fields': (),
|
||||
'bound_field_sets': (),
|
||||
'first_form_field_id': 'id_username',
|
||||
'opts': User._meta,
|
||||
'username_help_text': User._meta.get_field('username').help_text,
|
||||
}, context_instance=template.RequestContext(request))
|
@ -5,6 +5,28 @@ from django.template import Context, loader
|
||||
from django.core import validators
|
||||
from django import forms
|
||||
|
||||
class UserCreationForm(forms.Manipulator):
|
||||
"A form that creates a user, with no privileges, from the given username and password."
|
||||
def __init__(self):
|
||||
self.fields = (
|
||||
forms.TextField(field_name='username', length=30, maxlength=30, is_required=True,
|
||||
validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
|
||||
forms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
|
||||
forms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
|
||||
validator_list=[validators.AlwaysMatchesOtherField('password1', "The two password fields didn't match.")]),
|
||||
)
|
||||
|
||||
def isValidUsername(self, field_data, all_data):
|
||||
try:
|
||||
User.objects.get(username=field_data)
|
||||
except User.DoesNotExist:
|
||||
return
|
||||
raise validators.ValidationError, 'A user with that username already exists.'
|
||||
|
||||
def save(self, new_data):
|
||||
"Creates the user."
|
||||
return User.objects.create_user(new_data['username'], '', new_data['password1'])
|
||||
|
||||
class AuthenticationForm(forms.Manipulator):
|
||||
"""
|
||||
Base class for authenticating users. Extend this to get a form that accepts
|
||||
|
@ -829,6 +829,12 @@ def get_validation_errors(outfile, app=None):
|
||||
f = opts.get_field(fn)
|
||||
except models.FieldDoesNotExist:
|
||||
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
|
||||
# date_hierarchy
|
||||
if opts.admin.date_hierarchy:
|
||||
try:
|
||||
f = opts.get_field(opts.admin.date_hierarchy)
|
||||
except models.FieldDoesNotExist:
|
||||
e.add(opts, '"admin.date_hierarchy" refers to %r, which isn\'t a field.' % opts.admin.date_hierarchy)
|
||||
|
||||
# Check ordering attribute.
|
||||
if opts.ordering:
|
||||
|
@ -130,12 +130,13 @@ class RegexURLPattern(object):
|
||||
return reverse_helper(self.regex, *args, **kwargs)
|
||||
|
||||
class RegexURLResolver(object):
|
||||
def __init__(self, regex, urlconf_name):
|
||||
def __init__(self, regex, urlconf_name, default_kwargs=None):
|
||||
# regex is a string representing a regular expression.
|
||||
# urlconf_name is a string representing the module containing urlconfs.
|
||||
self.regex = re.compile(regex)
|
||||
self.urlconf_name = urlconf_name
|
||||
self.callback = None
|
||||
self.default_kwargs = default_kwargs or {}
|
||||
|
||||
def resolve(self, path):
|
||||
tried = []
|
||||
@ -149,7 +150,8 @@ class RegexURLResolver(object):
|
||||
tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']])
|
||||
else:
|
||||
if sub_match:
|
||||
return sub_match[0], sub_match[1], dict(match.groupdict(), **sub_match[2])
|
||||
sub_match_dict = dict(self.default_kwargs, **sub_match[2])
|
||||
return sub_match[0], sub_match[1], dict(match.groupdict(), **sub_match_dict)
|
||||
tried.append(pattern.regex.pattern)
|
||||
raise Resolver404, {'tried': tried, 'path': new_path}
|
||||
|
||||
|
@ -137,9 +137,12 @@ class SchemaBuilder(object):
|
||||
r_col = f.column
|
||||
table = opts.db_table
|
||||
col = opts.get_field(f.rel.field_name).column
|
||||
# For MySQL, r_name must be unique in the first 64
|
||||
# characters. So we are careful with character usage here.
|
||||
r_name = '%s_refs_%s_%x' % (r_col, col,
|
||||
abs(hash((r_table, table))))
|
||||
sql = style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
|
||||
(quote_name(table),
|
||||
quote_name('%s_referencing_%s_%s' % (r_col, r_table, col)),
|
||||
(quote_name(table), quote_name(r_name),
|
||||
quote_name(r_col), quote_name(r_table), quote_name(col))
|
||||
pending.setdefault(rel_class, []).append(
|
||||
BoundStatement(sql, db.connection))
|
||||
|
@ -289,8 +289,11 @@ class Field(object):
|
||||
if self.choices:
|
||||
return first_choice + list(self.choices)
|
||||
rel_model = self.rel.to
|
||||
return first_choice + [(x._get_pk_val(), str(x))
|
||||
for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
|
||||
if hasattr(self.rel, 'get_related_field'):
|
||||
lst = [(getattr(x, self.rel.get_related_field().attname), str(x)) for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
|
||||
else:
|
||||
lst = [(x._get_pk_val(), str(x)) for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
|
||||
return first_choice + lst
|
||||
|
||||
def get_choices_default(self):
|
||||
if self.radio_admin:
|
||||
|
@ -25,7 +25,7 @@ def add_lookup(rel_cls, field):
|
||||
key = (module, name)
|
||||
# Has the model already been loaded?
|
||||
# If so, resolve the string reference right away
|
||||
model = get_model(rel_cls._meta.app_label,field.rel.to)
|
||||
model = get_model(rel_cls._meta.app_label, field.rel.to, False)
|
||||
if model:
|
||||
field.rel.to = model
|
||||
field.do_related_class(model, rel_cls)
|
||||
|
@ -12,7 +12,11 @@ class GZipMiddleware(object):
|
||||
"""
|
||||
def process_response(self, request, response):
|
||||
patch_vary_headers(response, ('Accept-Encoding',))
|
||||
if response.has_header('Content-Encoding'):
|
||||
|
||||
# Avoid gzipping if we've already got a content-encoding or if the
|
||||
# content-type is Javascript (silly IE...)
|
||||
is_js = "javascript" in response.headers.get('Content-Type', '').lower()
|
||||
if response.has_header('Content-Encoding') or is_js:
|
||||
return response
|
||||
|
||||
ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
|
||||
|
@ -2,12 +2,15 @@
|
||||
The "contrib" add-ons
|
||||
=====================
|
||||
|
||||
Django aims to follow Python's "batteries included" philosophy. It ships with a
|
||||
variety of extra, optional tools that solve common Web-development problems.
|
||||
Django aims to follow Python's `"batteries included" philosophy`_. It ships
|
||||
with a variety of extra, optional tools that solve common Web-development
|
||||
problems.
|
||||
|
||||
This code lives in ``django/contrib`` in the Django distribution. Here's a
|
||||
rundown of the packages in ``contrib``:
|
||||
|
||||
.. _"batteries included" philosophy: http://docs.python.org/tut/node12.html#batteries-included
|
||||
|
||||
admin
|
||||
=====
|
||||
|
||||
|
@ -578,6 +578,9 @@ related ``Person`` *and* the related ``City``::
|
||||
p = b.author # Hits the database.
|
||||
c = p.hometown # Hits the database.
|
||||
|
||||
Note that ``select_related()`` does not follow foreign keys that have
|
||||
``null=True``.
|
||||
|
||||
``extra(select=None, where=None, params=None, tables=None)``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -620,13 +620,10 @@ like to make should be possible by editing the stylesheet. We've got a
|
||||
How do I create users without having to edit password hashes?
|
||||
-------------------------------------------------------------
|
||||
|
||||
We don't recommend you create users via the admin interface, because at the
|
||||
moment it requires you to edit password hashes manually. (Passwords are hashed
|
||||
using one-way hash algorithms for security; there's currently no Web interface
|
||||
for changing passwords by entering the actual password rather than the hash.)
|
||||
If you'd like to use the admin site to create users, upgrade to the Django
|
||||
development version, where this problem was fixed on Aug. 4, 2006.
|
||||
|
||||
To create a user, you'll have to use the Python API. See `creating users`_ for
|
||||
full info.
|
||||
You can also use the Python API. See `creating users`_ for full info.
|
||||
|
||||
.. _creating users: http://www.djangoproject.com/documentation/authentication/#creating-users
|
||||
|
||||
|
@ -263,12 +263,12 @@ Here's the example URLconf from the `Django overview`_::
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r'^articles/(\d{4})/$', 'myproject.news.views.year_archive'),
|
||||
(r'^articles/(\d{4})/(\d{2})/$', 'myproject.news.views.month_archive'),
|
||||
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'myproject.news.views.article_detail'),
|
||||
(r'^articles/(\d{4})/$', 'mysite.news.views.year_archive'),
|
||||
(r'^articles/(\d{4})/(\d{2})/$', 'mysite.news.views.month_archive'),
|
||||
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.news.views.article_detail'),
|
||||
)
|
||||
|
||||
In this example, each view has a common prefix -- ``'myproject.news.views'``.
|
||||
In this example, each view has a common prefix -- ``'mysite.news.views'``.
|
||||
Instead of typing that out for each entry in ``urlpatterns``, you can use the
|
||||
first argument to the ``patterns()`` function to specify a prefix to apply to
|
||||
each view function.
|
||||
@ -277,7 +277,7 @@ With this in mind, the above example can be written more concisely as::
|
||||
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('myproject.news.views',
|
||||
urlpatterns = patterns('mysite.news.views',
|
||||
(r'^articles/(\d{4})/$', 'year_archive'),
|
||||
(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
|
||||
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
|
||||
@ -389,3 +389,45 @@ to pass metadata and options to views.
|
||||
|
||||
.. _generic views: http://www.djangoproject.com/documentation/generic_views/
|
||||
.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
|
||||
|
||||
Passing extra options to ``include()``
|
||||
--------------------------------------
|
||||
|
||||
**New in the Django development version.**
|
||||
|
||||
Similarly, you can pass extra options to ``include()``. When you pass extra
|
||||
options to ``include()``, *each* line in the included URLconf will be passed
|
||||
the extra options.
|
||||
|
||||
For example, these two URLconf sets are functionally identical:
|
||||
|
||||
Set one::
|
||||
|
||||
# main.py
|
||||
urlpatterns = patterns('',
|
||||
(r'^blog/', include('inner'), {'blogid': 3}),
|
||||
)
|
||||
|
||||
# inner.py
|
||||
urlpatterns = patterns('',
|
||||
(r'^archive/$', 'mysite.views.archive'),
|
||||
(r'^about/$', 'mysite.views.about'),
|
||||
)
|
||||
|
||||
Set two::
|
||||
|
||||
# main.py
|
||||
urlpatterns = patterns('',
|
||||
(r'^blog/', include('inner')),
|
||||
)
|
||||
|
||||
# inner.py
|
||||
urlpatterns = patterns('',
|
||||
(r'^archive/$', 'mysite.views.archive', {'blogid': 3}),
|
||||
(r'^about/$', 'mysite.views.about', {'blogid': 3}),
|
||||
)
|
||||
|
||||
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
|
||||
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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user