mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +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
|
Clint Ecker
|
||||||
gandalf@owca.info
|
gandalf@owca.info
|
||||||
Baishampayan Ghose
|
Baishampayan Ghose
|
||||||
|
martin.glueck@gmail.com
|
||||||
|
Simon Greenhill <dev@simon.net.nz>
|
||||||
Espen Grindhaug <http://grindhaug.org/>
|
Espen Grindhaug <http://grindhaug.org/>
|
||||||
Brant Harris
|
Brant Harris
|
||||||
hipertracker@gmail.com
|
hipertracker@gmail.com
|
||||||
|
Binary file not shown.
@ -141,6 +141,7 @@ msgid "score date"
|
|||||||
msgstr "счёт времени"
|
msgstr "счёт времени"
|
||||||
|
|
||||||
#: contrib/comments/models.py:237
|
#: contrib/comments/models.py:237
|
||||||
|
#, fuzzy
|
||||||
msgid "karma score"
|
msgid "karma score"
|
||||||
msgstr "Карма счёт"
|
msgstr "Карма счёт"
|
||||||
|
|
||||||
@ -735,7 +736,7 @@ msgstr "К сожалению, запрашиваемая вами страни
|
|||||||
#: contrib/admin/templates/admin/index.html:17
|
#: contrib/admin/templates/admin/index.html:17
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Models available in the %(name)s application."
|
msgid "Models available in the %(name)s application."
|
||||||
msgstr "Модели доступны в %(name)s приложении."
|
msgstr "Модели доступны в %(name) приложении."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:28
|
#: contrib/admin/templates/admin/index.html:28
|
||||||
#: contrib/admin/templates/admin/change_form.html:15
|
#: contrib/admin/templates/admin/change_form.html:15
|
||||||
|
@ -10,8 +10,10 @@ include = lambda urlconf_module: [urlconf_module]
|
|||||||
def patterns(prefix, *tuples):
|
def patterns(prefix, *tuples):
|
||||||
pattern_list = []
|
pattern_list = []
|
||||||
for t in tuples:
|
for t in tuples:
|
||||||
if type(t[1]) == list:
|
regex, view_or_include = t[:2]
|
||||||
pattern_list.append(RegexURLResolver(t[0], t[1][0]))
|
default_kwargs = t[2:]
|
||||||
|
if type(view_or_include) == list:
|
||||||
|
pattern_list.append(RegexURLResolver(regex, view_or_include[0], *default_kwargs))
|
||||||
else:
|
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
|
return pattern_list
|
||||||
|
@ -8,7 +8,9 @@ var DateTimeShortcuts = {
|
|||||||
clockInputs: [],
|
clockInputs: [],
|
||||||
calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
|
calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
|
||||||
calendarDivName2: 'calendarin', // name of <div> that contains calendar
|
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
|
clockDivName: 'clockbox', // name of clock <div> that gets toggled
|
||||||
|
clockLinkName: 'clocklink', // name of the link that is used to toggle
|
||||||
admin_media_prefix: '',
|
admin_media_prefix: '',
|
||||||
init: function() {
|
init: function() {
|
||||||
// Deduce admin_media_prefix by looking at the <script>s in the
|
// 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')));
|
now_link.appendChild(document.createTextNode(gettext('Now')));
|
||||||
var clock_link = document.createElement('a');
|
var clock_link = document.createElement('a');
|
||||||
clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
|
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'));
|
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(document.createTextNode('\240'));
|
||||||
shortcuts_span.appendChild(now_link);
|
shortcuts_span.appendChild(now_link);
|
||||||
@ -69,17 +72,6 @@ var DateTimeShortcuts = {
|
|||||||
var clock_box = document.createElement('div');
|
var clock_box = document.createElement('div');
|
||||||
clock_box.style.display = 'none';
|
clock_box.style.display = 'none';
|
||||||
clock_box.style.position = 'absolute';
|
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.className = 'clockbox module';
|
||||||
clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
|
clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
|
||||||
document.body.appendChild(clock_box);
|
document.body.appendChild(clock_box);
|
||||||
@ -98,7 +90,25 @@ var DateTimeShortcuts = {
|
|||||||
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
|
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
|
||||||
},
|
},
|
||||||
openClock: function(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; });
|
addEvent(window, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
|
||||||
},
|
},
|
||||||
dismissClock: function(num) {
|
dismissClock: function(num) {
|
||||||
@ -123,6 +133,7 @@ var DateTimeShortcuts = {
|
|||||||
today_link.appendChild(document.createTextNode(gettext('Today')));
|
today_link.appendChild(document.createTextNode(gettext('Today')));
|
||||||
var cal_link = document.createElement('a');
|
var cal_link = document.createElement('a');
|
||||||
cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
|
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'));
|
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(document.createTextNode('\240'));
|
||||||
shortcuts_span.appendChild(today_link);
|
shortcuts_span.appendChild(today_link);
|
||||||
@ -149,18 +160,6 @@ var DateTimeShortcuts = {
|
|||||||
var cal_box = document.createElement('div');
|
var cal_box = document.createElement('div');
|
||||||
cal_box.style.display = 'none';
|
cal_box.style.display = 'none';
|
||||||
cal_box.style.position = 'absolute';
|
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.className = 'calendarbox module';
|
||||||
cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
|
cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
|
||||||
document.body.appendChild(cal_box);
|
document.body.appendChild(cal_box);
|
||||||
@ -195,7 +194,24 @@ var DateTimeShortcuts = {
|
|||||||
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
|
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
|
||||||
},
|
},
|
||||||
openCalendar: function(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; });
|
addEvent(window, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
|
||||||
},
|
},
|
||||||
dismissCalendar: function(num) {
|
dismissCalendar: function(num) {
|
||||||
|
@ -11,7 +11,7 @@ function showRelatedObjectLookupPopup(triggeringLink) {
|
|||||||
} else {
|
} else {
|
||||||
href = triggeringLink.href + '?pop=1';
|
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();
|
win.focus();
|
||||||
return false;
|
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/$', 'django.views.admin.doc.template_index'),
|
||||||
('^doc/templates/(?P<template>.*)/$', 'django.contrib.admin.views.doc.template_detail'),
|
('^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
|
# Add/change/delete/history
|
||||||
('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'),
|
('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'),
|
||||||
('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
|
('^([^/]+)/([^/]+)/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.core import validators
|
||||||
from django import forms
|
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):
|
class AuthenticationForm(forms.Manipulator):
|
||||||
"""
|
"""
|
||||||
Base class for authenticating users. Extend this to get a form that accepts
|
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)
|
f = opts.get_field(fn)
|
||||||
except models.FieldDoesNotExist:
|
except models.FieldDoesNotExist:
|
||||||
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
|
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.
|
# Check ordering attribute.
|
||||||
if opts.ordering:
|
if opts.ordering:
|
||||||
|
@ -130,12 +130,13 @@ class RegexURLPattern(object):
|
|||||||
return reverse_helper(self.regex, *args, **kwargs)
|
return reverse_helper(self.regex, *args, **kwargs)
|
||||||
|
|
||||||
class RegexURLResolver(object):
|
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.
|
# regex is a string representing a regular expression.
|
||||||
# urlconf_name is a string representing the module containing urlconfs.
|
# urlconf_name is a string representing the module containing urlconfs.
|
||||||
self.regex = re.compile(regex)
|
self.regex = re.compile(regex)
|
||||||
self.urlconf_name = urlconf_name
|
self.urlconf_name = urlconf_name
|
||||||
self.callback = None
|
self.callback = None
|
||||||
|
self.default_kwargs = default_kwargs or {}
|
||||||
|
|
||||||
def resolve(self, path):
|
def resolve(self, path):
|
||||||
tried = []
|
tried = []
|
||||||
@ -149,7 +150,8 @@ class RegexURLResolver(object):
|
|||||||
tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']])
|
tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']])
|
||||||
else:
|
else:
|
||||||
if sub_match:
|
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)
|
tried.append(pattern.regex.pattern)
|
||||||
raise Resolver404, {'tried': tried, 'path': new_path}
|
raise Resolver404, {'tried': tried, 'path': new_path}
|
||||||
|
|
||||||
|
@ -137,9 +137,12 @@ class SchemaBuilder(object):
|
|||||||
r_col = f.column
|
r_col = f.column
|
||||||
table = opts.db_table
|
table = opts.db_table
|
||||||
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
|
||||||
|
# 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);' % \
|
sql = style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
|
||||||
(quote_name(table),
|
(quote_name(table), quote_name(r_name),
|
||||||
quote_name('%s_referencing_%s_%s' % (r_col, r_table, col)),
|
|
||||||
quote_name(r_col), quote_name(r_table), quote_name(col))
|
quote_name(r_col), quote_name(r_table), quote_name(col))
|
||||||
pending.setdefault(rel_class, []).append(
|
pending.setdefault(rel_class, []).append(
|
||||||
BoundStatement(sql, db.connection))
|
BoundStatement(sql, db.connection))
|
||||||
|
@ -289,8 +289,11 @@ class Field(object):
|
|||||||
if self.choices:
|
if self.choices:
|
||||||
return first_choice + list(self.choices)
|
return first_choice + list(self.choices)
|
||||||
rel_model = self.rel.to
|
rel_model = self.rel.to
|
||||||
return first_choice + [(x._get_pk_val(), str(x))
|
if hasattr(self.rel, 'get_related_field'):
|
||||||
for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
|
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):
|
def get_choices_default(self):
|
||||||
if self.radio_admin:
|
if self.radio_admin:
|
||||||
|
@ -25,7 +25,7 @@ def add_lookup(rel_cls, field):
|
|||||||
key = (module, name)
|
key = (module, name)
|
||||||
# Has the model already been loaded?
|
# Has the model already been loaded?
|
||||||
# If so, resolve the string reference right away
|
# 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:
|
if model:
|
||||||
field.rel.to = model
|
field.rel.to = model
|
||||||
field.do_related_class(model, rel_cls)
|
field.do_related_class(model, rel_cls)
|
||||||
|
@ -12,7 +12,11 @@ class GZipMiddleware(object):
|
|||||||
"""
|
"""
|
||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
patch_vary_headers(response, ('Accept-Encoding',))
|
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
|
return response
|
||||||
|
|
||||||
ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
|
ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
The "contrib" add-ons
|
The "contrib" add-ons
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Django aims to follow Python's "batteries included" philosophy. It ships with a
|
Django aims to follow Python's `"batteries included" philosophy`_. It ships
|
||||||
variety of extra, optional tools that solve common Web-development problems.
|
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
|
This code lives in ``django/contrib`` in the Django distribution. Here's a
|
||||||
rundown of the packages in ``contrib``:
|
rundown of the packages in ``contrib``:
|
||||||
|
|
||||||
|
.. _"batteries included" philosophy: http://docs.python.org/tut/node12.html#batteries-included
|
||||||
|
|
||||||
admin
|
admin
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
@ -578,6 +578,9 @@ related ``Person`` *and* the related ``City``::
|
|||||||
p = b.author # Hits the database.
|
p = b.author # Hits the database.
|
||||||
c = p.hometown # 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)``
|
``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?
|
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
|
If you'd like to use the admin site to create users, upgrade to the Django
|
||||||
moment it requires you to edit password hashes manually. (Passwords are hashed
|
development version, where this problem was fixed on Aug. 4, 2006.
|
||||||
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.)
|
|
||||||
|
|
||||||
To create a user, you'll have to use the Python API. See `creating users`_ for
|
You can also use the Python API. See `creating users`_ for full info.
|
||||||
full info.
|
|
||||||
|
|
||||||
.. _creating users: http://www.djangoproject.com/documentation/authentication/#creating-users
|
.. _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 *
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
(r'^articles/(\d{4})/$', 'myproject.news.views.year_archive'),
|
(r'^articles/(\d{4})/$', 'mysite.news.views.year_archive'),
|
||||||
(r'^articles/(\d{4})/(\d{2})/$', 'myproject.news.views.month_archive'),
|
(r'^articles/(\d{4})/(\d{2})/$', 'mysite.news.views.month_archive'),
|
||||||
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'myproject.news.views.article_detail'),
|
(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
|
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
|
first argument to the ``patterns()`` function to specify a prefix to apply to
|
||||||
each view function.
|
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 *
|
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})/$', 'year_archive'),
|
||||||
(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
|
(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
|
||||||
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
|
(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/
|
.. _generic views: http://www.djangoproject.com/documentation/generic_views/
|
||||||
.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
|
.. _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