1
0
mirror of https://github.com/django/django.git synced 2025-07-05 02:09:13 +00:00

[multi-db] Merge trunk to [3354]

git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@3355 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jason Pellerin 2006-07-16 23:11:33 +00:00
parent 49ce784805
commit 541ac3b990
47 changed files with 2403 additions and 191 deletions

View File

@ -72,6 +72,7 @@ answer newbie questions, and generally made Django that much better:
junzhang.jn@gmail.com
Russell Keith-Magee <freakboy@iinet.net.au>
Garth Kidd <http://www.deadlybloodyserious.com/>
kilian <kilian.cavalotti@lip6.fr>
Sune Kirkeby <http://ibofobi.dk/>
Cameron Knight (ckknight)
Bruce Kroeze <http://coderseye.com/>

View File

@ -36,6 +36,7 @@ LANGUAGE_CODE = 'en-us'
# Languages we provide translations for, out of the box. The language name
# should be the utf-8 encoded local name for the language.
LANGUAGES = (
('ar', gettext_noop('Arabic')),
('bn', gettext_noop('Bengali')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
@ -67,7 +68,7 @@ LANGUAGES = (
)
# Languages using BiDi (right-to-left) layout
LANGUAGES_BIDI = ("he",)
LANGUAGES_BIDI = ("he", "ar")
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,110 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: Django SVN\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2006-07-06 23:50+0300\n"
"Last-Translator: Ahmad Alhashemi <ahmad@ahmadh.com>\n"
"Language-Team: Ahmad Alhashemi <trans@ahmadh.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Arabic\n"
"X-Poedit-Country: Kuwait\n"
"X-Poedit-SourceCharset: utf-8\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "%s متوفرة"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "اختيار الكل"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "إضافة"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "حذف"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "%s اختيرت"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "حدد خيارك أو خياراتك واضغط"
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "مسح الكل"
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
msgid "January February March April May June July August September October November December"
msgstr "يناير فبراير مارس إبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "الأحد الأثنين الثلاثاء الأربعاء الخميس الجمعة السبت"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "أ أ ث أ خ ج س"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
msgstr "الآن"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
msgid "Clock"
msgstr "الساعة"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
msgid "Choose a time"
msgstr "اختر وقتا ما"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Midnight"
msgstr "منتصف الليل"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
msgstr "6 ص."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
msgstr "الظهر"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
msgid "Cancel"
msgstr "الغاء"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
msgid "Today"
msgstr "اليوم"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
msgid "Calendar"
msgstr "التقويم"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
msgid "Yesterday"
msgstr "يوم أمس"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "الغد"

Binary file not shown.

View File

@ -26,7 +26,7 @@
{% block nav-global %}{% endblock %}
</div>
<!-- END Header -->
{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} &rsaquo; {{ title }}{% endif %}</div>{% endblock %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} &rsaquo; {{ title|escape }}{% endif %}</div>{% endblock %}
{% endif %}
{% if messages %}
@ -36,7 +36,7 @@
<!-- Content -->
<div id="content" class="{% block coltype %}colM{% endblock %}">
{% block pretitle %}{% endblock %}
{% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
{% block content_title %}{% if title %}<h1>{{ title|escape }}</h1>{% endif %}{% endblock %}
{% block content %}{{ content }}{% endblock %}
{% block sidebar %}{% endblock %}
<br class="clear" />

View File

@ -1,7 +1,7 @@
{% extends "admin/base.html" %}
{% load i18n %}
{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}
{% block title %}{{ title|escape }} | {% trans 'Django site admin' %}{% endblock %}
{% block branding %}
<h1 id="site-name">{% trans 'Django administration' %}</h1>

View File

@ -11,8 +11,8 @@
{% block breadcrumbs %}{% if not is_popup %}
<div class="breadcrumbs">
<a href="../../../">{% trans "Home" %}</a> &rsaquo;
<a href="../">{{ opts.verbose_name_plural|capfirst }}</a> &rsaquo;
{% if add %}{% trans "Add" %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %}
<a href="../">{{ opts.verbose_name_plural|capfirst|escape }}</a> &rsaquo;
{% if add %}{% trans "Add" %} {{ opts.verbose_name|escape }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %}
</div>
{% endif %}{% endblock %}
{% block content %}<div id="content-main">

View File

@ -3,12 +3,12 @@
{% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %}
{% block bodyclass %}change-list{% endblock %}
{% block userlinks %}<a href="../../doc/">{% trans 'Documentation' %}</a> / <a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> &rsaquo; {{ cl.opts.verbose_name_plural|capfirst }}</div>{% endblock %}{% endif %}
{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> &rsaquo; {{ cl.opts.verbose_name_plural|capfirst|escape }}</div>{% endblock %}{% endif %}
{% block coltype %}flex{% endblock %}
{% block content %}
<div id="content-main">
{% if has_add_permission %}
<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name|escape as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
{% endif %}
<div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
{% block search %}{% search_form cl %}{% endblock %}

View File

@ -1,9 +1,9 @@
{% if show %}
<div class="xfull">
<ul class="toplinks">
{% if back %}<li class="date-back"><a href="{{ back.link }}">&lsaquo; {{ back.title }}</a></li>{% endif %}
{% if back %}<li class="date-back"><a href="{{ back.link }}">&lsaquo; {{ back.title|escape }}</a></li>{% endif %}
{% for choice in choices %}
<li> {% if choice.link %}<a href="{{ choice.link }}">{% endif %}{{ choice.title }}{% if choice.link %}</a>{% endif %}</li>
<li> {% if choice.link %}<a href="{{ choice.link }}">{% endif %}{{ choice.title|escape }}{% if choice.link %}</a>{% endif %}</li>
{% endfor %}
</ul><br class="clear" />
</div>

View File

@ -4,21 +4,21 @@
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="../../../../">{% trans "Home" %}</a> &rsaquo;
<a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> &rsaquo;
<a href="../">{{ object|striptags|truncatewords:"18" }}</a> &rsaquo;
<a href="../../">{{ opts.verbose_name_plural|capfirst|escape }}</a> &rsaquo;
<a href="../">{{ object|escape|truncatewords:"18" }}</a> &rsaquo;
{% trans 'Delete' %}
</div>
{% endblock %}
{% block content %}
{% if perms_lacking %}
<p>{% blocktrans %}Deleting the {{ object_name }} '{{ object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}</p>
<p>{% blocktrans with object|escape as escaped_object %}Deleting the {{ object_name }} '{{ escaped_object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}</p>
<ul>
{% for obj in perms_lacking %}
<li>{{ obj }}</li>
<li>{{ obj|escape }}</li>
{% endfor %}
</ul>
{% else %}
<p>{% blocktrans %}Are you sure you want to delete the {{ object_name }} "{{ object }}"? All of the following related items will be deleted:{% endblocktrans %}</p>
<p>{% blocktrans with object|escape as escaped_object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktrans %}</p>
<ul>{{ deleted_objects|unordered_list }}</ul>
<form action="" method="post">
<div>

View File

@ -1,7 +1,7 @@
{% load admin_modify %}
<fieldset class="module aligned">
{% for fcw in bound_related_object.form_field_collection_wrappers %}
<h2>{{ bound_related_object.relation.opts.verbose_name|capfirst }}&nbsp;#{{ forloop.counter }}</h2>
<h2>{{ bound_related_object.relation.opts.verbose_name|capfirst|escape }}&nbsp;#{{ forloop.counter }}</h2>
{% if bound_related_object.show_url %}{% if fcw.obj.original %}
<p><a href="/r/{{ fcw.obj.original.content_type_id }}/{{ fcw.obj.original.id }}/">View on site</a></p>
{% endif %}{% endif %}

View File

@ -1,10 +1,10 @@
{% load admin_modify %}
<fieldset class="module">
<h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst }}</h2><table>
<h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst|escape }}</h2><table>
<thead><tr>
{% for fw in bound_related_object.field_wrapper_list %}
{% if fw.needs_header %}
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst }}</th>
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th>
{% endif %}
{% endfor %}
{% for fcw in bound_related_object.form_field_collection_wrappers %}

