mirror of
https://github.com/django/django.git
synced 2025-07-05 10:19:20 +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:
parent
49ce784805
commit
541ac3b990
1
AUTHORS
1
AUTHORS
@ -72,6 +72,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
junzhang.jn@gmail.com
|
junzhang.jn@gmail.com
|
||||||
Russell Keith-Magee <freakboy@iinet.net.au>
|
Russell Keith-Magee <freakboy@iinet.net.au>
|
||||||
Garth Kidd <http://www.deadlybloodyserious.com/>
|
Garth Kidd <http://www.deadlybloodyserious.com/>
|
||||||
|
kilian <kilian.cavalotti@lip6.fr>
|
||||||
Sune Kirkeby <http://ibofobi.dk/>
|
Sune Kirkeby <http://ibofobi.dk/>
|
||||||
Cameron Knight (ckknight)
|
Cameron Knight (ckknight)
|
||||||
Bruce Kroeze <http://coderseye.com/>
|
Bruce Kroeze <http://coderseye.com/>
|
||||||
|
@ -36,6 +36,7 @@ LANGUAGE_CODE = 'en-us'
|
|||||||
# Languages we provide translations for, out of the box. The language name
|
# Languages we provide translations for, out of the box. The language name
|
||||||
# should be the utf-8 encoded local name for the language.
|
# should be the utf-8 encoded local name for the language.
|
||||||
LANGUAGES = (
|
LANGUAGES = (
|
||||||
|
('ar', gettext_noop('Arabic')),
|
||||||
('bn', gettext_noop('Bengali')),
|
('bn', gettext_noop('Bengali')),
|
||||||
('cs', gettext_noop('Czech')),
|
('cs', gettext_noop('Czech')),
|
||||||
('cy', gettext_noop('Welsh')),
|
('cy', gettext_noop('Welsh')),
|
||||||
@ -67,7 +68,7 @@ LANGUAGES = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Languages using BiDi (right-to-left) layout
|
# 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
|
# If you set this to False, Django will make some optimizations so as not
|
||||||
# to load the internationalization machinery.
|
# to load the internationalization machinery.
|
||||||
|
BIN
django/conf/locale/ar/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/ar/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
1989
django/conf/locale/ar/LC_MESSAGES/django.po
Normal file
1989
django/conf/locale/ar/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ar/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/ar/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
110
django/conf/locale/ar/LC_MESSAGES/djangojs.po
Normal file
110
django/conf/locale/ar/LC_MESSAGES/djangojs.po
Normal 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 "الغد"
|
||||||
|
|
BIN
django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
@ -26,7 +26,7 @@
|
|||||||
{% block nav-global %}{% endblock %}
|
{% block nav-global %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
<!-- END Header -->
|
<!-- END Header -->
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} › {{ title }}{% endif %}</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} › {{ title|escape }}{% endif %}</div>{% endblock %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
<div id="content" class="{% block coltype %}colM{% endblock %}">
|
<div id="content" class="{% block coltype %}colM{% endblock %}">
|
||||||
{% block pretitle %}{% 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 content %}{{ content }}{% endblock %}
|
||||||
{% block sidebar %}{% endblock %}
|
{% block sidebar %}{% endblock %}
|
||||||
<br class="clear" />
|
<br class="clear" />
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% extends "admin/base.html" %}
|
{% extends "admin/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}
|
{% block title %}{{ title|escape }} | {% trans 'Django site admin' %}{% endblock %}
|
||||||
|
|
||||||
{% block branding %}
|
{% block branding %}
|
||||||
<h1 id="site-name">{% trans 'Django administration' %}</h1>
|
<h1 id="site-name">{% trans 'Django administration' %}</h1>
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
{% block breadcrumbs %}{% if not is_popup %}
|
{% block breadcrumbs %}{% if not is_popup %}
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
<a href="../../../">{% trans "Home" %}</a> ›
|
<a href="../../../">{% trans "Home" %}</a> ›
|
||||||
<a href="../">{{ opts.verbose_name_plural|capfirst }}</a> ›
|
<a href="../">{{ opts.verbose_name_plural|capfirst|escape }}</a> ›
|
||||||
{% if add %}{% trans "Add" %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %}
|
{% if add %}{% trans "Add" %} {{ opts.verbose_name|escape }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}{% endblock %}
|
{% endif %}{% endblock %}
|
||||||
{% block content %}<div id="content-main">
|
{% block content %}<div id="content-main">
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
{% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %}
|
{% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %}
|
||||||
{% block bodyclass %}change-list{% 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 %}
|
{% 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> › {{ cl.opts.verbose_name_plural|capfirst }}</div>{% endblock %}{% endif %}
|
{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> › {{ cl.opts.verbose_name_plural|capfirst|escape }}</div>{% endblock %}{% endif %}
|
||||||
{% block coltype %}flex{% endblock %}
|
{% block coltype %}flex{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="content-main">
|
<div id="content-main">
|
||||||
{% if has_add_permission %}
|
{% 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 %}
|
{% endif %}
|
||||||
<div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
|
<div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
|
||||||
{% block search %}{% search_form cl %}{% endblock %}
|
{% block search %}{% search_form cl %}{% endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% if show %}
|
{% if show %}
|
||||||
<div class="xfull">
|
<div class="xfull">
|
||||||
<ul class="toplinks">
|
<ul class="toplinks">
|
||||||
{% if back %}<li class="date-back"><a href="{{ back.link }}">‹ {{ back.title }}</a></li>{% endif %}
|
{% if back %}<li class="date-back"><a href="{{ back.link }}">‹ {{ back.title|escape }}</a></li>{% endif %}
|
||||||
{% for choice in choices %}
|
{% 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 %}
|
{% endfor %}
|
||||||
</ul><br class="clear" />
|
</ul><br class="clear" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,21 +4,21 @@
|
|||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
<a href="../../../../">{% trans "Home" %}</a> ›
|
<a href="../../../../">{% trans "Home" %}</a> ›
|
||||||
<a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> ›
|
<a href="../../">{{ opts.verbose_name_plural|capfirst|escape }}</a> ›
|
||||||
<a href="../">{{ object|striptags|truncatewords:"18" }}</a> ›
|
<a href="../">{{ object|escape|truncatewords:"18" }}</a> ›
|
||||||
{% trans 'Delete' %}
|
{% trans 'Delete' %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if perms_lacking %}
|
{% 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>
|
<ul>
|
||||||
{% for obj in perms_lacking %}
|
{% for obj in perms_lacking %}
|
||||||
<li>{{ obj }}</li>
|
<li>{{ obj|escape }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% else %}
|
{% 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>
|
<ul>{{ deleted_objects|unordered_list }}</ul>
|
||||||
<form action="" method="post">
|
<form action="" method="post">
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% load admin_modify %}
|
{% load admin_modify %}
|
||||||
<fieldset class="module aligned">
|
<fieldset class="module aligned">
|
||||||
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
||||||
<h2>{{ bound_related_object.relation.opts.verbose_name|capfirst }} #{{ forloop.counter }}</h2>
|
<h2>{{ bound_related_object.relation.opts.verbose_name|capfirst|escape }} #{{ forloop.counter }}</h2>
|
||||||
{% if bound_related_object.show_url %}{% if fcw.obj.original %}
|
{% 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>
|
<p><a href="/r/{{ fcw.obj.original.content_type_id }}/{{ fcw.obj.original.id }}/">View on site</a></p>
|
||||||
{% endif %}{% endif %}
|
{% endif %}{% endif %}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
{% load admin_modify %}
|
{% load admin_modify %}
|
||||||
<fieldset class="module">
|
<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>
|
<thead><tr>
|
||||||
{% for fw in bound_related_object.field_wrapper_list %}
|
{% for fw in bound_related_object.field_wrapper_list %}
|
||||||
{% if fw.needs_header %}
|
{% 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 %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<h3>{% blocktrans %} By {{ title }} {% endblocktrans %}</h3>
|
<h3>{% blocktrans with title|escape as filter_title %} By {{ filter_title }} {% endblocktrans %}</h3>
|
||||||
<ul>
|
<ul>
|
||||||
{% for choice in choices %}
|
{% for choice in choices %}
|
||||||
<li{% if choice.selected %} class="selected"{% endif %}>
|
<li{% if choice.selected %} class="selected"{% endif %}>
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
{% for model in app.models %}
|
{% for model in app.models %}
|
||||||
<tr>
|
<tr>
|
||||||
{% if model.perms.change %}
|
{% 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 %}
|
{% else %}
|
||||||
<th scope="row">{{ model.name }}</th>
|
<th scope="row">{{ model.name|escape }}</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if model.perms.add %}
|
{% if model.perms.add %}
|
||||||
@ -58,7 +58,7 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<ul class="actionlist">
|
<ul class="actionlist">
|
||||||
{% for entry in admin_log %}
|
{% 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 %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% extends "admin/base_site.html" %}
|
{% extends "admin/base_site.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {{ title }}</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {{ title|escape }}</div>{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{% load i18n %}
|
{% 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 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 %}
|
{% block breadcrumbs %}
|
||||||
<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> › <a href="../../">{{ module_name }}</a> › <a href="../">{{ object|truncatewords:"18" }}</a> › {% trans 'History' %}</div>
|
<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> › <a href="../../">{{ module_name|escape }}</a> › <a href="../">{{ object|escape|truncatewords:"18" }}</a> › {% trans 'History' %}</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
{% paginator_number cl i %}
|
{% paginator_number cl i %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% 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 %} <a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
|
{% if show_all_url %} <a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Models</a> › {{ name }}</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Models</a> › {{ name|escape }}</div>{% endblock %}
|
||||||
|
|
||||||
{% block title %}Model: {{ name }}{% endblock %}
|
{% block title %}Model: {{ name|escape }}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="content-main">
|
<div id="content-main">
|
||||||
<h1>{{ summary }}</h1>
|
<h1>{{ summary|escape }}</h1>
|
||||||
|
|
||||||
{% if description %}
|
{% if description %}
|
||||||
<p>{% filter escape|linebreaksbr %}{% trans description %}{% endfilter %}</p>
|
<p>{% filter escape|linebreaksbr %}{% trans description %}{% endfilter %}</p>
|
||||||
@ -35,7 +35,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>{{ field.name }}</td>
|
<td>{{ field.name }}</td>
|
||||||
<td>{{ field.data_type }}</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>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
{% extends "admin/base_site.html" %}
|
{% extends "admin/base_site.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › Templates › {{ name }}</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › Templates › {{ name|escape }}</div>{% endblock %}
|
||||||
{% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% 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 %}
|
{% block content %}
|
||||||
<h1>Template: "{{ name }}"</h1>
|
<h1>Template: "{{ name|escape }}"</h1>
|
||||||
|
|
||||||
{% regroup templates|dictsort:"site_id" by site as templates_by_site %}
|
{% regroup templates|dictsort:"site_id" by site as templates_by_site %}
|
||||||
{% for group in 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>
|
<ol>
|
||||||
{% for template in group.list|dictsort:"order" %}
|
{% 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 %}
|
{% endfor %}
|
||||||
</ol>
|
</ol>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<h1>{{ name }}</h1>
|
<h1>{{ name }}</h1>
|
||||||
|
|
||||||
<h2 class="subhead">{{ summary }}</h2>
|
<h2 class="subhead">{{ summary|escape }}</h2>
|
||||||
|
|
||||||
<p>{{ body }}</p>
|
<p>{{ body }}</p>
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{% load admin_modify i18n %}{% if bound_field.original_value %}
|
{% 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 %}
|
{% trans "Change:" %}{% output_all bound_field.form_fields %}
|
||||||
{% else %} {% output_all bound_field.form_fields %} {% endif %}
|
{% else %} {% output_all bound_field.form_fields %} {% endif %}
|
||||||
|
@ -15,6 +15,6 @@
|
|||||||
{{ bound_field.original_value }}
|
{{ bound_field.original_value }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if bound_field.raw_id_admin %}
|
{% if bound_field.raw_id_admin %}
|
||||||
{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}
|
{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
{% if add %}{% include "widget/foreign.html" %}{% endif %}
|
{% if add %}{% include "widget/foreign.html" %}{% endif %}
|
||||||
{% if change %}{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}{% endif %}
|
{% if change %}{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %}{% endif %}
|
||||||
|
@ -165,12 +165,14 @@ def items_for_result(cl, result):
|
|||||||
result_repr = escape(str(field_val))
|
result_repr = escape(str(field_val))
|
||||||
if result_repr == '':
|
if result_repr == '':
|
||||||
result_repr = ' '
|
result_repr = ' '
|
||||||
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
|
first = False
|
||||||
url = cl.url_for_result(result)
|
url = cl.url_for_result(result)
|
||||||
result_id = str(getattr(result, pk)) # str() is needed in case of 23L (long ints)
|
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>' % \
|
yield ('<%s%s><a href="%s"%s>%s</a></%s>' % \
|
||||||
(row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr))
|
(table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr, table_tag))
|
||||||
else:
|
else:
|
||||||
yield ('<td%s>%s</td>' % (row_class, result_repr))
|
yield ('<td%s>%s</td>' % (row_class, result_repr))
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ def authenticate(**credentials):
|
|||||||
if user is None:
|
if user is None:
|
||||||
continue
|
continue
|
||||||
# Annotate the user object with the path of the backend.
|
# 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
|
return user
|
||||||
|
|
||||||
def login(request, user):
|
def login(request, user):
|
||||||
|
@ -239,7 +239,7 @@ class User(models.Model):
|
|||||||
app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
|
app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
|
||||||
model = models.get_model(app_label, model_name)
|
model = models.get_model(app_label, model_name)
|
||||||
self._profile_cache = model._default_manager.get(user__id__exact=self.id)
|
self._profile_cache = model._default_manager.get(user__id__exact=self.id)
|
||||||
except ImportError, ImproperlyConfigured:
|
except (ImportError, ImproperlyConfigured):
|
||||||
raise SiteProfileNotAvailable
|
raise SiteProfileNotAvailable
|
||||||
return self._profile_cache
|
return self._profile_cache
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ class FlatPage(models.Model):
|
|||||||
content = models.TextField(_('content'))
|
content = models.TextField(_('content'))
|
||||||
enable_comments = models.BooleanField(_('enable comments'))
|
enable_comments = models.BooleanField(_('enable comments'))
|
||||||
template_name = models.CharField(_('template name'), maxlength=70, blank=True,
|
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."))
|
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)
|
sites = models.ManyToManyField(Site)
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -45,8 +45,8 @@ def disable_termcolors():
|
|||||||
global style
|
global style
|
||||||
style = dummy()
|
style = dummy()
|
||||||
|
|
||||||
# Disable terminal coloring on Windows or if somebody's piping the output.
|
# Disable terminal coloring on Windows, Pocket PC, or if somebody's piping the output.
|
||||||
if sys.platform == 'win32' or not sys.stdout.isatty():
|
if sys.platform == 'win32' or sys.platform == 'Pocket PC' or not sys.stdout.isatty():
|
||||||
disable_termcolors()
|
disable_termcolors()
|
||||||
|
|
||||||
# singleton representing the default connection
|
# singleton representing the default connection
|
||||||
@ -847,6 +847,19 @@ def get_validation_errors(outfile, app=None):
|
|||||||
else:
|
else:
|
||||||
if isinstance(f, models.ManyToManyField):
|
if isinstance(f, models.ManyToManyField):
|
||||||
e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn)
|
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
|
# list_filter
|
||||||
if not isinstance(opts.admin.list_filter, (list, tuple)):
|
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.')
|
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.stderr.write(s.read())
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def runserver(addr, port):
|
def runserver(addr, port, use_reloader=True):
|
||||||
"Starts a lightweight Web server for development."
|
"Starts a lightweight Web server for development."
|
||||||
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
|
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
|
||||||
from django.core.handlers.wsgi import WSGIHandler
|
from django.core.handlers.wsgi import WSGIHandler
|
||||||
@ -956,9 +969,12 @@ def runserver(addr, port):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
if use_reloader:
|
||||||
from django.utils import autoreload
|
from django.utils import autoreload
|
||||||
autoreload.main(inner_run)
|
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):
|
def createcachetable(tablename):
|
||||||
"Creates the table needed to use the SQL cache backend"
|
"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".')
|
help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
|
||||||
parser.add_option('--plain', action='store_true', dest='plain',
|
parser.add_option('--plain', action='store_true', dest='plain',
|
||||||
help='Tells Django to use plain Python, not IPython, for "shell" command.')
|
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:])
|
options, args = parser.parse_args(argv[1:])
|
||||||
|
|
||||||
# Take care of options.
|
# 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(':')
|
addr, port = args[1].split(':')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
addr, port = '', args[1]
|
addr, port = '', args[1]
|
||||||
action_mapping[action](addr, port)
|
action_mapping[action](addr, port, options.use_reloader)
|
||||||
elif action == 'runfcgi':
|
elif action == 'runfcgi':
|
||||||
action_mapping[action](args[1:])
|
action_mapping[action](args[1:])
|
||||||
else:
|
else:
|
||||||
|
@ -23,7 +23,7 @@ ansi_datetime_re = re.compile('^%s %s$' % (_datere, _timere))
|
|||||||
email_re = re.compile(
|
email_re = re.compile(
|
||||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
|
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'|^"([\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+$')
|
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}$')
|
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)
|
phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE)
|
||||||
|
@ -46,7 +46,7 @@ def manipulator_valid_rel_key(f, self, field_data, all_data):
|
|||||||
"Validates that the value is a valid foreign key"
|
"Validates that the value is a valid foreign key"
|
||||||
klass = f.rel.to
|
klass = f.rel.to
|
||||||
try:
|
try:
|
||||||
klass._default_manager.get(pk=field_data)
|
klass._default_manager.get(**{f.rel.field_name: field_data})
|
||||||
except klass.DoesNotExist:
|
except klass.DoesNotExist:
|
||||||
raise validators.ValidationError, _("Please enter a valid %s.") % f.verbose_name
|
raise validators.ValidationError, _("Please enter a valid %s.") % f.verbose_name
|
||||||
|
|
||||||
|
@ -212,12 +212,13 @@ class Options(object):
|
|||||||
return self._field_types[field_type]
|
return self._field_types[field_type]
|
||||||
|
|
||||||
class AdminOptions(object):
|
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,
|
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):
|
save_on_top=False, list_select_related=False, manager=None, list_per_page=100):
|
||||||
self.fields = fields
|
self.fields = fields
|
||||||
self.js = js or []
|
self.js = js or []
|
||||||
self.list_display = list_display or ['__str__']
|
self.list_display = list_display or ['__str__']
|
||||||
|
self.list_display_links = list_display_links or []
|
||||||
self.list_filter = list_filter or []
|
self.list_filter = list_filter or []
|
||||||
self.date_hierarchy = date_hierarchy
|
self.date_hierarchy = date_hierarchy
|
||||||
self.save_as, self.ordering = save_as, ordering
|
self.save_as, self.ordering = save_as, ordering
|
||||||
|
@ -85,8 +85,8 @@ class QuerySet(object):
|
|||||||
self._where = [] # List of extra WHERE clauses to use.
|
self._where = [] # List of extra WHERE clauses to use.
|
||||||
self._params = [] # List of params to use for extra WHERE clauses.
|
self._params = [] # List of params to use for extra WHERE clauses.
|
||||||
self._tables = [] # List of extra tables to use.
|
self._tables = [] # List of extra tables to use.
|
||||||
self._offset = None # OFFSET clause
|
self._offset = None # OFFSET clause.
|
||||||
self._limit = None # LIMIT clause
|
self._limit = None # LIMIT clause.
|
||||||
self._result_cache = None
|
self._result_cache = None
|
||||||
|
|
||||||
########################
|
########################
|
||||||
@ -444,8 +444,7 @@ class QuerySet(object):
|
|||||||
params = self._params[:]
|
params = self._params[:]
|
||||||
|
|
||||||
# Convert self._filters into SQL.
|
# Convert self._filters into SQL.
|
||||||
tables2, joins2, where2, params2 = self._filters.get_sql(opts)
|
joins2, where2, params2 = self._filters.get_sql(opts)
|
||||||
tables.extend(tables2)
|
|
||||||
joins.update(joins2)
|
joins.update(joins2)
|
||||||
where.extend(where2)
|
where.extend(where2)
|
||||||
params.extend(params2)
|
params.extend(params2)
|
||||||
@ -580,16 +579,15 @@ class QOperator(object):
|
|||||||
self.args = args
|
self.args = args
|
||||||
|
|
||||||
def get_sql(self, opts):
|
def get_sql(self, opts):
|
||||||
tables, joins, where, params = [], SortedDict(), [], []
|
joins, where, params = SortedDict(), [], []
|
||||||
for val in self.args:
|
for val in self.args:
|
||||||
tables2, joins2, where2, params2 = val.get_sql(opts)
|
joins2, where2, params2 = val.get_sql(opts)
|
||||||
tables.extend(tables2)
|
|
||||||
joins.update(joins2)
|
joins.update(joins2)
|
||||||
where.extend(where2)
|
where.extend(where2)
|
||||||
params.extend(params2)
|
params.extend(params2)
|
||||||
if where:
|
if where:
|
||||||
return tables, joins, ['(%s)' % self.operator.join(where)], params
|
return joins, ['(%s)' % self.operator.join(where)], params
|
||||||
return tables, joins, [], params
|
return joins, [], params
|
||||||
|
|
||||||
class QAnd(QOperator):
|
class QAnd(QOperator):
|
||||||
"Encapsulates a combined query that uses 'AND'."
|
"Encapsulates a combined query that uses 'AND'."
|
||||||
@ -640,9 +638,9 @@ class QNot(Q):
|
|||||||
self.q = q
|
self.q = q
|
||||||
|
|
||||||
def get_sql(self, opts):
|
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)]
|
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):
|
def get_where_clause(opts, lookup_type, table_prefix, field_name, value):
|
||||||
backend = opts.connection_info.backend
|
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.
|
place) for select_related queries.
|
||||||
"""
|
"""
|
||||||
backend = opts.connection_info.backend
|
backend = opts.connection_info.backend
|
||||||
|
qn = backend.quote_name
|
||||||
for f in opts.fields:
|
for f in opts.fields:
|
||||||
if f.rel and not f.null:
|
if f.rel and not f.null:
|
||||||
db_table = f.rel.to._meta.db_table
|
db_table = f.rel.to._meta.db_table
|
||||||
if db_table not in cache_tables_seen:
|
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.
|
else: # The table was already seen, so give it a table alias.
|
||||||
new_prefix = '%s%s' % (db_table, len(cache_tables_seen))
|
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
|
db_table = new_prefix
|
||||||
cache_tables_seen.append(db_table)
|
cache_tables_seen.append(db_table)
|
||||||
where.append('%s.%s = %s.%s' % \
|
where.append('%s.%s = %s.%s' % \
|
||||||
(backend.quote_name(old_prefix), backend.quote_name(f.column),
|
(qn(old_prefix), qn(f.column), qn(db_table), qn(f.rel.get_related_field().column)))
|
||||||
backend.quote_name(db_table), backend.quote_name(f.rel.get_related_field().column)))
|
select.extend(['%s.%s' % (qn(db_table), qn(f2.column)) for f2 in f.rel.to._meta.fields])
|
||||||
select.extend(['%s.%s' % (backend.quote_name(db_table), backend.quote_name(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)
|
fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen)
|
||||||
|
|
||||||
def parse_lookup(kwarg_items, opts):
|
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
|
# 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
|
# there for others to implement custom Q()s, etc that return other join
|
||||||
# types.
|
# types.
|
||||||
tables, joins, where, params = [], SortedDict(), [], []
|
joins, where, params = SortedDict(), [], []
|
||||||
|
|
||||||
for kwarg, value in kwarg_items:
|
for kwarg, value in kwarg_items:
|
||||||
if value is not None:
|
if value is not None:
|
||||||
path = kwarg.split(LOOKUP_SEPARATOR)
|
path = kwarg.split(LOOKUP_SEPARATOR)
|
||||||
# Extract the last elements of the kwarg.
|
# Extract the last elements of the kwarg.
|
||||||
# The very-last is the clause (equals, like, etc).
|
# The very-last is the lookup_type (equals, like, etc).
|
||||||
# The second-last is the table column on which the clause is
|
# The second-last is the table column on which the lookup_type is
|
||||||
# to be performed.
|
# to be performed.
|
||||||
# The exceptions to this are:
|
# The exceptions to this are:
|
||||||
# 1) "pk", which is an implicit id__exact;
|
# 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
|
# a dummy name of None, which we will replace when
|
||||||
# we know which table column to grab as the primary key.
|
# 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
|
# 2) If there is only one part, or the last part is not a query
|
||||||
# term, assume that the query is an __exact
|
# term, assume that the query is an __exact
|
||||||
clause = path.pop()
|
lookup_type = path.pop()
|
||||||
if clause == 'pk':
|
if lookup_type == 'pk':
|
||||||
clause = 'exact'
|
lookup_type = 'exact'
|
||||||
path.append(None)
|
path.append(None)
|
||||||
elif len(path) == 0 or clause not in QUERY_TERMS:
|
elif len(path) == 0 or lookup_type not in QUERY_TERMS:
|
||||||
path.append(clause)
|
path.append(lookup_type)
|
||||||
clause = 'exact'
|
lookup_type = 'exact'
|
||||||
|
|
||||||
if len(path) < 1:
|
if len(path) < 1:
|
||||||
raise TypeError, "Cannot parse keyword query %r" % kwarg
|
raise TypeError, "Cannot parse keyword query %r" % kwarg
|
||||||
|
|
||||||
tables2, joins2, where2, params2 = lookup_inner(path, clause, value, opts, opts.db_table, None)
|
joins2, where2, params2 = lookup_inner(path, lookup_type, value, opts, opts.db_table, None)
|
||||||
tables.extend(tables2)
|
|
||||||
joins.update(joins2)
|
joins.update(joins2)
|
||||||
where.extend(where2)
|
where.extend(where2)
|
||||||
params.extend(params2)
|
params.extend(params2)
|
||||||
return tables, joins, where, params
|
return joins, where, params
|
||||||
|
|
||||||
class FieldFound(Exception):
|
class FieldFound(Exception):
|
||||||
"Exception used to short circuit field-finding operations."
|
"Exception used to short circuit field-finding operations."
|
||||||
@ -770,8 +767,8 @@ def find_field(name, field_list, related_query):
|
|||||||
return None
|
return None
|
||||||
return matches[0]
|
return matches[0]
|
||||||
|
|
||||||
def lookup_inner(path, clause, value, opts, table, column):
|
def lookup_inner(path, lookup_type, value, opts, table, column):
|
||||||
tables, joins, where, params = [], SortedDict(), [], []
|
joins, where, params = SortedDict(), [], []
|
||||||
current_opts = opts
|
current_opts = opts
|
||||||
current_table = table
|
current_table = table
|
||||||
current_column = column
|
current_column = column
|
||||||
@ -780,6 +777,7 @@ def lookup_inner(path, clause, value, opts, table, column):
|
|||||||
info = current_opts.connection_info
|
info = current_opts.connection_info
|
||||||
backend = info.backend
|
backend = info.backend
|
||||||
connection = info.connection
|
connection = info.connection
|
||||||
|
qn = backend.quote_name
|
||||||
|
|
||||||
name = path.pop(0)
|
name = path.pop(0)
|
||||||
# Has the primary key been requested? If so, expand it out
|
# 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?
|
# Does the name belong to a defined many-to-many field?
|
||||||
field = find_field(name, current_opts.many_to_many, False)
|
field = find_field(name, current_opts.many_to_many, False)
|
||||||
if field:
|
if field:
|
||||||
new_table = current_table + LOOKUP_SEPARATOR + name
|
new_table = current_table + '__' + name
|
||||||
new_opts = field.rel.to._meta
|
new_opts = field.rel.to._meta
|
||||||
new_column = new_opts.pk.column
|
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?
|
# 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)
|
field = find_field(name, current_opts.get_all_related_many_to_many_objects(), True)
|
||||||
if field:
|
if field:
|
||||||
new_table = current_table + LOOKUP_SEPARATOR + name
|
new_table = current_table + '__' + name
|
||||||
new_opts = field.opts
|
new_opts = field.opts
|
||||||
new_column = new_opts.pk.column
|
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?
|
# Does the name belong to a one-to-many field?
|
||||||
field = find_field(name, current_opts.get_all_related_objects(), True)
|
field = find_field(name, current_opts.get_all_related_objects(), True)
|
||||||
if field:
|
if field:
|
||||||
new_table = table + LOOKUP_SEPARATOR + name
|
new_table = table + '__' + name
|
||||||
new_opts = field.opts
|
new_opts = field.opts
|
||||||
new_column = field.field.column
|
new_column = field.field.column
|
||||||
join_column = opts.pk.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)
|
field = find_field(name, current_opts.fields, False)
|
||||||
if field:
|
if field:
|
||||||
if field.rel: # One-to-One/Many-to-one 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_opts = field.rel.to._meta
|
||||||
new_column = new_opts.pk.column
|
new_column = new_opts.pk.column
|
||||||
join_column = field.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.
|
except FieldFound: # Match found, loop has been shortcut.
|
||||||
pass
|
pass
|
||||||
except: # Any other exception; rethrow
|
|
||||||
raise
|
|
||||||
else: # No match found.
|
else: # No match found.
|
||||||
raise TypeError, "Cannot resolve keyword '%s' into field" % name
|
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.
|
# and new_table.
|
||||||
if intermediate_table:
|
if intermediate_table:
|
||||||
joins[backend.quote_name(current_table)] = (
|
joins[qn(current_table)] = (
|
||||||
backend.quote_name(intermediate_table),
|
qn(intermediate_table), "LEFT OUTER JOIN",
|
||||||
"LEFT OUTER JOIN",
|
"%s.%s = %s.%s" % (qn(table), qn(current_opts.pk.column), qn(current_table), qn(intermediate_column))
|
||||||
"%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))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if path:
|
if path:
|
||||||
# There are elements left in the path. More joins are required.
|
# There are elements left in the path. More joins are required.
|
||||||
if len(path) == 1 and path[0] in (new_opts.pk.name, None) \
|
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,
|
# If the next and final name query is for a primary key,
|
||||||
# and the search is for isnull/exact, then the current
|
# and the search is for isnull/exact, then the current
|
||||||
# (for N-1) or intermediate (for N-N) table can be used
|
# (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.
|
# to check the primary key.
|
||||||
new_table = current_table
|
new_table = current_table
|
||||||
else:
|
else:
|
||||||
# There are 1 or more name queries pending, and we have ruled out
|
# There are 1 or more name queries pending, and we have ruled out
|
||||||
# any shortcuts; therefore, a join is required.
|
# any shortcuts; therefore, a join is required.
|
||||||
joins[backend.quote_name(new_table)] = (
|
joins[qn(new_table)] = (
|
||||||
backend.quote_name(new_opts.db_table),
|
qn(new_opts.db_table), "INNER JOIN",
|
||||||
"INNER JOIN",
|
"%s.%s = %s.%s" % (qn(current_table), qn(join_column), qn(new_table), qn(new_column))
|
||||||
"%s.%s = %s.%s" %
|
|
||||||
(backend.quote_name(current_table),
|
|
||||||
backend.quote_name(join_column),
|
|
||||||
backend.quote_name(new_table),
|
|
||||||
backend.quote_name(new_column))
|
|
||||||
)
|
)
|
||||||
# If we have made the join, we don't need to tell subsequent
|
# If we have made the join, we don't need to tell subsequent
|
||||||
# recursive calls about the column name we joined on.
|
# recursive calls about the column name we joined on.
|
||||||
join_column = None
|
join_column = None
|
||||||
|
|
||||||
# There are name queries remaining. Recurse deeper.
|
# 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)
|
joins.update(joins2)
|
||||||
where.extend(where2)
|
where.extend(where2)
|
||||||
params.extend(params2)
|
params.extend(params2)
|
||||||
@ -910,14 +895,9 @@ def lookup_inner(path, clause, value, opts, table, column):
|
|||||||
# RelatedObject is from a 1-N relation.
|
# RelatedObject is from a 1-N relation.
|
||||||
# Join is required; query operates on joined table.
|
# Join is required; query operates on joined table.
|
||||||
column = new_opts.pk.name
|
column = new_opts.pk.name
|
||||||
joins[backend.quote_name(new_table)] = (
|
joins[qn(new_table)] = (
|
||||||
backend.quote_name(new_opts.db_table),
|
qn(new_opts.db_table), "INNER JOIN",
|
||||||
"INNER JOIN",
|
"%s.%s = %s.%s" % (qn(current_table), qn(join_column), qn(new_table), qn(new_column))
|
||||||
"%s.%s = %s.%s" %
|
|
||||||
(backend.quote_name(current_table),
|
|
||||||
backend.quote_name(join_column),
|
|
||||||
backend.quote_name(new_table),
|
|
||||||
backend.quote_name(new_column))
|
|
||||||
)
|
)
|
||||||
current_table = new_table
|
current_table = new_table
|
||||||
else:
|
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.
|
# Last query term is a related object from an N-N relation.
|
||||||
# Join from intermediate table is sufficient.
|
# Join from intermediate table is sufficient.
|
||||||
column = join_column
|
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
|
# Last query term is for a primary key. If previous iterations
|
||||||
# introduced a current/intermediate table that can be used to
|
# introduced a current/intermediate table that can be used to
|
||||||
# optimize the query, then use that table and column name.
|
# 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.
|
# Last query term was a normal field.
|
||||||
column = field.column
|
column = field.column
|
||||||
|
|
||||||
where.append(get_where_clause(current_opts, clause, current_table + '.', column, value))
|
where.append(get_where_clause(current_opts, lookup_type, current_table + '.', column, value))
|
||||||
params.extend(field.get_db_prep_lookup(clause, 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):
|
def delete_objects(seen_objs):
|
||||||
"Iterate through a list of seen classes, and remove any instances that are referred to"
|
"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
|
backend = info.backend
|
||||||
connection = info.connection
|
connection = info.connection
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
qn = backend.quote_name
|
||||||
|
|
||||||
seen_objs[cls] = seen_objs[cls].items()
|
seen_objs[cls] = seen_objs[cls].items()
|
||||||
seen_objs[cls].sort()
|
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 related in cls._meta.get_all_related_many_to_many_objects():
|
||||||
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
||||||
cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
|
cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
|
||||||
(backend.quote_name(related.field.m2m_db_table()),
|
(qn(related.field.m2m_db_table()),
|
||||||
backend.quote_name(related.field.m2m_reverse_name()),
|
qn(related.field.m2m_reverse_name()),
|
||||||
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
|
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
|
||||||
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 f in cls._meta.many_to_many:
|
||||||
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
||||||
cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
|
cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
|
||||||
(backend.quote_name(f.m2m_db_table()),
|
(qn(f.m2m_db_table()), qn(f.m2m_column_name()),
|
||||||
backend.quote_name(f.m2m_column_name()),
|
|
||||||
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
|
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
|
||||||
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
|
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
|
||||||
for field in cls._meta.fields:
|
for field in cls._meta.fields:
|
||||||
if field.rel and field.null and field.rel.to in seen_objs:
|
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):
|
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
||||||
cursor.execute("UPDATE %s SET %s=NULL WHERE %s IN (%s)" % \
|
cursor.execute("UPDATE %s SET %s=NULL WHERE %s IN (%s)" % \
|
||||||
(backend.quote_name(cls._meta.db_table),
|
(qn(cls._meta.db_table), qn(field.column), qn(cls._meta.pk.column),
|
||||||
backend.quote_name(field.column),
|
|
||||||
backend.quote_name(cls._meta.pk.column),
|
|
||||||
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
|
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
|
||||||
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
|
info = cls._meta.connection_info
|
||||||
backend = info.backend
|
backend = info.backend
|
||||||
connection = info.connection
|
connection = info.connection
|
||||||
|
qn = backend.quote_name
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
if connection not in dirty_conns:
|
if connection not in dirty_conns:
|
||||||
dirty_conns.append(connection)
|
dirty_conns.append(connection)
|
||||||
@ -1001,8 +980,7 @@ def delete_objects(seen_objs):
|
|||||||
pk_list = [pk for pk,instance in seen_objs[cls]]
|
pk_list = [pk for pk,instance in seen_objs[cls]]
|
||||||
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
||||||
cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
|
cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
|
||||||
(backend.quote_name(cls._meta.db_table),
|
(qn(cls._meta.db_table), qn(cls._meta.pk.column),
|
||||||
backend.quote_name(cls._meta.pk.column),
|
|
||||||
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
|
','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
|
||||||
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
|
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ class Token(object):
|
|||||||
self.contents[:20].replace('\n', ''))
|
self.contents[:20].replace('\n', ''))
|
||||||
|
|
||||||
def split_contents(self):
|
def split_contents(self):
|
||||||
return smart_split(self.contents)
|
return list(smart_split(self.contents))
|
||||||
|
|
||||||
class Lexer(object):
|
class Lexer(object):
|
||||||
def __init__(self, template_string, origin):
|
def __init__(self, template_string, origin):
|
||||||
@ -758,7 +758,7 @@ class DebugVariableNode(VariableNode):
|
|||||||
|
|
||||||
def generic_tag_compiler(params, defaults, name, node_class, parser, token):
|
def generic_tag_compiler(params, defaults, name, node_class, parser, token):
|
||||||
"Returns a template.Node subclass."
|
"Returns a template.Node subclass."
|
||||||
bits = token.contents.split()[1:]
|
bits = token.split_contents()[1:]
|
||||||
bmax = len(params)
|
bmax = len(params)
|
||||||
def_len = defaults and len(defaults) or 0
|
def_len = defaults and len(defaults) or 0
|
||||||
bmin = bmax - def_len
|
bmin = bmax - def_len
|
||||||
|
@ -133,7 +133,7 @@ def wordwrap(value, arg):
|
|||||||
"""
|
"""
|
||||||
Wraps words at specified line length
|
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
|
from django.utils.text import wrap
|
||||||
return wrap(str(value), int(arg))
|
return wrap(str(value), int(arg))
|
||||||
|
@ -14,5 +14,14 @@ string_concat = lambda *strings: ''.join([str(el) for el in strings])
|
|||||||
activate = lambda x: None
|
activate = lambda x: None
|
||||||
deactivate = install = lambda: None
|
deactivate = install = lambda: None
|
||||||
get_language = lambda: settings.LANGUAGE_CODE
|
get_language = lambda: settings.LANGUAGE_CODE
|
||||||
get_date_formats = lambda: settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT
|
get_language_bidi = lambda: settings.LANGUAGE_CODE in settings.LANGUAGES_BIDI
|
||||||
get_partial_date_formats = lambda: settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT
|
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()
|
||||||
|
@ -224,6 +224,13 @@ block::
|
|||||||
This will have {{ myvar }} inside.
|
This will have {{ myvar }} inside.
|
||||||
{% endblocktrans %}
|
{% 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
|
To pluralize, specify both the singular and plural forms with the
|
||||||
``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and
|
``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and
|
||||||
``{% endblocktrans %}``. Example::
|
``{% 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``. In the ``de`` example, the file will be
|
||||||
``conf/locale/de/LC_MESSAGES/django.po``.
|
``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``
|
do the same, but the location of the locale directory is ``locale/LANG/LC_MESSAGES``
|
||||||
(note the missing ``conf`` prefix).
|
(note the missing ``conf`` prefix).
|
||||||
|
|
||||||
@ -452,7 +459,7 @@ Notes:
|
|||||||
``de``.
|
``de``.
|
||||||
* Only languages listed in the `LANGUAGES setting`_ can be selected. If
|
* Only languages listed in the `LANGUAGES setting`_ can be selected. If
|
||||||
you want to restrict the language selection to a subset of provided
|
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::
|
set ``LANGUAGES`` to a list of languages. For example::
|
||||||
|
|
||||||
LANGUAGES = (
|
LANGUAGES = (
|
||||||
@ -465,6 +472,30 @@ Notes:
|
|||||||
en-us).
|
en-us).
|
||||||
|
|
||||||
.. _LANGUAGES setting: http://www.djangoproject.com/documentation/settings/#languages
|
.. _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
|
* The ``LocaleMiddleware`` can only select languages for which there is a
|
||||||
Django-provided base translation. If you want to provide translations
|
Django-provided base translation. If you want to provide translations
|
||||||
for your application that aren't already in the set of 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
|
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
|
interface, plus an array of translation strings. Those translation strings are
|
||||||
taken from the application, project or Django core, according to what you
|
taken from the application, project or Django core, according to what you
|
||||||
specify in either the {{{info_dict}}} or the URL.
|
specify in either the {{{info_dict}}} or the URL.
|
||||||
|
@ -1225,6 +1225,33 @@ A few special cases to note about ``list_display``:
|
|||||||
return self.birthday.strftime('%Y')[:3] + "0's"
|
return self.birthday.strftime('%Y')[:3] + "0's"
|
||||||
decade_born_in.short_description = 'Birth decade'
|
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``
|
``list_filter``
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -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
|
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.
|
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
|
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
|
not necessarily the timezone of the server. For example, one server may serve
|
||||||
multiple Django-powered sites, each with a separate time-zone setting.
|
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
|
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,
|
setting is not passed to ``configure()`` and is needed at some later point,
|
||||||
Django will use the default setting value.
|
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
|
Custom default settings
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ explained later in this document.::
|
|||||||
JavaScript and CSV. You can use the template language for any text-based
|
JavaScript and CSV. You can use the template language for any text-based
|
||||||
format.
|
format.
|
||||||
|
|
||||||
Oh, and one more thing: Making humans edit XML is masochistic!
|
Oh, and one more thing: Making humans edit XML is sadistic!
|
||||||
|
|
||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
@ -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
|
`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::
|
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
|
.. _`strftime syntax`: http://www.python.org/doc/current/lib/module-time.html#l2h-1941
|
||||||
|
|
||||||
@ -653,10 +653,10 @@ object::
|
|||||||
from django import template
|
from django import template
|
||||||
def do_current_time(parser, token):
|
def do_current_time(parser, token):
|
||||||
try:
|
try:
|
||||||
# Splitting by None == splitting by spaces.
|
# split_contents() knows not to split quoted strings.
|
||||||
tag_name, format_string = token.contents.split(None, 1)
|
tag_name, format_string = token.split_contents()
|
||||||
except ValueError:
|
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 ('"', "'")):
|
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
|
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
|
||||||
return CurrentTimeNode(format_string[1:-1])
|
return CurrentTimeNode(format_string[1:-1])
|
||||||
@ -667,7 +667,13 @@ Notes:
|
|||||||
example.
|
example.
|
||||||
|
|
||||||
* ``token.contents`` is a string of the raw contents of the tag. In our
|
* ``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
|
* This function is responsible for raising
|
||||||
``django.template.TemplateSyntaxError``, with helpful messages, for
|
``django.template.TemplateSyntaxError``, with helpful messages, for
|
||||||
@ -681,7 +687,7 @@ Notes:
|
|||||||
|
|
||||||
* The function returns a ``CurrentTimeNode`` with everything the node needs
|
* The function returns a ``CurrentTimeNode`` with everything the node needs
|
||||||
to know about this tag. In this case, it just passes the argument --
|
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]``.
|
template tag are removed in ``format_string[1:-1]``.
|
||||||
|
|
||||||
* The parsing is very low-level. The Django developers have experimented
|
* 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::
|
Our earlier ``current_time`` function could thus be written like this::
|
||||||
|
|
||||||
# This version of do_current_time takes only a single argument and returns
|
def current_time(format_string):
|
||||||
# a string.
|
return datetime.datetime.now().strftime(format_string)
|
||||||
|
|
||||||
def do_current_time(token):
|
register.simple_tag(current_time)
|
||||||
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)
|
|
||||||
|
|
||||||
In Python 2.4, the decorator syntax also works::
|
In Python 2.4, the decorator syntax also works::
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def 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
|
Inclusion tags
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
3
setup.py
3
setup.py
@ -14,7 +14,8 @@ setup(
|
|||||||
packages = find_packages(exclude=['examples', 'examples.*']),
|
packages = find_packages(exclude=['examples', 'examples.*']),
|
||||||
package_data = {
|
package_data = {
|
||||||
'': ['*.TXT'],
|
'': ['*.TXT'],
|
||||||
'django.conf': ['locale/bn/LC_MESSAGES/*',
|
'django.conf': ['locale/ar/LC_MESSAGES/*',
|
||||||
|
'locale/bn/LC_MESSAGES/*',
|
||||||
'locale/cs/LC_MESSAGES/*',
|
'locale/cs/LC_MESSAGES/*',
|
||||||
'locale/cy/LC_MESSAGES/*',
|
'locale/cy/LC_MESSAGES/*',
|
||||||
'locale/da/LC_MESSAGES/*',
|
'locale/da/LC_MESSAGES/*',
|
||||||
|
@ -28,24 +28,23 @@ API_TESTS = """
|
|||||||
>>> r.save()
|
>>> r.save()
|
||||||
>>> g = User(username='gustav')
|
>>> g = User(username='gustav')
|
||||||
>>> g.save()
|
>>> g.save()
|
||||||
|
|
||||||
>>> i = Issue(num=1)
|
>>> i = Issue(num=1)
|
||||||
>>> i.client = r
|
>>> i.client = r
|
||||||
>>> i.validate()
|
|
||||||
{}
|
|
||||||
>>> i.save()
|
>>> i.save()
|
||||||
|
|
||||||
>>> i2 = Issue(num=2)
|
>>> i2 = Issue(num=2)
|
||||||
>>> i2.client = r
|
>>> i2.client = r
|
||||||
>>> i2.validate()
|
|
||||||
{}
|
|
||||||
>>> i2.save()
|
>>> i2.save()
|
||||||
>>> i2.cc.add(r)
|
>>> i2.cc.add(r)
|
||||||
|
|
||||||
>>> i3 = Issue(num=3)
|
>>> i3 = Issue(num=3)
|
||||||
>>> i3.client = g
|
>>> i3.client = g
|
||||||
>>> i3.validate()
|
|
||||||
{}
|
|
||||||
>>> i3.save()
|
>>> i3.save()
|
||||||
>>> i3.cc.add(r)
|
>>> i3.cc.add(r)
|
||||||
|
|
||||||
>>> from django.db.models.query import Q
|
>>> from django.db.models.query import Q
|
||||||
|
|
||||||
>>> Issue.objects.filter(client=r.id)
|
>>> Issue.objects.filter(client=r.id)
|
||||||
[<Issue: 1>, <Issue: 2>]
|
[<Issue: 1>, <Issue: 2>]
|
||||||
>>> Issue.objects.filter(client=g.id)
|
>>> Issue.objects.filter(client=g.id)
|
||||||
@ -55,8 +54,8 @@ API_TESTS = """
|
|||||||
>>> Issue.objects.filter(cc__id__exact=r.id)
|
>>> Issue.objects.filter(cc__id__exact=r.id)
|
||||||
[<Issue: 2>, <Issue: 3>]
|
[<Issue: 2>, <Issue: 3>]
|
||||||
|
|
||||||
# Queries that combine results from the m2m and the m2o relationship.
|
# These queries combine results from the m2m and the m2o relationships.
|
||||||
# 3 ways of saying the same thing:
|
# They're three ways of saying the same thing.
|
||||||
>>> Issue.objects.filter(Q(cc__id__exact=r.id) | Q(client=r.id))
|
>>> Issue.objects.filter(Q(cc__id__exact=r.id) | Q(client=r.id))
|
||||||
[<Issue: 1>, <Issue: 2>, <Issue: 3>]
|
[<Issue: 1>, <Issue: 2>, <Issue: 3>]
|
||||||
>>> Issue.objects.filter(cc__id__exact=r.id) | Issue.objects.filter(client=r.id)
|
>>> Issue.objects.filter(cc__id__exact=r.id) | Issue.objects.filter(client=r.id)
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
from django.conf import settings
|
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 import template
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
@ -538,10 +542,10 @@ TEMPLATE_TESTS = {
|
|||||||
|
|
||||||
### TIMESINCE TAG ##################################################
|
### TIMESINCE TAG ##################################################
|
||||||
# Default compare with datetime.now()
|
# Default compare with datetime.now()
|
||||||
'timesince01' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=-1)}, '1 minute'),
|
'timesince01' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=-1, seconds = -10)}, '1 minute'),
|
||||||
'timesince02' : ('{{ a|timesince }}', {'a':(datetime.now() - timedelta(days=1))}, '1 day'),
|
'timesince02' : ('{{ a|timesince }}', {'a':(datetime.now() - timedelta(days=1, minutes = 1))}, '1 day'),
|
||||||
'timesince03' : ('{{ a|timesince }}', {'a':(datetime.now() -
|
'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
|
# Compare to a given parameter
|
||||||
'timesince04' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2), 'b':NOW + timedelta(days=1)}, '1 day'),
|
'timesince04' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2), 'b':NOW + timedelta(days=1)}, '1 day'),
|
||||||
@ -552,9 +556,9 @@ TEMPLATE_TESTS = {
|
|||||||
|
|
||||||
### TIMEUNTIL TAG ##################################################
|
### TIMEUNTIL TAG ##################################################
|
||||||
# Default compare with datetime.now()
|
# Default compare with datetime.now()
|
||||||
'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2)}, '2 minutes'),
|
'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'),
|
||||||
'timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1))}, '1 day'),
|
'timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1, seconds = 10))}, '1 day'),
|
||||||
'timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10))}, '8 hours, 10 minutes'),
|
'timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10, seconds = 10))}, '8 hours, 10 minutes'),
|
||||||
|
|
||||||
# Compare to a given parameter
|
# Compare to a given parameter
|
||||||
'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=1), 'b':NOW - timedelta(days=2)}, '1 day'),
|
'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
|
raise Exception, msg
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
settings.configure()
|
|
||||||
run_tests(1, True)
|
run_tests(1, True)
|
||||||
|
@ -154,8 +154,9 @@ class TestRunner:
|
|||||||
# Manually set INSTALLED_APPS to point to the test models.
|
# Manually set INSTALLED_APPS to point to the test models.
|
||||||
settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS + ['.'.join(a) for a in get_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.DEBUG = False
|
||||||
|
settings.USE_I18N = True
|
||||||
|
|
||||||
self.output(0, "Running tests with database %r" % settings.DATABASE_ENGINE)
|
self.output(0, "Running tests with database %r" % settings.DATABASE_ENGINE)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user