View File

@ -1,5 +1,5 @@
{% load i18n %}
<h3>{% blocktrans %} By {{ title }} {% endblocktrans %}</h3>
<h3>{% blocktrans with title|escape as filter_title %} By {{ filter_title }} {% endblocktrans %}</h3>
<ul>
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>

View File

@ -19,9 +19,9 @@
{% for model in app.models %}
<tr>
{% if model.perms.change %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name|escape }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
<th scope="row">{{ model.name|escape }}</th>
{% endif %}
{% if model.perms.add %}
@ -58,7 +58,7 @@
{% else %}
<ul class="actionlist">
{% for entry in admin_log %}
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.content_type.name|capfirst }}</span></li>
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.content_type.name|capfirst|escape }}</span></li>
{% endfor %}
</ul>
{% endif %}

View File

@ -1,7 +1,7 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> &rsaquo; {{ title }}</div>{% endblock %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> &rsaquo; {{ title|escape }}</div>{% endblock %}
{% block content %}

View File

@ -2,7 +2,7 @@
{% load i18n %}
{% block userlinks %}<a href="../../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> &rsaquo; <a href="../../">{{ module_name }}</a> &rsaquo; <a href="../">{{ object|truncatewords:"18" }}</a> &rsaquo; {% trans 'History' %}</div>
<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> &rsaquo; <a href="../../">{{ module_name|escape }}</a> &rsaquo; <a href="../">{{ object|escape|truncatewords:"18" }}</a> &rsaquo; {% trans 'History' %}</div>
{% endblock %}
{% block content %}

View File

@ -6,6 +6,6 @@
{% paginator_number cl i %}
{% endfor %}
{% endif %}
{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %}
{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name|escape }}{% else %}{{ cl.opts.verbose_name_plural|escape }}{% endifequal %}
{% if show_all_url %}&nbsp;&nbsp;<a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
</p>

View File

@ -9,13 +9,13 @@
</style>
{% endblock %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> &rsaquo; <a href="../../">Documentation</a> &rsaquo; <a href="../">Models</a> &rsaquo; {{ name }}</div>{% endblock %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> &rsaquo; <a href="../../">Documentation</a> &rsaquo; <a href="../">Models</a> &rsaquo; {{ name|escape }}</div>{% endblock %}
{% block title %}Model: {{ name }}{% endblock %}
{% block title %}Model: {{ name|escape }}{% endblock %}
{% block content %}
<div id="content-main">
<h1>{{ summary }}</h1>
<h1>{{ summary|escape }}</h1>
{% if description %}
<p>{% filter escape|linebreaksbr %}{% trans description %}{% endfilter %}</p>
@ -35,7 +35,7 @@
<tr>
<td>{{ field.name }}</td>
<td>{{ field.data_type }}</td>
<td>{% if field.verbose %}{{ field.verbose }}{% endif %}{% if field.help_text %} - {{ field.help_text }}{% endif %}</td>
<td>{% if field.verbose %}{{ field.verbose|escape }}{% endif %}{% if field.help_text %} - {{ field.help_text|escape }}{% endif %}</td>
</tr>
{% endfor %}
</tbody>

View File

@ -1,19 +1,19 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> &rsaquo; <a href="../../">Documentation</a> &rsaquo; Templates &rsaquo; {{ name }}</div>{% endblock %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> &rsaquo; <a href="../../">Documentation</a> &rsaquo; Templates &rsaquo; {{ name|escape }}</div>{% endblock %}
{% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
{% block title %}Template: {{ name }}{% endblock %}
{% block title %}Template: {{ name|escape }}{% endblock %}
{% block content %}
<h1>Template: "{{ name }}"</h1>
<h1>Template: "{{ name|escape }}"</h1>
{% regroup templates|dictsort:"site_id" by site as templates_by_site %}
{% for group in templates_by_site %}
<h2>Search path for template "{{ name }}" on {{ group.grouper }}:</h2>
<h2>Search path for template "{{ name|escape }}" on {{ group.grouper }}:</h2>
<ol>
{% for template in group.list|dictsort:"order" %}
<li><code>{{ template.file }}</code>{% if not template.exists %} <em>(does not exist)</em>{% endif %}</li>
<li><code>{{ template.file|escape }}</code>{% if not template.exists %} <em>(does not exist)</em>{% endif %}</li>
{% endfor %}
</ol>
{% endfor %}

View File

@ -8,7 +8,7 @@
<h1>{{ name }}</h1>
<h2 class="subhead">{{ summary }}</h2>
<h2 class="subhead">{{ summary|escape }}</h2>
<p>{{ body }}</p>

View File

@ -1,4 +1,4 @@
{% load admin_modify i18n %}{% if bound_field.original_value %}
{% trans "Currently:" %} <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value }} </a><br />
{% trans "Currently:" %} <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value|escape }} </a><br />
{% trans "Change:" %}{% output_all bound_field.form_fields %}
{% else %} {% output_all bound_field.form_fields %} {% endif %}

View File

@ -15,6 +15,6 @@
{{ bound_field.original_value }}
{% endif %}
{% if bound_field.raw_id_admin %}
{% if bound_field.existing_display %}&nbsp;<strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}
{% if bound_field.existing_display %}&nbsp;<strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %}
{% endif %}
{% endif %}

View File

@ -1,2 +1,2 @@
{% if add %}{% include "widget/foreign.html" %}{% endif %}
{% if change %}{% if bound_field.existing_display %}&nbsp;<strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}{% endif %}
{% if change %}{% if bound_field.existing_display %}&nbsp;<strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %}{% endif %}

View File

@ -165,12 +165,14 @@ def items_for_result(cl, result):
result_repr = escape(str(field_val))
if result_repr == '':
result_repr = '&nbsp;'
if first: # First column is a special case
# If list_display_links not defined, add the link tag to the first field
if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links:
table_tag = {True:'th', False:'td'}[first]
first = False
url = cl.url_for_result(result)
result_id = str(getattr(result, pk)) # str() is needed in case of 23L (long ints)
yield ('<th%s><a href="%s"%s>%s</a></th>' % \
(row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr))
yield ('<%s%s><a href="%s"%s>%s</a></%s>' % \
(table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr, table_tag))
else:
yield ('<td%s>%s</td>' % (row_class, result_repr))

View File

@ -38,7 +38,7 @@ def authenticate(**credentials):
if user is None:
continue
# Annotate the user object with the path of the backend.
user.backend = str(backend.__class__)
user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
return user
def login(request, user):

View File

@ -239,7 +239,7 @@ class User(models.Model):
app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
model = models.get_model(app_label, model_name)
self._profile_cache = model._default_manager.get(user__id__exact=self.id)
except ImportError, ImproperlyConfigured:
except (ImportError, ImproperlyConfigured):
raise SiteProfileNotAvailable
return self._profile_cache

View File

@ -10,7 +10,7 @@ class FlatPage(models.Model):
content = models.TextField(_('content'))
enable_comments = models.BooleanField(_('enable comments'))
template_name = models.CharField(_('template name'), maxlength=70, blank=True,
help_text=_("Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'."))
help_text=_("Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'."))
registration_required = models.BooleanField(_('registration required'), help_text=_("If this is checked, only logged-in users will be able to view the page."))
sites = models.ManyToManyField(Site)
class Meta:

View File

@ -45,8 +45,8 @@ def disable_termcolors():
global style
style = dummy()
# Disable terminal coloring on Windows or if somebody's piping the output.
if sys.platform == 'win32' or not sys.stdout.isatty():
# Disable terminal coloring on Windows, Pocket PC, or if somebody's piping the output.
if sys.platform == 'win32' or sys.platform == 'Pocket PC' or not sys.stdout.isatty():
disable_termcolors()
# singleton representing the default connection
@ -847,6 +847,19 @@ def get_validation_errors(outfile, app=None):
else:
if isinstance(f, models.ManyToManyField):
e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn)
# list_display_links
if opts.admin.list_display_links and not opts.admin.list_display:
e.add(opts, '"admin.list_display" must be defined for "admin.list_display_links" to be used.')
if not isinstance(opts.admin.list_display_links, (list, tuple)):
e.add(opts, '"admin.list_display_links", if given, must be set to a list or tuple.')
else:
for fn in opts.admin.list_display_links:
try:
f = opts.get_field(fn)
except models.FieldDoesNotExist:
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
if fn not in opts.admin.list_display:
e.add(opts, '"admin.list_display_links" refers to %r, which is not defined in "admin.list_display".' % fn)
# list_filter
if not isinstance(opts.admin.list_filter, (list, tuple)):
e.add(opts, '"admin.list_filter", if given, must be set to a list or tuple.')
@ -922,7 +935,7 @@ def _check_for_validation_errors(app=None):
sys.stderr.write(s.read())
sys.exit(1)
def runserver(addr, port):
def runserver(addr, port, use_reloader=True):
"Starts a lightweight Web server for development."
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
from django.core.handlers.wsgi import WSGIHandler
@ -956,9 +969,12 @@ def runserver(addr, port):
sys.exit(1)
except KeyboardInterrupt:
sys.exit(0)
if use_reloader:
from django.utils import autoreload
autoreload.main(inner_run)
runserver.args = '[optional port number, or ipaddr:port]'
else:
inner_run()
runserver.args = '[--noreload] [optional port number, or ipaddr:port]'
def createcachetable(tablename):
"Creates the table needed to use the SQL cache backend"
@ -1107,6 +1123,8 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
parser.add_option('--plain', action='store_true', dest='plain',
help='Tells Django to use plain Python, not IPython, for "shell" command.')
parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
help='Tells Django to NOT use the auto-reloader when running the development server.')
options, args = parser.parse_args(argv[1:])
# Take care of options.
@ -1162,7 +1180,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
addr, port = args[1].split(':')
except ValueError:
addr, port = '', args[1]
action_mapping[action](addr, port)
action_mapping[action](addr, port, options.use_reloader)
elif action == 'runfcgi':
action_mapping[action](args[1:])
else:

View File

@ -23,7 +23,7 @@ ansi_datetime_re = re.compile('^%s %s$' % (_datere, _timere))
email_re = re.compile(
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$', re.IGNORECASE) # domain
r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain
integer_re = re.compile(r'^-?\d+$')
ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE)

View File

@ -46,7 +46,7 @@ def manipulator_valid_rel_key(f, self, field_data, all_data):
"Validates that the value is a valid foreign key"
klass = f.rel.to
try:
klass._default_manager.get(pk=field_data)
klass._default_manager.get(**{f.rel.field_name: field_data})
except klass.DoesNotExist:
raise validators.ValidationError, _("Please enter a valid %s.") % f.verbose_name

View File

@ -212,12 +212,13 @@ class Options(object):
return self._field_types[field_type]
class AdminOptions(object):
def __init__(self, fields=None, js=None, list_display=None, list_filter=None,
def __init__(self, fields=None, js=None, list_display=None, list_display_links=None, list_filter=None,
date_hierarchy=None, save_as=False, ordering=None, search_fields=None,
save_on_top=False, list_select_related=False, manager=None, list_per_page=100):
self.fields = fields
self.js = js or []
self.list_display = list_display or ['__str__']
self.list_display_links = list_display_links or []
self.list_filter = list_filter or []
self.date_hierarchy = date_hierarchy
self.save_as, self.ordering = save_as, ordering

View File

@ -85,8 +85,8 @@ class QuerySet(object):
self._where = [] # List of extra WHERE clauses to use.
self._params = [] # List of params to use for extra WHERE clauses.
self._tables = [] # List of extra tables to use.
self._offset = None # OFFSET clause
self._limit = None # LIMIT clause
self._offset = None # OFFSET clause.
self._limit = None # LIMIT clause.
self._result_cache = None
########################
@ -444,8 +444,7 @@ class QuerySet(object):
params = self._params[:]
# Convert self._filters into SQL.
tables2, joins2, where2, params2 = self._filters.get_sql(opts)
tables.extend(tables2)
joins2, where2, params2 = self._filters.get_sql(opts)
joins.update(joins2)
where.extend(where2)
params.extend(params2)
@ -580,16 +579,15 @@ class QOperator(object):
self.args = args
def get_sql(self, opts):
tables, joins, where, params = [], SortedDict(), [], []
joins, where, params = SortedDict(), [], []
for val in self.args:
tables2, joins2, where2, params2 = val.get_sql(opts)
tables.extend(tables2)
joins2, where2, params2 = val.get_sql(opts)
joins.update(joins2)
where.extend(where2)
params.extend(params2)
if where:
return tables, joins, ['(%s)' % self.operator.join(where)], params
return tables, joins, [], params
return joins, ['(%s)' % self.operator.join(where)], params
return joins, [], params
class QAnd(QOperator):
"Encapsulates a combined query that uses 'AND'."
@ -640,9 +638,9 @@ class QNot(Q):
self.q = q
def get_sql(self, opts):
tables, joins, where, params = self.q.get_sql(opts)
joins, where, params = self.q.get_sql(opts)
where2 = ['(NOT (%s))' % " AND ".join(where)]
return tables, joins, where2, params
return joins, where2, params
def get_where_clause(opts, lookup_type, table_prefix, field_name, value):
backend = opts.connection_info.backend
@ -682,20 +680,20 @@ def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen)
place) for select_related queries.
"""
backend = opts.connection_info.backend
qn = backend.quote_name
for f in opts.fields:
if f.rel and not f.null:
db_table = f.rel.to._meta.db_table
if db_table not in cache_tables_seen:
tables.append(backend.quote_name(db_table))
tables.append(qn(db_table))
else: # The table was already seen, so give it a table alias.
new_prefix = '%s%s' % (db_table, len(cache_tables_seen))
tables.append('%s %s' % (backend.quote_name(db_table), backend.quote_name(new_prefix)))
tables.append('%s %s' % (qn(db_table), qn(new_prefix)))
db_table = new_prefix
cache_tables_seen.append(db_table)
where.append('%s.%s = %s.%s' % \
(backend.quote_name(old_prefix), backend.quote_name(f.column),
backend.quote_name(db_table), backend.quote_name(f.rel.get_related_field().column)))
select.extend(['%s.%s' % (backend.quote_name(db_table), backend.quote_name(f2.column)) for f2 in f.rel.to._meta.fields])
(qn(old_prefix), qn(f.column), qn(db_table), qn(f.rel.get_related_field().column)))
select.extend(['%s.%s' % (qn(db_table), qn(f2.column)) for f2 in f.rel.to._meta.fields])
fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen)
def parse_lookup(kwarg_items, opts):
@ -719,39 +717,38 @@ def parse_lookup(kwarg_items, opts):
# At present, this method only every returns INNER JOINs; the option is
# there for others to implement custom Q()s, etc that return other join
# types.
tables, joins, where, params = [], SortedDict(), [], []
joins, where, params = SortedDict(), [], []
for kwarg, value in kwarg_items:
if value is not None:
path = kwarg.split(LOOKUP_SEPARATOR)
# Extract the last elements of the kwarg.
# The very-last is the clause (equals, like, etc).
# The second-last is the table column on which the clause is
# The very-last is the lookup_type (equals, like, etc).
# The second-last is the table column on which the lookup_type is
# to be performed.
# The exceptions to this are:
# 1) "pk", which is an implicit id__exact;
# if we find "pk", make the clause "exact', and insert
# if we find "pk", make the lookup_type "exact', and insert
# a dummy name of None, which we will replace when
# we know which table column to grab as the primary key.
# 2) If there is only one part, or the last part is not a query
# term, assume that the query is an __exact
clause = path.pop()
if clause == 'pk':
clause = 'exact'
lookup_type = path.pop()
if lookup_type == 'pk':
lookup_type = 'exact'
path.append(None)
elif len(path) == 0 or clause not in QUERY_TERMS:
path.append(clause)
clause = 'exact'
elif len(path) == 0 or lookup_type not in QUERY_TERMS:
path.append(lookup_type)
lookup_type = 'exact'
if len(path) < 1:
raise TypeError, "Cannot parse keyword query %r" % kwarg
tables2, joins2, where2, params2 = lookup_inner(path, clause, value, opts, opts.db_table, None)
tables.extend(tables2)
joins2, where2, params2 = lookup_inner(path, lookup_type, value, opts, opts.db_table, None)
joins.update(joins2)
where.extend(where2)
params.extend(params2)
return tables, joins, where, params
return joins, where, params
class FieldFound(Exception):
"Exception used to short circuit field-finding operations."
@ -770,8 +767,8 @@ def find_field(name, field_list, related_query):
return None
return matches[0]
def lookup_inner(path, clause, value, opts, table, column):
tables, joins, where, params = [], SortedDict(), [], []
def lookup_inner(path, lookup_type, value, opts, table, column):
joins, where, params = SortedDict(), [], []
current_opts = opts
current_table = table
current_column = column
@ -780,6 +777,7 @@ def lookup_inner(path, clause, value, opts, table, column):
info = current_opts.connection_info
backend = info.backend
connection = info.connection
qn = backend.quote_name
name = path.pop(0)
# Has the primary key been requested? If so, expand it out
@ -792,7 +790,7 @@ def lookup_inner(path, clause, value, opts, table, column):
# Does the name belong to a defined many-to-many field?
field = find_field(name, current_opts.many_to_many, False)
if field:
new_table = current_table + LOOKUP_SEPARATOR + name
new_table = current_table + '__' + name
new_opts = field.rel.to._meta
new_column = new_opts.pk.column
@ -809,7 +807,7 @@ def lookup_inner(path, clause, value, opts, table, column):
# Does the name belong to a reverse defined many-to-many field?
field = find_field(name, current_opts.get_all_related_many_to_many_objects(), True)
if field:
new_table = current_table + LOOKUP_SEPARATOR + name
new_table = current_table + '__' + name
new_opts = field.opts
new_column = new_opts.pk.column
@ -826,7 +824,7 @@ def lookup_inner(path, clause, value, opts, table, column):
# Does the name belong to a one-to-many field?
field = find_field(name, current_opts.get_all_related_objects(), True)
if field:
new_table = table + LOOKUP_SEPARATOR + name
new_table = table + '__' + name
new_opts = field.opts
new_column = field.field.column
join_column = opts.pk.column
@ -840,7 +838,7 @@ def lookup_inner(path, clause, value, opts, table, column):
field = find_field(name, current_opts.fields, False)
if field:
if field.rel: # One-to-One/Many-to-one field
new_table = current_table + LOOKUP_SEPARATOR + name
new_table = current_table + '__' + name
new_opts = field.rel.to._meta
new_column = new_opts.pk.column
join_column = field.column
@ -849,54 +847,41 @@ def lookup_inner(path, clause, value, opts, table, column):
except FieldFound: # Match found, loop has been shortcut.
pass
except: # Any other exception; rethrow
raise
else: # No match found.
raise TypeError, "Cannot resolve keyword '%s' into field" % name
# Check to see if an intermediate join is required between current_table
# Check whether an intermediate join is required between current_table
# and new_table.
if intermediate_table:
joins[backend.quote_name(current_table)] = (
backend.quote_name(intermediate_table),
"LEFT OUTER JOIN",
"%s.%s = %s.%s" % \
(backend.quote_name(table),
backend.quote_name(current_opts.pk.column),
backend.quote_name(current_table),
backend.quote_name(intermediate_column))
joins[qn(current_table)] = (
qn(intermediate_table), "LEFT OUTER JOIN",
"%s.%s = %s.%s" % (qn(table), qn(current_opts.pk.column), qn(current_table), qn(intermediate_column))
)
if path:
# There are elements left in the path. More joins are required.
if len(path) == 1 and path[0] in (new_opts.pk.name, None) \
and clause in ('exact', 'isnull') and not join_required:
and lookup_type in ('exact', 'isnull') and not join_required:
# If the next and final name query is for a primary key,
# and the search is for isnull/exact, then the current
# (for N-1) or intermediate (for N-N) table can be used
# for the search - no need to join an extra table just
# for the search. No need to join an extra table just
# to check the primary key.
new_table = current_table
else:
# There are 1 or more name queries pending, and we have ruled out
# any shortcuts; therefore, a join is required.
joins[backend.quote_name(new_table)] = (
backend.quote_name(new_opts.db_table),
"INNER JOIN",
"%s.%s = %s.%s" %
(backend.quote_name(current_table),
backend.quote_name(join_column),
backend.quote_name(new_table),
backend.quote_name(new_column))
joins[qn(new_table)] = (
qn(new_opts.db_table), "INNER JOIN",
"%s.%s = %s.%s" % (qn(current_table), qn(join_column), qn(new_table), qn(new_column))
)
# If we have made the join, we don't need to tell subsequent
# recursive calls about the column name we joined on.
join_column = None
# There are name queries remaining. Recurse deeper.
tables2, joins2, where2, params2 = lookup_inner(path, clause, value, new_opts, new_table, join_column)
joins2, where2, params2 = lookup_inner(path, lookup_type, value, new_opts, new_table, join_column)
tables.extend(tables2)
joins.update(joins2)
where.extend(where2)
params.extend(params2)
@ -910,14 +895,9 @@ def lookup_inner(path, clause, value, opts, table, column):
# RelatedObject is from a 1-N relation.
# Join is required; query operates on joined table.
column = new_opts.pk.name
joins[backend.quote_name(new_table)] = (
backend.quote_name(new_opts.db_table),
"INNER JOIN",
"%s.%s = %s.%s" %
(backend.quote_name(current_table),
backend.quote_name(join_column),
backend.quote_name(new_table),
backend.quote_name(new_column))
joins[qn(new_table)] = (
qn(new_opts.db_table), "INNER JOIN",
"%s.%s = %s.%s" % (qn(current_table), qn(join_column), qn(new_table), qn(new_column))
)
current_table = new_table
else:
@ -929,7 +909,7 @@ def lookup_inner(path, clause, value, opts, table, column):
# Last query term is a related object from an N-N relation.
# Join from intermediate table is sufficient.
column = join_column
elif name == current_opts.pk.name and clause in ('exact', 'isnull') and current_column:
elif name == current_opts.pk.name and lookup_type in ('exact', 'isnull') and current_column:
# Last query term is for a primary key. If previous iterations
# introduced a current/intermediate table that can be used to
# optimize the query, then use that table and column name.
@ -938,10 +918,10 @@ def lookup_inner(path, clause, value, opts, table, column):
# Last query term was a normal field.
column = field.column
where.append(get_where_clause(current_opts, clause, current_table + '.', column, value))
params.extend(field.get_db_prep_lookup(clause, value))
where.append(get_where_clause(current_opts, lookup_type, current_table + '.', column, value))
params.extend(field.get_db_prep_lookup(lookup_type, value))
return tables, joins, where, params
return joins, where, params
def delete_objects(seen_objs):
"Iterate through a list of seen classes, and remove any instances that are referred to"
@ -953,6 +933,7 @@ def delete_objects(seen_objs):
backend = info.backend
connection = info.connection
cursor = connection.cursor()
qn = backend.quote_name
seen_objs[cls] = seen_objs[cls].items()
seen_objs[cls].sort()
@ -965,24 +946,21 @@ def delete_objects(seen_objs):
for related in cls._meta.get_all_related_many_to_many_objects():
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
(backend.quote_name(related.field.m2m_db_table()),
backend.quote_name(related.field.m2m_reverse_name()),
(qn(related.field.m2m_db_table()),
qn(related.field.m2m_reverse_name()),
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
for f in cls._meta.many_to_many:
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
(backend.quote_name(f.m2m_db_table()),
backend.quote_name(f.m2m_column_name()),
(qn(f.m2m_db_table()), qn(f.m2m_column_name()),
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
for field in cls._meta.fields:
if field.rel and field.null and field.rel.to in seen_objs:
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
cursor.execute("UPDATE %s SET %s=NULL WHERE %s IN (%s)" % \
(backend.quote_name(cls._meta.db_table),
backend.quote_name(field.column),
backend.quote_name(cls._meta.pk.column),
(qn(cls._meta.db_table), qn(field.column), qn(cls._meta.pk.column),
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
@ -993,6 +971,7 @@ def delete_objects(seen_objs):
info = cls._meta.connection_info
backend = info.backend
connection = info.connection
qn = backend.quote_name
cursor = connection.cursor()
if connection not in dirty_conns:
dirty_conns.append(connection)
@ -1001,8 +980,7 @@ def delete_objects(seen_objs):
pk_list = [pk for pk,instance in seen_objs[cls]]
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
(backend.quote_name(cls._meta.db_table),
backend.quote_name(cls._meta.pk.column),
(qn(cls._meta.db_table), qn(cls._meta.pk.column),
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])

View File

@ -171,7 +171,7 @@ class Token(object):
self.contents[:20].replace('\n', ''))
def split_contents(self):
return smart_split(self.contents)
return list(smart_split(self.contents))
class Lexer(object):
def __init__(self, template_string, origin):
@ -758,7 +758,7 @@ class DebugVariableNode(VariableNode):
def generic_tag_compiler(params, defaults, name, node_class, parser, token):
"Returns a template.Node subclass."
bits = token.contents.split()[1:]
bits = token.split_contents()[1:]
bmax = len(params)
def_len = defaults and len(defaults) or 0
bmin = bmax - def_len

View File

@ -133,7 +133,7 @@ def wordwrap(value, arg):
"""
Wraps words at specified line length
Argument: number of words to wrap the text at.
Argument: number of characters to wrap the text at.
"""
from django.utils.text import wrap
return wrap(str(value), int(arg))

View File

@ -14,5 +14,14 @@ string_concat = lambda *strings: ''.join([str(el) for el in strings])
activate = lambda x: None
deactivate = install = lambda: None
get_language = lambda: settings.LANGUAGE_CODE
get_date_formats = lambda: settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT
get_partial_date_formats = lambda: settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT
get_language_bidi = lambda: settings.LANGUAGE_CODE in settings.LANGUAGES_BIDI
get_date_formats = lambda: (settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT)
get_partial_date_formats = lambda: (settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT)
check_for_language = lambda x: True
def to_locale(language):
p = language.find('-')
if p >= 0:
return language[:p].lower()+'_'+language[p+1:].upper()
else:
return language.lower()

View File

@ -224,6 +224,13 @@ block::
This will have {{ myvar }} inside.
{% endblocktrans %}
If you need to bind more than one expression inside a ``blocktrans`` tag,
separate the pieces with ``and``::
{% blocktrans with book|title as book_t and author|title as author_t %}
This is {{ book_t }} by {{ author_t }}
{% endblocktrans %}
To pluralize, specify both the singular and plural forms with the
``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and
``{% endblocktrans %}``. Example::
@ -306,7 +313,7 @@ marked for translation. It creates (or updates) a message file in the directory
``conf/locale``. In the ``de`` example, the file will be
``conf/locale/de/LC_MESSAGES/django.po``.
If run over your project source tree or your appliation source tree, it will
If run over your project source tree or your application source tree, it will
do the same, but the location of the locale directory is ``locale/LANG/LC_MESSAGES``
(note the missing ``conf`` prefix).
@ -349,7 +356,7 @@ A quick explanation:
Long messages are a special case. There, the first string directly after the
``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be
written over the next few lines as one string per line. Those strings are
directlyconcatenated. Don't forget trailing spaces within the strings;
directly concatenated. Don't forget trailing spaces within the strings;
otherwise, they'll be tacked together without whitespace!
.. admonition:: Mind your charset
@ -452,7 +459,7 @@ Notes:
``de``.
* Only languages listed in the `LANGUAGES setting`_ can be selected. If
you want to restrict the language selection to a subset of provided
languages (because your appliaction doesn't provide all those languages),
languages (because your application doesn't provide all those languages),
set ``LANGUAGES`` to a list of languages. For example::
LANGUAGES = (
@ -465,6 +472,30 @@ Notes:
en-us).
.. _LANGUAGES setting: http://www.djangoproject.com/documentation/settings/#languages
* If you define a custom ``LANGUAGES`` setting, as explained in the
previous bullet, it's OK to mark the languages as translation strings
-- but use a "dummy" ``gettext()`` function, not the one in
``django.utils.translation``. You should *never* import
``django.utils.translation`` from within your settings file, because that
module in itself depends on the settings, and that would cause a circular
import.
The solution is to use a "dummy" ``gettext()`` function. Here's a sample
settings file::
gettext = lambda s: s
LANGUAGES = (
('de', gettext('German')),
('en', gettext('English')),
)
With this arrangement, ``make-messages.py`` will still find and mark
these strings for translation, but the translation won't happen at
runtime -- so you'll have to remember to wrap the languages in the *real*
``gettext()`` in any code that uses ``LANGUAGES`` at runtime.
* The ``LocaleMiddleware`` can only select languages for which there is a
Django-provided base translation. If you want to provide translations
for your application that aren't already in the set of translations
@ -623,7 +654,7 @@ The ``javascript_catalog`` view
-------------------------------
The main solution to these problems is the ``javascript_catalog`` view, which
sends out a JavaScript code library with functions that mimick the ``gettext``
sends out a JavaScript code library with functions that mimic the ``gettext``
interface, plus an array of translation strings. Those translation strings are
taken from the application, project or Django core, according to what you
specify in either the {{{info_dict}}} or the URL.
@ -641,7 +672,7 @@ You hook it up like this::
Each string in ``packages`` should be in Python dotted-package syntax (the
same format as the strings in ``INSTALLED_APPS``) and should refer to a package
that contains a ``locale`` directory. If you specify multiple packages, all
those catalogs aremerged into one catalog. This is useful if you have
those catalogs are merged into one catalog. This is useful if you have
JavaScript that uses strings from different applications.
You can make the view dynamic by putting the packages into the URL pattern::

View File

@ -1225,6 +1225,33 @@ A few special cases to note about ``list_display``:
return self.birthday.strftime('%Y')[:3] + "0's"
decade_born_in.short_description = 'Birth decade'
``list_display_links``
----------------------
Set ``list_display_links`` to control which fields in ``list_display`` should
be linked to the "change" page for an object.
By default, the change list page will link the first column -- the first field
specified in ``list_display`` -- to the change page for each item. But
``list_display_links`` lets you change which columns are linked. Set
``list_display_links`` to a list or tuple of field names (in the same format as
``list_display``) to link.
``list_display_links`` can specify one or many field names. As long as the
field names appear in ``list_display``, Django doesn't care how many (or how
few) fields are linked. The only requirement is: If you want to use
``list_display_links``, you must define ``list_display``.
In this example, the ``first_name`` and ``last_name`` fields will be linked on
the change list page::
class Admin:
list_display = ('first_name', 'last_name', 'birthday')
list_display_links = ('first_name', 'last_name')
Finally, note that in order to use ``list_display_links``, you must define
``list_display``, too.
``list_filter``
---------------

View File

@ -501,6 +501,28 @@ specifies which languages are available for language selection. See the
Generally, the default value should suffice. Only set this setting if you want
to restrict language selection to a subset of the Django-provided languages.
If you define a custom ``LANGUAGES`` setting, it's OK to mark the languages as
translation strings (as in the default value displayed above) -- but use a
"dummy" ``gettext()`` function, not the one in ``django.utils.translation``.
You should *never* import ``django.utils.translation`` from within your
settings file, because that module in itself depends on the settings, and that
would cause a circular import.
The solution is to use a "dummy" ``gettext()`` function. Here's a sample
settings file::
gettext = lambda s: s
LANGUAGES = (
('de', gettext('German')),
('en', gettext('English')),
)
With this arrangement, ``make-messages.py`` will still find and mark these
strings for translation, but the translation won't happen at runtime -- so
you'll have to remember to wrap the languages in the *real* ``gettext()`` in
any code that uses ``LANGUAGES`` at runtime.
MANAGERS
--------
@ -738,6 +760,13 @@ Note that this is the time zone to which Django will convert all dates/times --
not necessarily the timezone of the server. For example, one server may serve
multiple Django-powered sites, each with a separate time-zone setting.
Normally, Django sets the ``os.environ['TZ']`` variable to the time zone you
specify in the ``TIME_ZONE`` setting. Thus, all your views and models will
automatically operate in the correct time zone. However, if you're using the
manual configuration option (see below), Django will *not* touch the ``TZ``
environment variable, and it'll be up to you to ensure your processes are
running in the correct environment.
USE_ETAGS
---------
@ -815,6 +844,15 @@ uppercase, with the same name as the settings described above. If a particular
setting is not passed to ``configure()`` and is needed at some later point,
Django will use the default setting value.
Configuring Django in this fashion is mostly necessary -- and, indeed,
recommended -- when you're using a piece of the framework inside a larger
application.
Consequently, when configured via ``settings.configure()``, Django will not
make any modifications to the process environment variables. (See the
explanation of ``TIME_ZONE``, above, for why this would normally occur.) It's
assumed that you're already in full control of your environment in these cases.
Custom default settings
-----------------------

View File

@ -47,7 +47,7 @@ explained later in this document.::
JavaScript and CSV. You can use the template language for any text-based
format.
Oh, and one more thing: Making humans edit XML is masochistic!
Oh, and one more thing: Making humans edit XML is sadistic!
Variables
=========

View File

@ -643,7 +643,7 @@ the current date/time, formatted according to a parameter given in the tag, in
`strftime syntax`_. It's a good idea to decide the tag syntax before anything
else. In our case, let's say the tag should be used like this::
<p>The time is {% current_time "%Y-%M-%d %I:%M %p" %}.</p>
<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
.. _`strftime syntax`: http://www.python.org/doc/current/lib/module-time.html#l2h-1941
@ -653,10 +653,10 @@ object::
from django import template
def do_current_time(parser, token):
try:
# Splitting by None == splitting by spaces.
tag_name, format_string = token.contents.split(None, 1)
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires an argument" % token.contents[0]
raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents[0]
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
return CurrentTimeNode(format_string[1:-1])
@ -667,7 +667,13 @@ Notes:
example.
* ``token.contents`` is a string of the raw contents of the tag. In our
example, it's ``'current_time "%Y-%M-%d %I:%M %p"'``.
example, it's ``'current_time "%Y-%m-%d %I:%M %p"'``.
* The ``token.split_contents()`` method separates the arguments on spaces
while keeping quoted strings together. The more straightforward
``token.contents.split()`` wouldn't be as robust, as it would naively
split on *all* spaces, including those within quoted strings. It's a good
idea to always use ``token.split_contents()``.
* This function is responsible for raising
``django.template.TemplateSyntaxError``, with helpful messages, for
@ -681,7 +687,7 @@ Notes:
* The function returns a ``CurrentTimeNode`` with everything the node needs
to know about this tag. In this case, it just passes the argument --
``"%Y-%M-%d %I:%M %p"``. The leading and trailing quotes from the
``"%Y-%m-%d %I:%M %p"``. The leading and trailing quotes from the
template tag are removed in ``format_string[1:-1]``.
* The parsing is very low-level. The Django developers have experimented
@ -766,27 +772,24 @@ registers it with the template system.
Our earlier ``current_time`` function could thus be written like this::
# This version of do_current_time takes only a single argument and returns
# a string.
def current_time(format_string):
return datetime.datetime.now().strftime(format_string)
def do_current_time(token):
try:
# Splitting by None == splitting by spaces.
tag_name, format_string = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires an argument" % token.contents[0]
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
return datetime.datetime.now().strftime(self.format_string[1:-1])
register.simple_tag(do_current_time)
register.simple_tag(current_time)
In Python 2.4, the decorator syntax also works::
@register.simple_tag
def do_current_time(token):
def current_time(token):
...
A couple of things to note about the ``simple_tag`` helper function:
* Only the (single) argument is passed into our function.
* Checking for the required number of arguments, etc, has already been
done by the time our function is called, so we don't need to do that.
* The quotes around the argument (if any) have already been stripped away,
so we just receive a plain string.
Inclusion tags
~~~~~~~~~~~~~~

View File

@ -14,7 +14,8 @@ setup(
packages = find_packages(exclude=['examples', 'examples.*']),
package_data = {
'': ['*.TXT'],
'django.conf': ['locale/bn/LC_MESSAGES/*',
'django.conf': ['locale/ar/LC_MESSAGES/*',
'locale/bn/LC_MESSAGES/*',
'locale/cs/LC_MESSAGES/*',
'locale/cy/LC_MESSAGES/*',
'locale/da/LC_MESSAGES/*',

View File

@ -28,24 +28,23 @@ API_TESTS = """
>>> r.save()
>>> g = User(username='gustav')
>>> g.save()
>>> i = Issue(num=1)
>>> i.client = r
>>> i.validate()
{}
>>> i.save()
>>> i2 = Issue(num=2)
>>> i2.client = r
>>> i2.validate()
{}
>>> i2.save()
>>> i2.cc.add(r)
>>> i3 = Issue(num=3)
>>> i3.client = g
>>> i3.validate()
{}
>>> i3.save()
>>> i3.cc.add(r)
>>> from django.db.models.query import Q
>>> Issue.objects.filter(client=r.id)
[<Issue: 1>, <Issue: 2>]
>>> Issue.objects.filter(client=g.id)
@ -55,8 +54,8 @@ API_TESTS = """
>>> Issue.objects.filter(cc__id__exact=r.id)
[<Issue: 2>, <Issue: 3>]
# Queries that combine results from the m2m and the m2o relationship.
# 3 ways of saying the same thing:
# These queries combine results from the m2m and the m2o relationships.
# They're three ways of saying the same thing.
>>> Issue.objects.filter(Q(cc__id__exact=r.id) | Q(client=r.id))
[<Issue: 1>, <Issue: 2>, <Issue: 3>]
>>> Issue.objects.filter(cc__id__exact=r.id) | Issue.objects.filter(client=r.id)

View File

@ -1,5 +1,9 @@
from django.conf import settings
if __name__ == '__main__':
# When running this file in isolation, we need to set up the configuration
# before importing 'template'.
settings.configure()
from django import template
from django.template import loader
@ -538,10 +542,10 @@ TEMPLATE_TESTS = {
### TIMESINCE TAG ##################################################
# Default compare with datetime.now()
'timesince01' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=-1)}, '1 minute'),
'timesince02' : ('{{ a|timesince }}', {'a':(datetime.now() - timedelta(days=1))}, '1 day'),
'timesince01' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=-1, seconds = -10)}, '1 minute'),
'timesince02' : ('{{ a|timesince }}', {'a':(datetime.now() - timedelta(days=1, minutes = 1))}, '1 day'),
'timesince03' : ('{{ a|timesince }}', {'a':(datetime.now() -
timedelta(hours=1, minutes=25))}, '1 hour, 25 minutes'),
timedelta(hours=1, minutes=25, seconds = 10))}, '1 hour, 25 minutes'),
# Compare to a given parameter
'timesince04' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2), 'b':NOW + timedelta(days=1)}, '1 day'),
@ -552,9 +556,9 @@ TEMPLATE_TESTS = {
### TIMEUNTIL TAG ##################################################
# Default compare with datetime.now()
'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2)}, '2 minutes'),
'timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1))}, '1 day'),
'timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10))}, '8 hours, 10 minutes'),
'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'),
'timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1, seconds = 10))}, '1 day'),
'timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10, seconds = 10))}, '8 hours, 10 minutes'),
# Compare to a given parameter
'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=1), 'b':NOW - timedelta(days=2)}, '1 day'),
@ -621,5 +625,4 @@ def run_tests(verbosity=0, standalone=False):
raise Exception, msg
if __name__ == "__main__":
settings.configure()
run_tests(1, True)

View File

@ -154,8 +154,9 @@ class TestRunner:
# Manually set INSTALLED_APPS to point to the test models.
settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS + ['.'.join(a) for a in get_test_models()]
# Manually set DEBUG = False.
# Manually set DEBUG and USE_I18N.
settings.DEBUG = False
settings.USE_I18N = True
self.output(0, "Running tests with database %r" % settings.DATABASE_ENGINE)