mirror of
https://github.com/django/django.git
synced 2025-07-06 18:59:13 +00:00
queryset-refactor: Merged changed from trunk up to [6463].
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6466 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
94c320d8a9
commit
7ebf3068c1
6
AUTHORS
6
AUTHORS
@ -114,6 +114,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Enrico <rico.bl@gmail.com>
|
||||
A. Murat Eren <meren@pardus.org.tr>
|
||||
Ludvig Ericson <ludvig.ericson@gmail.com>
|
||||
eriks@win.tue.nl
|
||||
Dirk Eschler <dirk.eschler@gmx.net>
|
||||
Marc Fargas <telenieko@telenieko.com>
|
||||
Szilveszter Farkas <szilveszter.farkas@gmail.com>
|
||||
@ -234,6 +235,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Jay Parlar <parlar@gmail.com>
|
||||
pavithran s <pavithran.s@gmail.com>
|
||||
Barry Pederson <bp@barryp.org>
|
||||
permonik@mesias.brnonet.cz
|
||||
petr.marhoun@gmail.com
|
||||
pgross@thoughtworks.com
|
||||
phaedo <http://phaedo.cx/>
|
||||
@ -312,7 +314,8 @@ answer newbie questions, and generally made Django that much better:
|
||||
Vlado <vlado@labath.org>
|
||||
Milton Waddams
|
||||
wam-djangobug@wamber.net
|
||||
wangchun <yaohua2000@gmail.com>
|
||||
Wang Chun <wangchun@exoweb.net>
|
||||
Filip Wasilewski <filip.wasilewski@gmail.com>
|
||||
Filip Wasilewski <filip.wasilewski@gmail.com>
|
||||
Dan Watson <http://theidioteque.net/>
|
||||
Chris Wesseling <Chris.Wesseling@cwi.nl>
|
||||
@ -321,6 +324,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Rachel Willmer <http://www.willmer.com/kb/>
|
||||
Gary Wilson <gary.wilson@gmail.com>
|
||||
Jakub Wiśniowski <restless.being@gmail.com>
|
||||
Maciej Wiśniowski <pigletto@gmail.com>
|
||||
wojtek
|
||||
ye7cakf02@sneakemail.com
|
||||
ymasuda@ethercube.com
|
||||
|
@ -14,6 +14,7 @@ def compile_messages(locale=None):
|
||||
basedirs = [os.path.join('conf', 'locale'), 'locale']
|
||||
if os.environ.get('DJANGO_SETTINGS_MODULE'):
|
||||
from django.conf import settings
|
||||
if hasattr(settings, 'LOCALE_PATHS'):
|
||||
basedirs += settings.LOCALE_PATHS
|
||||
|
||||
# Gather existing directories.
|
||||
|
@ -74,8 +74,11 @@ def make_messages():
|
||||
if os.path.exists(potfile):
|
||||
os.unlink(potfile)
|
||||
|
||||
all_files = []
|
||||
for (dirpath, dirnames, filenames) in os.walk("."):
|
||||
for file in filenames:
|
||||
all_files.extend([(dirpath, f) for f in filenames])
|
||||
all_files.sort()
|
||||
for dirpath, file in all_files:
|
||||
if domain == 'djangojs' and file.endswith('.js'):
|
||||
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
|
||||
src = open(os.path.join(dirpath, file), "rb").read()
|
||||
|
Binary file not shown.
@ -1,6 +1,7 @@
|
||||
# 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.
|
||||
# Translation of django.po to German
|
||||
#
|
||||
# Copyright (C) 2005-2007,
|
||||
# This file is distributed under the same license as the django package.
|
||||
#
|
||||
msgid ""
|
||||
""
|
||||
@ -1629,76 +1630,76 @@ msgstr "Webseite"
|
||||
msgid "flat pages"
|
||||
msgstr "Webseiten"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:17
|
||||
#: contrib/humanize/templatetags/humanize.py:20
|
||||
msgid "th"
|
||||
msgstr ""
|
||||
msgstr "."
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:17
|
||||
#: contrib/humanize/templatetags/humanize.py:20
|
||||
msgid "st"
|
||||
msgstr ""
|
||||
msgstr "."
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:17
|
||||
#: contrib/humanize/templatetags/humanize.py:20
|
||||
msgid "nd"
|
||||
msgstr ""
|
||||
msgstr "."
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:17
|
||||
#: contrib/humanize/templatetags/humanize.py:20
|
||||
msgid "rd"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:47
|
||||
#, python-format
|
||||
msgid "%(value).1f million"
|
||||
msgid_plural "%(value).1f million"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr "."
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:50
|
||||
#, python-format
|
||||
msgid "%(value).1f billion"
|
||||
msgid_plural "%(value).1f billion"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgid "%(value).1f million"
|
||||
msgid_plural "%(value).1f million"
|
||||
msgstr[0] "%(value).1f Million"
|
||||
msgstr[1] "%(value).1f Millionen"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:53
|
||||
#, python-format
|
||||
msgid "%(value).1f billion"
|
||||
msgid_plural "%(value).1f billion"
|
||||
msgstr[0] "%(value).1f Milliarde"
|
||||
msgstr[1] "%(value).1f Milliarden"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:56
|
||||
#, python-format
|
||||
msgid "%(value).1f trillion"
|
||||
msgid_plural "%(value).1f trillion"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "%(value).1f Billion"
|
||||
msgstr[1] "%(value).1f Billionen"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:68
|
||||
#: contrib/humanize/templatetags/humanize.py:71
|
||||
msgid "one"
|
||||
msgstr "ein"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:68
|
||||
#: contrib/humanize/templatetags/humanize.py:71
|
||||
msgid "two"
|
||||
msgstr "zwei"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:68
|
||||
#: contrib/humanize/templatetags/humanize.py:71
|
||||
msgid "three"
|
||||
msgstr "drei"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:68
|
||||
#: contrib/humanize/templatetags/humanize.py:71
|
||||
msgid "four"
|
||||
msgstr "vier"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:68
|
||||
#: contrib/humanize/templatetags/humanize.py:71
|
||||
msgid "five"
|
||||
msgstr "fünf"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:68
|
||||
#: contrib/humanize/templatetags/humanize.py:71
|
||||
msgid "six"
|
||||
msgstr "sechs"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:68
|
||||
#: contrib/humanize/templatetags/humanize.py:71
|
||||
msgid "seven"
|
||||
msgstr "sieben"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:68
|
||||
#: contrib/humanize/templatetags/humanize.py:71
|
||||
msgid "eight"
|
||||
msgstr "acht"
|
||||
|
||||
#: contrib/humanize/templatetags/humanize.py:68
|
||||
#: contrib/humanize/templatetags/humanize.py:71
|
||||
msgid "nine"
|
||||
msgstr "neun"
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
{% endblock %}
|
||||
{% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %}
|
||||
{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% 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 %}{% if not is_popup %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="../../../../">{% trans "Home" %}</a> ›
|
||||
|
@ -22,7 +22,14 @@
|
||||
{% block branding %}{% endblock %}
|
||||
</div>
|
||||
{% if user.is_authenticated and user.is_staff %}
|
||||
<div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name|escape }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div>
|
||||
<div id="user-tools">
|
||||
{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name|escape }}{% else %}{{ user.username }}{% endif %}</strong>.
|
||||
{% block userlinks %}
|
||||
<a href="{% url django.contrib.admin.views.doc.doc_index %}">{% trans 'Documentation' %}</a>
|
||||
/ <a href="{% url django.contrib.auth.views.password_change %}">{% trans 'Change password' %}</a>
|
||||
/ <a href="{% url django.contrib.auth.views.logout %}">{% trans 'Log out' %}</a>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block nav-global %}{% endblock %}
|
||||
</div>
|
||||
|
@ -7,7 +7,6 @@
|
||||
{% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %}
|
||||
{% block coltype %}{% if ordered_objects %}colMS{% else %}colM{% endif %}{% endblock %}
|
||||
{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% 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 %}{% if not is_popup %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="../../../">{% trans "Home" %}</a> ›
|
||||
|
@ -2,7 +2,6 @@
|
||||
{% load adminmedia admin_list i18n %}
|
||||
{% 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> › {{ cl.opts.verbose_name_plural|capfirst|escape }}</div>{% endblock %}{% endif %}
|
||||
{% block coltype %}flex{% endblock %}
|
||||
{% block content %}
|
||||
|
@ -1,6 +1,5 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% 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> ›
|
||||
|
@ -1,6 +1,5 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% 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> › <a href="../../">{{ module_name|escape }}</a> › <a href="../">{{ object|escape|truncatewords:"18" }}</a> › {% trans 'History' %}</div>
|
||||
{% endblock %}
|
||||
|
@ -1,7 +1,6 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
|
||||
{% block breadcrumbs %}{% load i18n %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> › <a href="../">{% trans "Documentation" %}</a> › {% trans "Bookmarklets" %}</div>{% endblock %}
|
||||
{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block title %}{% trans "Documentation bookmarklets" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -1,7 +1,6 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Documentation</div>{% endblock %}
|
||||
{% block userlinks %}<a href="../password_change/">{% trans 'Change password' %}</a> / <a href="../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block title %}Documentation{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -1,7 +1,6 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Documentation</div>{% endblock %}
|
||||
{% block userlinks %}<a href="../password_change/">{% trans 'Change password' %}</a> / <a href="../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block title %}Please install docutils{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -1,6 +1,5 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
{% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block extrahead %}
|
||||
{{ block.super }}
|
||||
<style type="text/css">
|
||||
|
@ -2,7 +2,6 @@
|
||||
{% load i18n %}
|
||||
{% block coltype %}colSM{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › Models</div>{% endblock %}
|
||||
{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
|
||||
{% block title %}Models{% endblock %}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
{% 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 title %}Template: {{ name|escape }}{% endblock %}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
{% load i18n %}
|
||||
{% block coltype %}colSM{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › filters</div>{% endblock %}
|
||||
{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block title %}Template filters{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -2,7 +2,6 @@
|
||||
{% load i18n %}
|
||||
{% block coltype %}colSM{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › Tags</div>{% endblock %}
|
||||
{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block title %}Template tags{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -1,7 +1,6 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Views</a> › {{ name }}</div>{% endblock %}
|
||||
{% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block title %}View: {{ name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -2,7 +2,6 @@
|
||||
{% load i18n %}
|
||||
{% block coltype %}colSM{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › Views</div>{% endblock %}
|
||||
{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block title %}Views{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -1,6 +1,5 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
{% block userlinks %}<a href="../../doc/">{% trans 'Documentation' %}</a> / {% trans 'Change password' %} / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {% trans 'Password change' %}</div>{% endblock %}
|
||||
|
||||
{% block title %}{% trans 'Password change successful' %}{% endblock %}
|
||||
|
@ -1,6 +1,5 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
{% block userlinks %}<a href="../doc/">{% trans 'Documentation' %}</a> / {% trans 'Change password' %} / <a href="../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> › {% trans 'Password change' %}</div>{% endblock %}
|
||||
|
||||
{% block title %}{% trans 'Password change' %}{% endblock %}
|
||||
|
@ -72,7 +72,7 @@ class FieldWidgetNode(template.Node):
|
||||
default = None
|
||||
|
||||
def __init__(self, bound_field_var):
|
||||
self.bound_field_var = bound_field_var
|
||||
self.bound_field_var = template.Variable(bound_field_var)
|
||||
|
||||
def get_nodelist(cls, klass):
|
||||
if klass not in cls.nodelists:
|
||||
@ -96,7 +96,7 @@ class FieldWidgetNode(template.Node):
|
||||
get_nodelist = classmethod(get_nodelist)
|
||||
|
||||
def render(self, context):
|
||||
bound_field = template.resolve_variable(self.bound_field_var, context)
|
||||
bound_field = self.bound_field_var.resolve(context)
|
||||
|
||||
context.push()
|
||||
context['bound_field'] = bound_field
|
||||
@ -156,10 +156,10 @@ class StackedBoundRelatedObject(BoundRelatedObject):
|
||||
|
||||
class EditInlineNode(template.Node):
|
||||
def __init__(self, rel_var):
|
||||
self.rel_var = rel_var
|
||||
self.rel_var = template.Variable(rel_var)
|
||||
|
||||
def render(self, context):
|
||||
relation = template.resolve_variable(self.rel_var, context)
|
||||
relation = self.rel_var.resolve(context)
|
||||
context.push()
|
||||
if relation.field.rel.edit_inline == models.TABULAR:
|
||||
bound_related_object_class = TabularBoundRelatedObject
|
||||
|
@ -1,6 +1,11 @@
|
||||
from django.db import connection
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
try:
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set # Python 2.3 fallback
|
||||
|
||||
class ModelBackend:
|
||||
"""
|
||||
Authenticate against django.contrib.auth.models.User
|
||||
|
@ -19,6 +19,8 @@ class CommentFormNode(template.Node):
|
||||
ratings_optional=False, ratings_required=False, rating_options='',
|
||||
is_public=True):
|
||||
self.content_type = content_type
|
||||
if obj_id_lookup_var is not None:
|
||||
obj_id_lookup_var = template.Variable(obj_id_lookup_var)
|
||||
self.obj_id_lookup_var, self.obj_id, self.free = obj_id_lookup_var, obj_id, free
|
||||
self.photos_optional, self.photos_required = photos_optional, photos_required
|
||||
self.ratings_optional, self.ratings_required = ratings_optional, ratings_required
|
||||
@ -32,7 +34,7 @@ class CommentFormNode(template.Node):
|
||||
context.push()
|
||||
if self.obj_id_lookup_var is not None:
|
||||
try:
|
||||
self.obj_id = template.resolve_variable(self.obj_id_lookup_var, context)
|
||||
self.obj_id = self.obj_id_lookup_var.resolve(context)
|
||||
except template.VariableDoesNotExist:
|
||||
return ''
|
||||
# Validate that this object ID is valid for this content-type.
|
||||
@ -75,6 +77,8 @@ class CommentFormNode(template.Node):
|
||||
class CommentCountNode(template.Node):
|
||||
def __init__(self, package, module, context_var_name, obj_id, var_name, free):
|
||||
self.package, self.module = package, module
|
||||
if context_var_name is not None:
|
||||
context_var_name = template.Variable(context_var_name)
|
||||
self.context_var_name, self.obj_id = context_var_name, obj_id
|
||||
self.var_name, self.free = var_name, free
|
||||
|
||||
@ -82,7 +86,7 @@ class CommentCountNode(template.Node):
|
||||
from django.conf import settings
|
||||
manager = self.free and FreeComment.objects or Comment.objects
|
||||
if self.context_var_name is not None:
|
||||
self.obj_id = template.resolve_variable(self.context_var_name, context)
|
||||
self.obj_id = self.context_var_name.resolve(context)
|
||||
comment_count = manager.filter(object_id__exact=self.obj_id,
|
||||
content_type__app_label__exact=self.package,
|
||||
content_type__model__exact=self.module, site__id__exact=settings.SITE_ID).count()
|
||||
@ -92,6 +96,8 @@ class CommentCountNode(template.Node):
|
||||
class CommentListNode(template.Node):
|
||||
def __init__(self, package, module, context_var_name, obj_id, var_name, free, ordering, extra_kwargs=None):
|
||||
self.package, self.module = package, module
|
||||
if context_var_name is not None:
|
||||
context_var_name = template.Variable(context_var_name)
|
||||
self.context_var_name, self.obj_id = context_var_name, obj_id
|
||||
self.var_name, self.free = var_name, free
|
||||
self.ordering = ordering
|
||||
@ -102,7 +108,7 @@ class CommentListNode(template.Node):
|
||||
get_list_function = self.free and FreeComment.objects.filter or Comment.objects.get_list_with_karma
|
||||
if self.context_var_name is not None:
|
||||
try:
|
||||
self.obj_id = template.resolve_variable(self.context_var_name, context)
|
||||
self.obj_id = self.context_var_name.resolve(context)
|
||||
except template.VariableDoesNotExist:
|
||||
return ''
|
||||
kwargs = {
|
||||
|
@ -16,7 +16,6 @@ class SessionBase(object):
|
||||
"""
|
||||
Base class for all Session classes.
|
||||
"""
|
||||
|
||||
TEST_COOKIE_NAME = 'testcookie'
|
||||
TEST_COOKIE_VALUE = 'worked'
|
||||
|
||||
@ -82,9 +81,14 @@ class SessionBase(object):
|
||||
"Returns session key that isn't being used."
|
||||
# The random module is seeded when this Apache child is created.
|
||||
# Use settings.SECRET_KEY as added salt.
|
||||
try:
|
||||
pid = os.getpid()
|
||||
except AttributeError:
|
||||
# No getpid() in Jython, for example
|
||||
pid = 1
|
||||
while 1:
|
||||
session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
|
||||
os.getpid(), time.time(), settings.SECRET_KEY)).hexdigest()
|
||||
pid, time.time(), settings.SECRET_KEY)).hexdigest()
|
||||
if not self.exists(session_key):
|
||||
break
|
||||
return session_key
|
||||
@ -140,4 +144,3 @@ class SessionBase(object):
|
||||
Loads the session data and returns a dictionary.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -1,5 +1,12 @@
|
||||
import base64, md5, random, sys, datetime
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import datetime
|
||||
import base64
|
||||
import md5
|
||||
import random
|
||||
import cPickle as pickle
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.conf import settings
|
||||
|
@ -1,16 +1,16 @@
|
||||
from threading import Lock
|
||||
from pprint import pformat
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
except ImportError:
|
||||
from StringIO import StringIO
|
||||
|
||||
from django.core.handlers.base import BaseHandler
|
||||
from django.core import signals
|
||||
from django.dispatch import dispatcher
|
||||
from django.utils import datastructures
|
||||
from django.utils.encoding import force_unicode
|
||||
from django import http
|
||||
from pprint import pformat
|
||||
from shutil import copyfileobj
|
||||
from threading import Lock
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
except ImportError:
|
||||
from StringIO import StringIO
|
||||
|
||||
# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
STATUS_CODE_TEXT = {
|
||||
@ -105,7 +105,8 @@ class WSGIRequest(http.HttpRequest):
|
||||
return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '')
|
||||
|
||||
def is_secure(self):
|
||||
return 'HTTPS' in self.environ and self.environ['HTTPS'] == 'on'
|
||||
return 'wsgi.url_scheme' in self.environ \
|
||||
and self.environ['wsgi.url_scheme'] == 'https'
|
||||
|
||||
def _load_post_and_files(self):
|
||||
# Populates self._post and self._files
|
||||
|
@ -1,18 +1,104 @@
|
||||
import django
|
||||
from django.core.management.base import BaseCommand, CommandError, handle_default_options
|
||||
from optparse import OptionParser
|
||||
import os
|
||||
import sys
|
||||
from imp import find_module
|
||||
|
||||
# For backwards compatibility: get_version() used to be in this module.
|
||||
get_version = django.get_version
|
||||
|
||||
def load_command_class(name):
|
||||
# A cache of loaded commands, so that call_command
|
||||
# doesn't have to reload every time it is called
|
||||
_commands = None
|
||||
|
||||
def find_commands(management_dir):
|
||||
"""
|
||||
Given a command name, returns the Command class instance. Raises
|
||||
ImportError if it doesn't exist.
|
||||
Given a path to a management directory, return a list of all the command names
|
||||
that are available. Returns an empty list if no commands are defined.
|
||||
"""
|
||||
# Let the ImportError propogate.
|
||||
return getattr(__import__('django.core.management.commands.%s' % name, {}, {}, ['Command']), 'Command')()
|
||||
command_dir = os.path.join(management_dir,'commands')
|
||||
try:
|
||||
return [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')]
|
||||
except OSError:
|
||||
return []
|
||||
|
||||
def find_management_module(app_name):
|
||||
"""
|
||||
Determine the path to the management module for the application named,
|
||||
without acutally importing the application or the management module.
|
||||
|
||||
Raises ImportError if the management module cannot be found for any reason.
|
||||
"""
|
||||
parts = app_name.split('.')
|
||||
parts.append('management')
|
||||
parts.reverse()
|
||||
path = None
|
||||
while parts:
|
||||
part = parts.pop()
|
||||
f,path,descr = find_module(part, path and [path] or None)
|
||||
return path
|
||||
|
||||
def load_command_class(app_name, name):
|
||||
"""
|
||||
Given a command name and an application name, returns the Command
|
||||
class instance. All errors raised by the importation process
|
||||
(ImportError, AttributeError) are allowed to propagate.
|
||||
"""
|
||||
return getattr(__import__('%s.management.commands.%s' % (app_name, name),
|
||||
{}, {}, ['Command']), 'Command')()
|
||||
|
||||
def get_commands(load_user_commands=True, project_directory=None):
|
||||
"""
|
||||
Returns a dictionary of commands against the application in which
|
||||
those commands can be found. This works by looking for a
|
||||
management.commands package in django.core, and in each installed
|
||||
application -- if a commands package exists, all commands in that
|
||||
package are registered.
|
||||
|
||||
Core commands are always included; user-defined commands will also
|
||||
be included if ``load_user_commands`` is True. If a project directory
|
||||
is provided, the startproject command will be disabled, and the
|
||||
startapp command will be modified to use that directory.
|
||||
|
||||
The dictionary is in the format {command_name: app_name}. Key-value
|
||||
pairs from this dictionary can then be used in calls to
|
||||
load_command_class(app_name, command_name)
|
||||
|
||||
If a specific version of a command must be loaded (e.g., with the
|
||||
startapp command), the instantiated module can be placed in the
|
||||
dictionary in place of the application name.
|
||||
|
||||
The dictionary is cached on the first call, and reused on subsequent
|
||||
calls.
|
||||
"""
|
||||
global _commands
|
||||
if _commands is None:
|
||||
_commands = dict([(name, 'django.core')
|
||||
for name in find_commands(__path__[0])])
|
||||
if load_user_commands:
|
||||
# Get commands from all installed apps
|
||||
from django.conf import settings
|
||||
for app_name in settings.INSTALLED_APPS:
|
||||
try:
|
||||
path = find_management_module(app_name)
|
||||
_commands.update(dict([(name, app_name)
|
||||
for name in find_commands(path)]))
|
||||
except ImportError:
|
||||
pass # No management module - ignore this app
|
||||
|
||||
if project_directory:
|
||||
# Remove the "startproject" command from self.commands, because
|
||||
# that's a django-admin.py command, not a manage.py command.
|
||||
del _commands['startproject']
|
||||
|
||||
# Override the startapp command so that it always uses the
|
||||
# project_directory, not the current working directory
|
||||
# (which is default).
|
||||
from django.core.management.commands.startapp import ProjectCommand
|
||||
_commands['startapp'] = ProjectCommand(project_directory)
|
||||
|
||||
return _commands
|
||||
|
||||
def call_command(name, *args, **options):
|
||||
"""
|
||||
@ -25,9 +111,27 @@ def call_command(name, *args, **options):
|
||||
call_command('shell', plain=True)
|
||||
call_command('sqlall', 'myapp')
|
||||
"""
|
||||
klass = load_command_class(name)
|
||||
try:
|
||||
app_name = get_commands()[name]
|
||||
if isinstance(app_name, BaseCommand):
|
||||
# If the command is already loaded, use it directly.
|
||||
klass = app_name
|
||||
else:
|
||||
klass = load_command_class(app_name, name)
|
||||
except KeyError:
|
||||
raise CommandError, "Unknown command: %r" % name
|
||||
return klass.execute(*args, **options)
|
||||
|
||||
class LaxOptionParser(OptionParser):
|
||||
"""
|
||||
An option parser that doesn't raise any errors on unknown options.
|
||||
|
||||
This is needed because the --settings and --pythonpath options affect
|
||||
the commands (and thus the options) that are available to the user.
|
||||
"""
|
||||
def error(self, msg):
|
||||
pass
|
||||
|
||||
class ManagementUtility(object):
|
||||
"""
|
||||
Encapsulates the logic of the django-admin.py and manage.py utilities.
|
||||
@ -38,20 +142,8 @@ class ManagementUtility(object):
|
||||
def __init__(self, argv=None):
|
||||
self.argv = argv or sys.argv[:]
|
||||
self.prog_name = os.path.basename(self.argv[0])
|
||||
self.commands = self.default_commands()
|
||||
|
||||
def default_commands(self):
|
||||
"""
|
||||
Returns a dictionary of instances of all available Command classes.
|
||||
|
||||
This works by looking for and loading all Python modules in the
|
||||
django.core.management.commands package.
|
||||
|
||||
The dictionary is in the format {name: command_instance}.
|
||||
"""
|
||||
command_dir = os.path.join(__path__[0], 'commands')
|
||||
names = [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')]
|
||||
return dict([(name, load_command_class(name)) for name in names])
|
||||
self.project_directory = None
|
||||
self.user_commands = False
|
||||
|
||||
def main_help_text(self):
|
||||
"""
|
||||
@ -61,7 +153,7 @@ class ManagementUtility(object):
|
||||
usage.append('Django command line tool, version %s' % django.get_version())
|
||||
usage.append("Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name)
|
||||
usage.append('Available subcommands:')
|
||||
commands = self.commands.keys()
|
||||
commands = get_commands(self.user_commands, self.project_directory).keys()
|
||||
commands.sort()
|
||||
for cmd in commands:
|
||||
usage.append(' %s' % cmd)
|
||||
@ -74,16 +166,33 @@ class ManagementUtility(object):
|
||||
django-admin.py or manage.py) if it can't be found.
|
||||
"""
|
||||
try:
|
||||
return self.commands[subcommand]
|
||||
app_name = get_commands(self.user_commands, self.project_directory)[subcommand]
|
||||
if isinstance(app_name, BaseCommand):
|
||||
# If the command is already loaded, use it directly.
|
||||
klass = app_name
|
||||
else:
|
||||
klass = load_command_class(app_name, subcommand)
|
||||
except KeyError:
|
||||
sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % (subcommand, self.prog_name))
|
||||
sys.exit(1)
|
||||
return klass
|
||||
|
||||
def execute(self):
|
||||
"""
|
||||
Given the command-line arguments, this figures out which subcommand is
|
||||
being run, creates a parser appropriate to that command, and runs it.
|
||||
"""
|
||||
# Preprocess options to extract --settings and --pythonpath. These options
|
||||
# could affect the commands that are available, so they must be processed
|
||||
# early
|
||||
parser = LaxOptionParser(version=get_version(),
|
||||
option_list=BaseCommand.option_list)
|
||||
try:
|
||||
options, args = parser.parse_args(self.argv)
|
||||
handle_default_options(options)
|
||||
except:
|
||||
pass # Ignore any option errors at this point.
|
||||
|
||||
try:
|
||||
subcommand = self.argv[1]
|
||||
except IndexError:
|
||||
@ -91,8 +200,8 @@ class ManagementUtility(object):
|
||||
sys.exit(1)
|
||||
|
||||
if subcommand == 'help':
|
||||
if len(self.argv) > 2:
|
||||
self.fetch_command(self.argv[2]).print_help(self.prog_name, self.argv[2])
|
||||
if len(args) > 2:
|
||||
self.fetch_command(args[2]).print_help(self.prog_name, args[2])
|
||||
else:
|
||||
sys.stderr.write(self.main_help_text() + '\n')
|
||||
sys.exit(1)
|
||||
@ -116,15 +225,8 @@ class ProjectManagementUtility(ManagementUtility):
|
||||
"""
|
||||
def __init__(self, argv, project_directory):
|
||||
super(ProjectManagementUtility, self).__init__(argv)
|
||||
|
||||
# Remove the "startproject" command from self.commands, because
|
||||
# that's a django-admin.py command, not a manage.py command.
|
||||
del self.commands['startproject']
|
||||
|
||||
# Override the startapp command so that it always uses the
|
||||
# project_directory, not the current working directory (which is default).
|
||||
from django.core.management.commands.startapp import ProjectCommand
|
||||
self.commands['startapp'] = ProjectCommand(project_directory)
|
||||
self.project_directory = project_directory
|
||||
self.user_commands = True
|
||||
|
||||
def setup_environ(settings_mod):
|
||||
"""
|
||||
@ -137,7 +239,7 @@ def setup_environ(settings_mod):
|
||||
project_directory, settings_filename = os.path.split(settings_mod.__file__)
|
||||
project_name = os.path.basename(project_directory)
|
||||
settings_name = os.path.splitext(settings_filename)[0]
|
||||
sys.path.append(os.path.join(project_directory, '..'))
|
||||
sys.path.append(os.path.join(project_directory, os.pardir))
|
||||
project_module = __import__(project_name, {}, {}, [''])
|
||||
sys.path.pop()
|
||||
|
||||
|
@ -9,6 +9,17 @@ import os
|
||||
class CommandError(Exception):
|
||||
pass
|
||||
|
||||
def handle_default_options(options):
|
||||
"""
|
||||
Include any default options that all commands should accept
|
||||
here so that ManagementUtility can handle them before searching
|
||||
for user commands.
|
||||
"""
|
||||
if options.settings:
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
|
||||
if options.pythonpath:
|
||||
sys.path.insert(0, options.pythonpath)
|
||||
|
||||
class BaseCommand(object):
|
||||
# Metadata about this command.
|
||||
option_list = (
|
||||
@ -55,10 +66,7 @@ class BaseCommand(object):
|
||||
def run_from_argv(self, argv):
|
||||
parser = self.create_parser(argv[0], argv[1])
|
||||
options, args = parser.parse_args(argv[2:])
|
||||
if options.settings:
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
|
||||
if options.pythonpath:
|
||||
sys.path.insert(0, options.pythonpath)
|
||||
handle_default_options(options)
|
||||
self.execute(*args, **options.__dict__)
|
||||
|
||||
def execute(self, *args, **options):
|
||||
|
@ -16,7 +16,7 @@ class Command(LabelCommand):
|
||||
directory = os.getcwd()
|
||||
# Determine the project_name a bit naively -- by looking at the name of
|
||||
# the parent directory.
|
||||
project_dir = os.path.normpath(os.path.join(directory, '..'))
|
||||
project_dir = os.path.normpath(os.path.join(directory, os.pardir))
|
||||
parent_dir = os.path.basename(project_dir)
|
||||
project_name = os.path.basename(directory)
|
||||
if app_name == project_name:
|
||||
|
@ -245,7 +245,7 @@ class Field(object):
|
||||
if self.default is not NOT_PROVIDED:
|
||||
if callable(self.default):
|
||||
return self.default()
|
||||
return self.default
|
||||
return force_unicode(self.default, strings_only=True)
|
||||
if not self.empty_strings_allowed or (self.null and settings.DATABASE_ENGINE != 'oracle'):
|
||||
return None
|
||||
return ""
|
||||
|
@ -47,8 +47,9 @@ class HttpRequest(object):
|
||||
def get_host(self):
|
||||
"Returns the HTTP host using the environment or request headers."
|
||||
# We try three options, in order of decreasing preference.
|
||||
host = self.META.get('HTTP_X_FORWARDED_HOST', '')
|
||||
if 'HTTP_HOST' in self.META:
|
||||
if 'HTTP_X_FORWARDED_HOST' in self.META:
|
||||
host = self.META['HTTP_X_FORWARDED_HOST']
|
||||
elif 'HTTP_HOST' in self.META:
|
||||
host = self.META['HTTP_HOST']
|
||||
else:
|
||||
# Reconstruct the host using the algorithm from PEP 333.
|
||||
|
@ -54,8 +54,7 @@ class SetRemoteAddrFromForwardedFor(object):
|
||||
except KeyError:
|
||||
return None
|
||||
else:
|
||||
# HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs.
|
||||
# Take just the last one.
|
||||
# See http://bob.pythonmac.org/archives/2005/09/23/apache-x-forwarded-for-caveat/
|
||||
real_ip = real_ip.split(",")[-1].strip()
|
||||
# HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs. The
|
||||
# client's IP will be the first one.
|
||||
real_ip = real_ip.split(",")[0].strip()
|
||||
request.META['REMOTE_ADDR'] = real_ip
|
||||
|
@ -7,7 +7,9 @@ try:
|
||||
except NameError:
|
||||
from sets import Set as set # Python 2.3 fallback
|
||||
|
||||
import copy
|
||||
from itertools import chain
|
||||
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
from django.utils.html import escape
|
||||
from django.utils.translation import ugettext
|
||||
@ -32,6 +34,12 @@ class Widget(object):
|
||||
else:
|
||||
self.attrs = {}
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
obj = copy.copy(self)
|
||||
obj.attrs = self.attrs.copy()
|
||||
memo[id(self)] = obj
|
||||
return obj
|
||||
|
||||
def render(self, name, value, attrs=None):
|
||||
"""
|
||||
Returns this Widget rendered as HTML, as a Unicode string.
|
||||
@ -88,7 +96,7 @@ class PasswordInput(Input):
|
||||
input_type = 'password'
|
||||
|
||||
def __init__(self, attrs=None, render_value=True):
|
||||
self.attrs = attrs or {}
|
||||
super(PasswordInput, self).__init__(attrs)
|
||||
self.render_value = render_value
|
||||
|
||||
def render(self, name, value, attrs=None):
|
||||
@ -105,8 +113,8 @@ class MultipleHiddenInput(HiddenInput):
|
||||
of values.
|
||||
"""
|
||||
def __init__(self, attrs=None, choices=()):
|
||||
super(MultipleHiddenInput, self).__init__(attrs)
|
||||
# choices can be any iterable
|
||||
self.attrs = attrs or {}
|
||||
self.choices = choices
|
||||
|
||||
def render(self, name, value, attrs=None, choices=()):
|
||||
@ -145,9 +153,9 @@ class Textarea(Widget):
|
||||
|
||||
class CheckboxInput(Widget):
|
||||
def __init__(self, attrs=None, check_test=bool):
|
||||
super(CheckboxInput, self).__init__(attrs)
|
||||
# check_test is a callable that takes a value and returns True
|
||||
# if the checkbox should be checked for that value.
|
||||
self.attrs = attrs or {}
|
||||
self.check_test = check_test
|
||||
|
||||
def render(self, name, value, attrs=None):
|
||||
@ -164,7 +172,7 @@ class CheckboxInput(Widget):
|
||||
|
||||
class Select(Widget):
|
||||
def __init__(self, attrs=None, choices=()):
|
||||
self.attrs = attrs or {}
|
||||
super(Select, self).__init__(attrs)
|
||||
# choices can be any iterable, but we may need to render this widget
|
||||
# multiple times. Thus, collapse it into a list so it can be consumed
|
||||
# more than once.
|
||||
@ -203,8 +211,8 @@ class NullBooleanSelect(Select):
|
||||
|
||||
class SelectMultiple(Widget):
|
||||
def __init__(self, attrs=None, choices=()):
|
||||
super(SelectMultiple, self).__init__(attrs)
|
||||
# choices can be any iterable
|
||||
self.attrs = attrs or {}
|
||||
self.choices = choices
|
||||
|
||||
def render(self, name, value, attrs=None, choices=()):
|
||||
|
@ -500,7 +500,7 @@ class SelectField(FormField):
|
||||
selected_html = u''
|
||||
if smart_unicode(value) == str_data:
|
||||
selected_html = u' selected="selected"'
|
||||
output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(display_name)))
|
||||
output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(display_name))))
|
||||
output.append(u' </select>')
|
||||
return u'\n'.join(output)
|
||||
|
||||
@ -612,7 +612,7 @@ class SelectMultipleField(SelectField):
|
||||
selected_html = u''
|
||||
if smart_unicode(value) in str_data_list:
|
||||
selected_html = u' selected="selected"'
|
||||
output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(choice)))
|
||||
output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(choice))))
|
||||
output.append(u' </select>')
|
||||
return u'\n'.join(output)
|
||||
|
||||
|
@ -88,8 +88,6 @@ UNKNOWN_SOURCE="<unknown source>"
|
||||
tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
|
||||
re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END),
|
||||
re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END)))
|
||||
# matches if the string is valid number
|
||||
number_re = re.compile(r'[-+]?(\d+|\d*\.\d+)$')
|
||||
|
||||
# global dictionary of libraries that have been loaded using get_library
|
||||
libraries = {}
|
||||
@ -564,18 +562,19 @@ class FilterExpression(object):
|
||||
elif constant_arg is not None:
|
||||
args.append((False, constant_arg.replace(r'\"', '"')))
|
||||
elif var_arg:
|
||||
args.append((True, var_arg))
|
||||
args.append((True, Variable(var_arg)))
|
||||
filter_func = parser.find_filter(filter_name)
|
||||
self.args_check(filter_name,filter_func, args)
|
||||
filters.append( (filter_func,args))
|
||||
upto = match.end()
|
||||
if upto != len(token):
|
||||
raise TemplateSyntaxError, "Could not parse the remainder: '%s' from '%s'" % (token[upto:], token)
|
||||
self.var, self.filters = var, filters
|
||||
self.filters = filters
|
||||
self.var = Variable(var)
|
||||
|
||||
def resolve(self, context, ignore_failures=False):
|
||||
try:
|
||||
obj = resolve_variable(self.var, context)
|
||||
obj = self.var.resolve(context)
|
||||
except VariableDoesNotExist:
|
||||
if ignore_failures:
|
||||
obj = None
|
||||
@ -595,7 +594,7 @@ class FilterExpression(object):
|
||||
if not lookup:
|
||||
arg_vals.append(arg)
|
||||
else:
|
||||
arg_vals.append(resolve_variable(arg, context))
|
||||
arg_vals.append(arg.resolve(context))
|
||||
obj = func(obj, *arg_vals)
|
||||
return obj
|
||||
|
||||
@ -637,37 +636,98 @@ class FilterExpression(object):
|
||||
def resolve_variable(path, context):
|
||||
"""
|
||||
Returns the resolved variable, which may contain attribute syntax, within
|
||||
the given context. The variable may be a hard-coded string (if it begins
|
||||
and ends with single or double quote marks).
|
||||
the given context.
|
||||
|
||||
Deprecated; use the Variable class instead.
|
||||
"""
|
||||
return Variable(path).resolve(context)
|
||||
|
||||
class Variable(object):
|
||||
"""
|
||||
A template variable, resolvable against a given context. The variable may be
|
||||
a hard-coded string (if it begins and ends with single or double quote
|
||||
marks)::
|
||||
|
||||
>>> c = {'article': {'section':'News'}}
|
||||
>>> resolve_variable('article.section', c)
|
||||
>>> Variable('article.section').resolve(c)
|
||||
u'News'
|
||||
>>> resolve_variable('article', c)
|
||||
>>> Variable('article').resolve(c)
|
||||
{'section': 'News'}
|
||||
>>> class AClass: pass
|
||||
>>> c = AClass()
|
||||
>>> c.article = AClass()
|
||||
>>> c.article.section = 'News'
|
||||
>>> resolve_variable('article.section', c)
|
||||
>>> Variable('article.section').resolve(c)
|
||||
u'News'
|
||||
|
||||
(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
|
||||
"""
|
||||
if number_re.match(path):
|
||||
number_type = '.' in path and float or int
|
||||
current = number_type(path)
|
||||
elif path[0] in ('"', "'") and path[0] == path[-1]:
|
||||
current = path[1:-1]
|
||||
|
||||
def __init__(self, var):
|
||||
self.var = var
|
||||
self.literal = None
|
||||
self.lookups = None
|
||||
|
||||
try:
|
||||
# First try to treat this variable as a number.
|
||||
#
|
||||
# Note that this could cause an OverflowError here that we're not
|
||||
# catching. Since this should only happen at compile time, that's
|
||||
# probably OK.
|
||||
self.literal = float(var)
|
||||
|
||||
# So it's a float... is it an int? If the original value contained a
|
||||
# dot or an "e" then it was a float, not an int.
|
||||
if '.' not in var and 'e' not in var.lower():
|
||||
self.literal = int(self.literal)
|
||||
|
||||
# "2." is invalid
|
||||
if var.endswith('.'):
|
||||
raise ValueError
|
||||
|
||||
except ValueError:
|
||||
# A ValueError means that the variable isn't a number.
|
||||
# If it's wrapped with quotes (single or double), then
|
||||
# we're also dealing with a literal.
|
||||
if var[0] in "\"'" and var[0] == var[-1]:
|
||||
self.literal = var[1:-1]
|
||||
|
||||
else:
|
||||
# Otherwise we'll set self.lookups so that resolve() knows we're
|
||||
# dealing with a bonafide variable
|
||||
self.lookups = tuple(var.split(VARIABLE_ATTRIBUTE_SEPARATOR))
|
||||
|
||||
def resolve(self, context):
|
||||
"""Resolve this variable against a given context."""
|
||||
if self.lookups is not None:
|
||||
# We're dealing with a variable that needs to be resolved
|
||||
return self._resolve_lookup(context)
|
||||
else:
|
||||
# We're dealing with a literal, so it's already been "resolved"
|
||||
return self.literal
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s: %r>" % (self.__class__.__name__, self.var)
|
||||
|
||||
def __str__(self):
|
||||
return self.var
|
||||
|
||||
def _resolve_lookup(self, context):
|
||||
"""
|
||||
Performs resolution of a real variable (i.e. not a literal) against the
|
||||
given context.
|
||||
|
||||
As indicated by the method's name, this method is an implementation
|
||||
detail and shouldn't be called by external code. Use Variable.resolve()
|
||||
instead.
|
||||
"""
|
||||
current = context
|
||||
bits = path.split(VARIABLE_ATTRIBUTE_SEPARATOR)
|
||||
while bits:
|
||||
for bit in self.lookups:
|
||||
try: # dictionary lookup
|
||||
current = current[bits[0]]
|
||||
current = current[bit]
|
||||
except (TypeError, AttributeError, KeyError):
|
||||
try: # attribute lookup
|
||||
current = getattr(current, bits[0])
|
||||
current = getattr(current, bit)
|
||||
if callable(current):
|
||||
if getattr(current, 'alters_data', False):
|
||||
current = settings.TEMPLATE_STRING_IF_INVALID
|
||||
@ -685,19 +745,19 @@ def resolve_variable(path, context):
|
||||
raise
|
||||
except (TypeError, AttributeError):
|
||||
try: # list-index lookup
|
||||
current = current[int(bits[0])]
|
||||
current = current[int(bit)]
|
||||
except (IndexError, # list index out of range
|
||||
ValueError, # invalid literal for int()
|
||||
KeyError, # current is a dict without `int(bits[0])` key
|
||||
KeyError, # current is a dict without `int(bit)` key
|
||||
TypeError, # unsubscriptable object
|
||||
):
|
||||
raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bits[0], current)) # missing attribute
|
||||
raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bit, current)) # missing attribute
|
||||
except Exception, e:
|
||||
if getattr(e, 'silent_variable_failure', False):
|
||||
current = settings.TEMPLATE_STRING_IF_INVALID
|
||||
else:
|
||||
raise
|
||||
del bits[0]
|
||||
|
||||
if isinstance(current, (basestring, Promise)):
|
||||
try:
|
||||
current = force_unicode(current)
|
||||
@ -861,10 +921,10 @@ class Library(object):
|
||||
|
||||
class SimpleNode(Node):
|
||||
def __init__(self, vars_to_resolve):
|
||||
self.vars_to_resolve = vars_to_resolve
|
||||
self.vars_to_resolve = map(Variable, vars_to_resolve)
|
||||
|
||||
def render(self, context):
|
||||
resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve]
|
||||
resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
|
||||
return func(*resolved_vars)
|
||||
|
||||
compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode)
|
||||
@ -883,10 +943,10 @@ class Library(object):
|
||||
|
||||
class InclusionNode(Node):
|
||||
def __init__(self, vars_to_resolve):
|
||||
self.vars_to_resolve = vars_to_resolve
|
||||
self.vars_to_resolve = map(Variable, vars_to_resolve)
|
||||
|
||||
def render(self, context):
|
||||
resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve]
|
||||
resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
|
||||
if takes_context:
|
||||
args = [context] + resolved_vars
|
||||
else:
|
||||
|
@ -1,6 +1,6 @@
|
||||
"Default variable filters"
|
||||
|
||||
from django.template import resolve_variable, Library
|
||||
from django.template import Variable, Library
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext, ungettext
|
||||
from django.utils.encoding import force_unicode, smart_str, iri_to_uri
|
||||
@ -297,7 +297,8 @@ def dictsort(value, arg):
|
||||
Takes a list of dicts, returns that list sorted by the property given in
|
||||
the argument.
|
||||
"""
|
||||
decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value]
|
||||
var_resolve = Variable(arg).resolve
|
||||
decorated = [(var_resolve(item), item) for item in value]
|
||||
decorated.sort()
|
||||
return [item[1] for item in decorated]
|
||||
|
||||
@ -306,7 +307,8 @@ def dictsortreversed(value, arg):
|
||||
Takes a list of dicts, returns that list sorted in reverse order by the
|
||||
property given in the argument.
|
||||
"""
|
||||
decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value]
|
||||
var_resolve = Variable(arg).resolve
|
||||
decorated = [(var_resolve(item), item) for item in value]
|
||||
decorated.sort()
|
||||
decorated.reverse()
|
||||
return [item[1] for item in decorated]
|
||||
|
@ -1,6 +1,6 @@
|
||||
"Default tags used by the template system, available to all templates."
|
||||
|
||||
from django.template import Node, NodeList, Template, Context, resolve_variable
|
||||
from django.template import Node, NodeList, Template, Context, Variable
|
||||
from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END
|
||||
from django.template import get_library, Library, InvalidTemplateLibrary
|
||||
from django.conf import settings
|
||||
@ -30,7 +30,7 @@ class CycleNode(Node):
|
||||
def render(self, context):
|
||||
self.counter += 1
|
||||
value = self.cyclevars[self.counter % self.cyclevars_len]
|
||||
value = resolve_variable(value, context)
|
||||
value = Variable(value).resolve(context)
|
||||
if self.variable_name:
|
||||
context[self.variable_name] = value
|
||||
return value
|
||||
@ -57,12 +57,12 @@ class FilterNode(Node):
|
||||
|
||||
class FirstOfNode(Node):
|
||||
def __init__(self, vars):
|
||||
self.vars = vars
|
||||
self.vars = map(Variable, vars)
|
||||
|
||||
def render(self, context):
|
||||
for var in self.vars:
|
||||
try:
|
||||
value = resolve_variable(var, context)
|
||||
value = var.resolve(context)
|
||||
except VariableDoesNotExist:
|
||||
continue
|
||||
if value:
|
||||
@ -147,7 +147,7 @@ class IfChangedNode(Node):
|
||||
def __init__(self, nodelist, *varlist):
|
||||
self.nodelist = nodelist
|
||||
self._last_seen = None
|
||||
self._varlist = varlist
|
||||
self._varlist = map(Variable, varlist)
|
||||
|
||||
def render(self, context):
|
||||
if 'forloop' in context and context['forloop']['first']:
|
||||
@ -156,7 +156,7 @@ class IfChangedNode(Node):
|
||||
if self._varlist:
|
||||
# Consider multiple parameters.
|
||||
# This automatically behaves like a OR evaluation of the multiple variables.
|
||||
compare_to = [resolve_variable(var, context) for var in self._varlist]
|
||||
compare_to = [var.resolve(context) for var in self._varlist]
|
||||
else:
|
||||
compare_to = self.nodelist.render(context)
|
||||
except VariableDoesNotExist:
|
||||
@ -175,7 +175,7 @@ class IfChangedNode(Node):
|
||||
|
||||
class IfEqualNode(Node):
|
||||
def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
|
||||
self.var1, self.var2 = var1, var2
|
||||
self.var1, self.var2 = Variable(var1), Variable(var2)
|
||||
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
|
||||
self.negate = negate
|
||||
|
||||
@ -184,11 +184,11 @@ class IfEqualNode(Node):
|
||||
|
||||
def render(self, context):
|
||||
try:
|
||||
val1 = resolve_variable(self.var1, context)
|
||||
val1 = self.var1.resolve(context)
|
||||
except VariableDoesNotExist:
|
||||
val1 = None
|
||||
try:
|
||||
val2 = resolve_variable(self.var2, context)
|
||||
val2 = self.var2.resolve(context)
|
||||
except VariableDoesNotExist:
|
||||
val2 = None
|
||||
if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
|
||||
|
@ -1,4 +1,4 @@
|
||||
from django.template import TemplateSyntaxError, TemplateDoesNotExist, resolve_variable
|
||||
from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable
|
||||
from django.template import Library, Node
|
||||
from django.template.loader import get_template, get_template_from_string, find_template_source
|
||||
from django.conf import settings
|
||||
@ -99,11 +99,11 @@ class ConstantIncludeNode(Node):
|
||||
|
||||
class IncludeNode(Node):
|
||||
def __init__(self, template_name):
|
||||
self.template_name = template_name
|
||||
self.template_name = Variable(template_name)
|
||||
|
||||
def render(self, context):
|
||||
try:
|
||||
template_name = resolve_variable(self.template_name, context)
|
||||
template_name = self.template_name.resolve(context)
|
||||
t = get_template(template_name)
|
||||
return t.render(context)
|
||||
except TemplateSyntaxError, e:
|
||||
|
@ -1,4 +1,4 @@
|
||||
from django.template import Node, resolve_variable
|
||||
from django.template import Node, Variable
|
||||
from django.template import TemplateSyntaxError, TokenParser, Library
|
||||
from django.template import TOKEN_TEXT, TOKEN_VAR
|
||||
from django.utils import translation
|
||||
@ -32,11 +32,11 @@ class GetCurrentLanguageBidiNode(Node):
|
||||
|
||||
class TranslateNode(Node):
|
||||
def __init__(self, value, noop):
|
||||
self.value = value
|
||||
self.value = Variable(value)
|
||||
self.noop = noop
|
||||
|
||||
def render(self, context):
|
||||
value = resolve_variable(self.value, context)
|
||||
value = self.value.resolve(context)
|
||||
if self.noop:
|
||||
return value
|
||||
else:
|
||||
|
@ -23,7 +23,7 @@ import time
|
||||
from email.Utils import formatdate
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.encoding import smart_str, iri_to_uri
|
||||
|
||||
cc_delim_re = re.compile(r'\s*,\s*')
|
||||
|
||||
@ -57,6 +57,13 @@ def patch_cache_control(response, **kwargs):
|
||||
cc = dict([dictitem(el) for el in cc])
|
||||
else:
|
||||
cc = {}
|
||||
|
||||
# If there's already a max-age header but we're being asked to set a new
|
||||
# max-age, use the minumum of the two ages. In practice this happens when
|
||||
# a decorator and a piece of middleware both operate on a given view.
|
||||
if 'max-age' in cc and 'max_age' in kwargs:
|
||||
kwargs['max_age'] = min(cc['max-age'], kwargs['max_age'])
|
||||
|
||||
for (k,v) in kwargs.items():
|
||||
cc[k.replace('_', '-')] = v
|
||||
cc = ', '.join([dictvalue(el) for el in cc.items()])
|
||||
@ -118,7 +125,7 @@ def _generate_cache_key(request, headerlist, key_prefix):
|
||||
value = request.META.get(header, None)
|
||||
if value is not None:
|
||||
ctx.update(value)
|
||||
return 'views.decorators.cache.cache_page.%s.%s.%s' % (key_prefix, request.path, ctx.hexdigest())
|
||||
return 'views.decorators.cache.cache_page.%s.%s.%s' % (key_prefix, iri_to_uri(request.path), ctx.hexdigest())
|
||||
|
||||
def get_cache_key(request, key_prefix=None):
|
||||
"""
|
||||
@ -132,7 +139,7 @@ def get_cache_key(request, key_prefix=None):
|
||||
"""
|
||||
if key_prefix is None:
|
||||
key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
|
||||
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, request.path)
|
||||
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, iri_to_uri(request.path))
|
||||
headerlist = cache.get(cache_key, None)
|
||||
if headerlist is not None:
|
||||
return _generate_cache_key(request, headerlist, key_prefix)
|
||||
@ -156,7 +163,7 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None):
|
||||
key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
|
||||
if cache_timeout is None:
|
||||
cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
|
||||
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, request.path)
|
||||
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, iri_to_uri(request.path))
|
||||
if response.has_header('Vary'):
|
||||
headerlist = ['HTTP_'+header.upper().replace('-', '_') for header in vary_delim_re.split(response['Vary'])]
|
||||
cache.set(cache_key, headerlist, cache_timeout)
|
||||
|
@ -149,7 +149,7 @@ class MultiValueDict(dict):
|
||||
dict.__init__(self, key_to_list_mapping)
|
||||
|
||||
def __repr__(self):
|
||||
return "<MultiValueDict: %s>" % dict.__repr__(self)
|
||||
return "<%s: %s>" % (self.__class__.__name__, dict.__repr__(self))
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""
|
||||
|
@ -1,5 +1,6 @@
|
||||
import types
|
||||
import urllib
|
||||
import datetime
|
||||
from django.utils.functional import Promise
|
||||
|
||||
class StrAndUnicode(object):
|
||||
@ -30,7 +31,7 @@ def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
|
||||
|
||||
If strings_only is True, don't convert (some) non-string-like objects.
|
||||
"""
|
||||
if strings_only and isinstance(s, (types.NoneType, int, long)):
|
||||
if strings_only and isinstance(s, (types.NoneType, int, long, datetime.datetime, datetime.time, float)):
|
||||
return s
|
||||
if not isinstance(s, basestring,):
|
||||
if hasattr(s, '__unicode__'):
|
||||
|
@ -2,6 +2,7 @@
|
||||
Internationalization support.
|
||||
"""
|
||||
from django.utils.functional import lazy
|
||||
from django.utils.encoding import force_unicode
|
||||
|
||||
__all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext',
|
||||
'ngettext_lazy', 'string_concat', 'activate', 'deactivate',
|
||||
@ -39,7 +40,7 @@ def delayed_loader(*args, **kwargs):
|
||||
g['real_%s' % name] = getattr(trans, name)
|
||||
|
||||
# Make the originally requested function call on the way out the door.
|
||||
return g[caller](*args, **kwargs)
|
||||
return g['real_%s' % caller](*args, **kwargs)
|
||||
|
||||
g = globals()
|
||||
for name in __all__:
|
||||
@ -63,14 +64,10 @@ def ugettext(message):
|
||||
def ungettext(singular, plural, number):
|
||||
return real_ungettext(singular, plural, number)
|
||||
|
||||
def string_concat(*strings):
|
||||
return real_string_concat(*strings)
|
||||
|
||||
ngettext_lazy = lazy(ngettext, str)
|
||||
gettext_lazy = lazy(gettext, str)
|
||||
ungettext_lazy = lazy(ungettext, unicode)
|
||||
ugettext_lazy = lazy(ugettext, unicode)
|
||||
string_concat = lazy(string_concat, unicode)
|
||||
|
||||
def activate(language):
|
||||
return real_activate(language)
|
||||
@ -108,3 +105,10 @@ def templatize(src):
|
||||
def deactivate_all():
|
||||
return real_deactivate_all()
|
||||
|
||||
def string_concat(*strings):
|
||||
"""
|
||||
Lazy variant of string concatenation, needed for translations that are
|
||||
constructed from multiple parts.
|
||||
"""
|
||||
return u''.join([force_unicode(s) for s in strings])
|
||||
string_concat = lazy(string_concat, unicode)
|
||||
|
@ -13,7 +13,6 @@ ngettext_lazy = ngettext
|
||||
def ungettext(singular, plural, number):
|
||||
return force_unicode(ngettext(singular, plural, number))
|
||||
|
||||
string_concat = lambda *strings: u''.join([force_unicode(el) for el in strings])
|
||||
activate = lambda x: None
|
||||
deactivate = deactivate_all = install = lambda: None
|
||||
get_language = lambda: settings.LANGUAGE_CODE
|
||||
|
@ -516,9 +516,3 @@ def templatize(src):
|
||||
out.write(blankout(t.contents, 'X'))
|
||||
return out.getvalue()
|
||||
|
||||
def string_concat(*strings):
|
||||
""""
|
||||
Lazy variant of string concatenation, needed for translations that are
|
||||
constructed from multiple parts.
|
||||
"""
|
||||
return u''.join([force_unicode(s) for s in strings])
|
||||
|
@ -29,12 +29,12 @@ def serve(request, path, document_root=None, show_indexes=False):
|
||||
newpath = ''
|
||||
for part in path.split('/'):
|
||||
if not part:
|
||||
# strip empty path components
|
||||
# Strip empty path components.
|
||||
continue
|
||||
drive, part = os.path.splitdrive(part)
|
||||
head, part = os.path.split(part)
|
||||
if part in (os.curdir, os.pardir):
|
||||
# strip '.' amd '..' in path
|
||||
# Strip '.' and '..' in path.
|
||||
continue
|
||||
newpath = os.path.join(newpath, part).replace('\\', '/')
|
||||
if newpath and path != newpath:
|
||||
|
@ -163,3 +163,118 @@ storage engine, you have a couple of options.
|
||||
|
||||
.. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB
|
||||
|
||||
|
||||
Oracle Notes
|
||||
============
|
||||
|
||||
Django supports `Oracle Database Server`_ versions 9i and higher. Oracle
|
||||
version 10g or later is required to use Django's ``regex`` and ``iregex`` query
|
||||
operators. You will also need the `cx_Oracle`_ driver, version 4.3.1 or newer.
|
||||
|
||||
.. _`Oracle Database Server`: http://www.oracle.com/
|
||||
.. _`cx_Oracle`: http://cx-oracle.sourceforge.net/
|
||||
|
||||
To run ``python manage.py syncdb``, you'll need to create an Oracle database
|
||||
user with CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE, and CREATE TRIGGER
|
||||
privileges. To run Django's test suite, the user also needs
|
||||
CREATE and DROP DATABASE and CREATE and DROP TABLESPACE privileges.
|
||||
|
||||
Connecting to the Database
|
||||
--------------------------
|
||||
|
||||
Your Django settings.py file should look something like this for Oracle::
|
||||
|
||||
DATABASE_ENGINE = 'oracle'
|
||||
DATABASE_NAME = 'xe'
|
||||
DATABASE_USER = 'a_user'
|
||||
DATABASE_PASSWORD = 'a_password'
|
||||
DATABASE_HOST = ''
|
||||
DATABASE_PORT = ''
|
||||
|
||||
If you don't use a ``tnsnames.ora`` file or a similar naming method that
|
||||
recognizes the SID ("xe" in this example), then fill in both ``DATABASE_HOST``
|
||||
and ``DATABASE_PORT`` like so::
|
||||
|
||||
DATABASE_ENGINE = 'oracle'
|
||||
DATABASE_NAME = 'xe'
|
||||
DATABASE_USER = 'a_user'
|
||||
DATABASE_PASSWORD = 'a_password'
|
||||
DATABASE_HOST = 'dbprod01ned.mycompany.com'
|
||||
DATABASE_PORT = '1540'
|
||||
|
||||
You should supply both ``DATABASE_HOST`` and ``DATABASE_PORT``, or leave both
|
||||
as empty strings.
|
||||
|
||||
Tablespace Options
|
||||
------------------
|
||||
|
||||
A common paradigm for optimizing performance in Oracle-based systems is the
|
||||
use of `tablespaces`_ to organize disk layout. The Oracle backend supports
|
||||
this use case by adding ``db_tablespace`` options to the ``Meta`` and
|
||||
``Field`` classes. (When using a backend that lacks support for tablespaces,
|
||||
these options are ignored.)
|
||||
|
||||
.. _`tablespaces`: http://en.wikipedia.org/wiki/Tablespace
|
||||
|
||||
A tablespace can be specified for the table(s) generated by a model by
|
||||
supplying the ``db_tablespace`` option inside the model's ``Meta`` class.
|
||||
Additionally, the ``db_tablespace`` option can be passed to a ``Field``
|
||||
constructor to specify an alternate tablespace for the ``Field``'s column
|
||||
index. If no index would be created for the column, the ``db_tablespace``
|
||||
option is ignored.
|
||||
|
||||
::
|
||||
|
||||
class TablespaceExample(models.Model):
|
||||
name = models.CharField(maxlength=30, db_index=True, db_tablespace="indexes")
|
||||
data = models.CharField(maxlength=255, db_index=True)
|
||||
edges = models.ManyToManyField(to="self", db_tablespace="indexes")
|
||||
|
||||
class Meta:
|
||||
db_tablespace = "tables"
|
||||
|
||||
In this example, the tables generated by the ``TablespaceExample`` model
|
||||
(i.e., the model table and the many-to-many table) would be stored in the
|
||||
``tables`` tablespace. The index for the name field and the indexes on the
|
||||
many-to-many table would be stored in the ``indexes`` tablespace. The ``data``
|
||||
field would also generate an index, but no tablespace for it is specified, so
|
||||
it would be stored in the model tablespace ``tables`` by default.
|
||||
|
||||
Django does not create the tablespaces for you. Please refer to `Oracle's
|
||||
documentation`_ for details on creating and managing tablespaces.
|
||||
|
||||
.. _`Oracle's documentation`: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7003.htm#SQLRF01403
|
||||
|
||||
Naming Issues
|
||||
-------------
|
||||
|
||||
Oracle imposes a name length limit of 30 characters. To accommodate this, the
|
||||
backend truncates database identifiers to fit, replacing the final four
|
||||
characters of the truncated name with a repeatable MD5 hash value.
|
||||
|
||||
NULL and Empty Strings
|
||||
----------------------
|
||||
|
||||
Django generally prefers to use the empty string ('') rather than NULL, but
|
||||
Oracle treats both identically. To get around this, the Oracle backend
|
||||
coerces the ``null=True`` option on fields that permit the empty string as a
|
||||
value. When fetching from the database, it is assumed that a NULL value in
|
||||
one of these fields really means the empty string, and the data is silently
|
||||
converted to reflect this assumption.
|
||||
|
||||
TextField Limitations
|
||||
---------------------
|
||||
|
||||
The Oracle backend stores ``TextFields`` as ``NCLOB`` columns. Oracle imposes
|
||||
some limitations on the usage of such LOB columns in general:
|
||||
|
||||
* LOB columns may not be used as primary keys.
|
||||
|
||||
* LOB columns may not be used in indexes.
|
||||
|
||||
* LOB columns may not be used in a ``SELECT DISTINCT`` list. This means that
|
||||
attempting to use the ``QuerySet.distinct`` method on a model that
|
||||
includes ``TextField`` columns will result in an error when run against
|
||||
Oracle. A workaround to this is to keep ``TextField`` columns out of any
|
||||
models that you foresee performing ``.distinct`` queries on, and to
|
||||
include the ``TextField`` in a related model instead.
|
||||
|
@ -952,7 +952,7 @@ Example::
|
||||
If you pass ``in_bulk()`` an empty list, you'll get an empty dictionary.
|
||||
|
||||
``iterator()``
|
||||
~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Evaluates the ``QuerySet`` (by performing the query) and returns an
|
||||
`iterator`_ over the results. A ``QuerySet`` typically reads all of
|
||||
@ -1371,11 +1371,6 @@ equivalent::
|
||||
Entry.objects.filter(blog__id=3) # __exact is implied
|
||||
Entry.objects.filter(blog__pk=3) # __pk implies __id__exact
|
||||
|
||||
.. note::
|
||||
Because of this shortcut, you cannot have a field in your model called
|
||||
``pk`` that is not the primary key of the model. It will always be
|
||||
replaced by the name of the model's primary key in queries.
|
||||
|
||||
Lookups that span relationships
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -735,3 +735,32 @@ distribution. It enables tab-completion of ``django-admin.py`` and
|
||||
* Press [TAB] to see all available options.
|
||||
* Type ``sql``, then [TAB], to see all available options whose names start
|
||||
with ``sql``.
|
||||
|
||||
Customized actions
|
||||
==================
|
||||
|
||||
**New in Django development version**
|
||||
|
||||
If you want to add an action of your own to ``manage.py``, you can.
|
||||
Simply add a ``management/commands`` directory to your application.
|
||||
Each python module in that directory will be discovered and registered as
|
||||
a command that can be executed as an action when you run ``manage.py``::
|
||||
|
||||
/fancy_blog
|
||||
__init__.py
|
||||
models.py
|
||||
/management
|
||||
__init__.py
|
||||
/commands
|
||||
__init__.py
|
||||
explode.py
|
||||
views.py
|
||||
|
||||
In this example, ``explode`` command will be made available to any project
|
||||
that includes the ``fancy_blog`` application in ``settings.INSTALLED_APPS``.
|
||||
|
||||
The ``explode.py`` module has only one requirement -- it must define a class
|
||||
called ``Command`` that extends ``django.core.management.base.BaseCommand``.
|
||||
|
||||
For more details on how to define your own commands, look at the code for the
|
||||
existing ``django-admin.py`` commands, in ``/django/core/management/commands``.
|
||||
|
@ -100,31 +100,31 @@ mail_admins()
|
||||
=============
|
||||
|
||||
``django.core.mail.mail_admins()`` is a shortcut for sending an e-mail to the
|
||||
site admins, as defined in the `ADMINS setting`_. Here's the definition::
|
||||
site admins, as defined in the `ADMINS`_ setting. Here's the definition::
|
||||
|
||||
mail_admins(subject, message, fail_silently=False)
|
||||
|
||||
``mail_admins()`` prefixes the subject with the value of the
|
||||
`EMAIL_SUBJECT_PREFIX setting`_, which is ``"[Django] "`` by default.
|
||||
`EMAIL_SUBJECT_PREFIX`_ setting, which is ``"[Django] "`` by default.
|
||||
|
||||
The "From:" header of the e-mail will be the value of the `SERVER_EMAIL setting`_.
|
||||
The "From:" header of the e-mail will be the value of the `SERVER_EMAIL`_ setting.
|
||||
|
||||
This method exists for convenience and readability.
|
||||
|
||||
.. _ADMINS setting: ../settings/#admins
|
||||
.. _EMAIL_SUBJECT_PREFIX setting: ../settings/#email-subject-prefix
|
||||
.. _SERVER_EMAIL setting: ../settings/#server-email
|
||||
.. _ADMINS: ../settings/#admins
|
||||
.. _EMAIL_SUBJECT_PREFIX: ../settings/#email-subject-prefix
|
||||
.. _SERVER_EMAIL: ../settings/#server-email
|
||||
|
||||
mail_managers() function
|
||||
========================
|
||||
|
||||
``django.core.mail.mail_managers()`` is just like ``mail_admins()``, except it
|
||||
sends an e-mail to the site managers, as defined in the `MANAGERS setting`_.
|
||||
sends an e-mail to the site managers, as defined in the `MANAGERS`_ setting.
|
||||
Here's the definition::
|
||||
|
||||
mail_managers(subject, message, fail_silently=False)
|
||||
|
||||
.. _MANAGERS setting: ../settings/#managers
|
||||
.. _MANAGERS: ../settings/#managers
|
||||
|
||||
Examples
|
||||
========
|
||||
@ -225,7 +225,7 @@ optional and can be set at any time prior to calling the ``send()`` method.
|
||||
|
||||
* ``from_email``: The sender's address. Both ``fred@example.com`` and
|
||||
``Fred <fred@example.com>`` forms are legal. If omitted, the
|
||||
``DEFAULT_FROM_EMAIL`` setting is used.
|
||||
`DEFAULT_FROM_EMAIL`_ setting is used.
|
||||
|
||||
* ``to``: A list or tuple of recipient addresses.
|
||||
|
||||
@ -297,6 +297,8 @@ The class has the following methods:
|
||||
|
||||
message.attach_file('/images/weather_map.png')
|
||||
|
||||
.. _DEFAULT_FROM_EMAIL: ../settings/#default-from-email
|
||||
|
||||
Sending alternative content types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -315,7 +317,7 @@ To send a text and HTML combination, you could write::
|
||||
subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
|
||||
text_content = 'This is an important message.'
|
||||
html_content = '<p>This is an <strong>important</strong> message.</p>'
|
||||
msg = EmailMultiAlternatives(subject, text_content, from_email, to)
|
||||
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
|
||||
msg.attach_alternative(html_content, "text/html")
|
||||
msg.send()
|
||||
|
||||
|
@ -800,9 +800,14 @@ specify the page number in the URL in one of two ways:
|
||||
variable. You can iterate over the list provided by ``page_range``
|
||||
to create a link to every page of results.
|
||||
|
||||
These values and lists are is 1-based, not 0-based, so the first page would be
|
||||
These values and lists are 1-based, not 0-based, so the first page would be
|
||||
represented as page ``1``.
|
||||
|
||||
An example of the use of pagination can be found in the `object pagination`_
|
||||
example model.
|
||||
|
||||
.. _`object pagination`: ../models/pagination/
|
||||
|
||||
**New in Django development version:**
|
||||
|
||||
As a special case, you are also permitted to use
|
||||
|
@ -456,10 +456,13 @@ otherwise, they'll be tacked together without whitespace!
|
||||
|
||||
.. admonition:: Mind your charset
|
||||
|
||||
When creating a ``.po`` file with your favorite text editor, first edit
|
||||
When creating a PO file with your favorite text editor, first edit
|
||||
the charset line (search for ``"CHARSET"``) and set it to the charset
|
||||
you'll be using to edit the content. Generally, utf-8 should work for most
|
||||
languages, but ``gettext`` should handle any charset you throw at it.
|
||||
you'll be using to edit the content. Due to the way the ``gettext`` tools
|
||||
work internally and because we want to allow non-ASCII source strings in
|
||||
Django's core and your applications, you **must** use UTF-8 as the encoding
|
||||
for your PO file (this means that everybody will be using the same
|
||||
encoding, which is important when Django processes the PO files).
|
||||
|
||||
To reexamine all source code and templates for new translation strings and
|
||||
update all message files for **all** languages, run this::
|
||||
|
@ -66,6 +66,7 @@ installed.
|
||||
* If you're using SQLite, you'll need pysqlite_. Use version 2.0.3 or higher.
|
||||
|
||||
* If you're using Oracle, you'll need cx_Oracle_, version 4.3.1 or higher.
|
||||
You will also want to read the database-specific notes for the `Oracle backend`_.
|
||||
|
||||
If you plan to use Django's ``manage.py syncdb`` command to
|
||||
automatically create database tables for your models, you'll need to
|
||||
@ -88,6 +89,7 @@ to create a temporary test database.
|
||||
.. _MySQL backend: ../databases/
|
||||
.. _cx_Oracle: http://cx-oracle.sourceforge.net/
|
||||
.. _Oracle: http://www.oracle.com/
|
||||
.. _Oracle backend: ../databases/#oracle-notes
|
||||
.. _testing framework: ../testing/
|
||||
|
||||
Remove any old versions of Django
|
||||
|
@ -1923,11 +1923,22 @@ of the model fields:
|
||||
.. note::
|
||||
|
||||
If you specify ``fields`` when creating a form with ``form_for_model()``,
|
||||
make sure that the fields that are *not* specified can provide default
|
||||
values, or are allowed to have a value of ``None``. If a field isn't
|
||||
specified on a form, the object created from the form can't provide
|
||||
a value for that attribute, which will prevent the new instance from
|
||||
being saved.
|
||||
then the fields that are *not* specified will not be set by the form's
|
||||
``save()`` method. Django will prevent any attempt to save an incomplete
|
||||
model, so if the model does not allow the missing fields to be empty, and
|
||||
does not provide a default value for the missing fields, any attempt to
|
||||
``save()`` a ``form_for_model`` with missing fields will fail. To avoid
|
||||
this failure, you must use ``save(commit=False)`` and manually set any
|
||||
extra required fields::
|
||||
|
||||
instance = form.save(commit=False)
|
||||
instance.required_field = 'new value'
|
||||
instance.save()
|
||||
|
||||
See the `section on saving forms`_ for more details on using
|
||||
``save(commit=False)``.
|
||||
|
||||
.. _section on saving forms: `The save() method`_
|
||||
|
||||
Overriding the default field types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -2064,9 +2075,9 @@ More coming soon
|
||||
================
|
||||
|
||||
That's all the documentation for now. For more, see the file
|
||||
http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/forms/tests.py
|
||||
http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/forms
|
||||
-- the unit tests for ``django.newforms``. This can give you a good idea of
|
||||
what's possible.
|
||||
what's possible. (Each submodule there contains separate tests.)
|
||||
|
||||
If you're really itching to learn and use this library, please be patient.
|
||||
We're working hard on finishing both the code and documentation.
|
||||
|
@ -190,7 +190,7 @@ necessary because some HTML form elements, notably
|
||||
That means you can't change attributes of ``request.POST`` and ``request.GET``
|
||||
directly.
|
||||
|
||||
``QueryDict`` implements the all standard dictionary methods, because it's a
|
||||
``QueryDict`` implements all the standard dictionary methods, because it's a
|
||||
subclass of dictionary. Exceptions are outlined here:
|
||||
|
||||
* ``__getitem__(key)`` -- Returns the value for the given key. If the key
|
||||
|
@ -205,7 +205,7 @@ An API is available to manipulate session data outside of a view::
|
||||
datetime.datetime(2005, 8, 20, 13, 35, 0)
|
||||
>>> s.save()
|
||||
|
||||
If you're using the ``django.contrib.sessions.engine.db`` backend, each
|
||||
If you're using the ``django.contrib.sessions.backends.db`` backend, each
|
||||
session is just a normal Django model. The ``Session`` model is defined in
|
||||
``django/contrib/sessions/models.py``. Because it's a normal model, you can
|
||||
access sessions using the normal Django database API::
|
||||
|
@ -363,7 +363,7 @@ regular expression which will hide from the DEBUG view anything that contains
|
||||
be able to give backtraces without seeing sensitive (or offensive) settings.
|
||||
|
||||
Still, note that there are always going to be sections of your debug output that
|
||||
are inapporpriate for public consumption. File paths, configuration options, and
|
||||
are inappropriate for public consumption. File paths, configuration options, and
|
||||
the like all give attackers extra information about your server. Never deploy a
|
||||
site with ``DEBUG`` turned on.
|
||||
|
||||
|
@ -316,7 +316,7 @@ optional, third positional argument, ``processors``. In this example, the
|
||||
}, [ip_address_processor])
|
||||
return t.render(c)
|
||||
|
||||
Note::
|
||||
.. note::
|
||||
If you're using Django's ``render_to_response()`` shortcut to populate a
|
||||
template with the contents of a dictionary, your template will be passed a
|
||||
``Context`` instance by default (not a ``RequestContext``). To use a
|
||||
@ -928,10 +928,36 @@ current context, available in the ``render`` method::
|
||||
``resolve_variable`` will try to resolve ``blog_entry.date_updated`` and then
|
||||
format it accordingly.
|
||||
|
||||
.. note::
|
||||
The ``resolve_variable()`` function will throw a ``VariableDoesNotExist``
|
||||
exception if it cannot resolve the string passed to it in the current
|
||||
context of the page.
|
||||
.. admonition:: New in development version:
|
||||
|
||||
Variable resolution has changed in the development version of Django.
|
||||
``template.resolve_variable()`` is still available, but has been deprecated
|
||||
in favor of a new ``template.Variable`` class. Using this class will usually
|
||||
be more efficient than calling ``template.resolve_variable``
|
||||
|
||||
To use the ``Variable`` class, simply instantiate it with the name of the
|
||||
variable to be resolved, and then call ``variable.resolve(context)``. So,
|
||||
in the development version, the above example would be more correctly
|
||||
written as:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
class FormatTimeNode(template.Node):
|
||||
def __init__(self, date_to_be_formatted, format_string):
|
||||
self.date_to_be_formatted = **Variable(date_to_be_formatted)**
|
||||
self.format_string = format_string
|
||||
|
||||
def render(self, context):
|
||||
try:
|
||||
actual_date = **self.date_to_be_formatted.resolve(context)**
|
||||
return actual_date.strftime(self.format_string)
|
||||
except template.VariableDoesNotExist:
|
||||
return ''
|
||||
|
||||
Changes are highlighted in bold.
|
||||
|
||||
Variable resolution will throw a ``VariableDoesNotExist`` exception if it cannot
|
||||
resolve the string passed to it in the current context of the page.
|
||||
|
||||
Shortcut for simple tags
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -110,19 +110,22 @@ Conversion functions
|
||||
The ``django.utils.encoding`` module contains a few functions that are handy
|
||||
for converting back and forth between Unicode and bytestrings.
|
||||
|
||||
* ``smart_unicode(s, encoding='utf-8', errors='strict')`` converts its
|
||||
input to a Unicode string. The ``encoding`` parameter specifies the input
|
||||
encoding. (For example, Django uses this internally when processing form
|
||||
input data, which might not be UTF-8 encoded.) The ``errors`` parameter
|
||||
takes any of the values that are accepted by Python's ``unicode()``
|
||||
function for its error handling.
|
||||
* ``smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict')``
|
||||
converts its input to a Unicode string. The ``encoding`` parameter
|
||||
specifies the input encoding. (For example, Django uses this internally
|
||||
when processing form input data, which might not be UTF-8 encoded.) The
|
||||
``strings_only`` parameter, if set to True, will result in Python
|
||||
numbers, booleans and ``None`` not being converted to a string (they keep
|
||||
their original types). The ``errors`` parameter takes any of the values
|
||||
that are accepted by Python's ``unicode()`` function for its error
|
||||
handling.
|
||||
|
||||
If you pass ``smart_unicode()`` an object that has a ``__unicode__``
|
||||
method, it will use that method to do the conversion.
|
||||
|
||||
* ``force_unicode(s, encoding='utf-8', errors='strict')`` is identical to
|
||||
``smart_unicode()`` in almost all cases. The difference is when the
|
||||
first argument is a `lazy translation`_ instance. While
|
||||
* ``force_unicode(s, encoding='utf-8', strings_only=False, errors='strict')``
|
||||
is identical to ``smart_unicode()`` in almost all cases. The difference
|
||||
is when the first argument is a `lazy translation`_ instance. While
|
||||
``smart_unicode()`` preserves lazy translations, ``force_unicode()``
|
||||
forces those objects to a Unicode string (causing the translation to
|
||||
occur). Normally, you'll want to use ``smart_unicode()``. However,
|
||||
@ -132,11 +135,10 @@ for converting back and forth between Unicode and bytestrings.
|
||||
|
||||
* ``smart_str(s, encoding='utf-8', strings_only=False, errors='strict')``
|
||||
is essentially the opposite of ``smart_unicode()``. It forces the first
|
||||
argument to a bytestring. The ``strings_only`` parameter, if set to True,
|
||||
will result in Python integers, booleans and ``None`` not being
|
||||
converted to a string (they keep their original types). This is slightly
|
||||
different semantics from Python's builtin ``str()`` function, but the
|
||||
difference is needed in a few places within Django's internals.
|
||||
argument to a bytestring. The ``strings_only`` parameter has the same
|
||||
behaviour as for ``smart_unicode()`` and ``force_unicode()``. This is
|
||||
slightly different semantics from Python's builtin ``str()`` function,
|
||||
but the difference is needed in a few places within Django's internals.
|
||||
|
||||
Normally, you'll only need to use ``smart_unicode()``. Call it as early as
|
||||
possible on any input data that might be either Unicode or a bytestring, and
|
||||
|
@ -152,7 +152,7 @@ TypeError: 'foo' is an invalid keyword argument for this function
|
||||
>>> a6 = Article(pub_date=datetime(2005, 7, 31))
|
||||
>>> a6.save()
|
||||
>>> a6.headline
|
||||
'Default headline'
|
||||
u'Default headline'
|
||||
|
||||
# For DateTimeFields, Django saves as much precision (in seconds) as you
|
||||
# give it.
|
||||
|
@ -42,7 +42,7 @@ __test__ = {'API_TESTS':"""
|
||||
|
||||
# Access database columns via Python attributes.
|
||||
>>> a.headline
|
||||
'Default headline'
|
||||
u'Default headline'
|
||||
|
||||
# make sure the two dates are sufficiently close
|
||||
>>> d = now - a.pub_date
|
||||
|
@ -64,6 +64,9 @@ class Movie(models.Model):
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
class Score(models.Model):
|
||||
score = models.FloatField()
|
||||
|
||||
__test__ = {'API_TESTS':"""
|
||||
# Create some data:
|
||||
>>> from datetime import datetime
|
||||
@ -83,7 +86,7 @@ __test__ = {'API_TESTS':"""
|
||||
>>> a2 = Article(
|
||||
... author = joe,
|
||||
... headline = "Time to reform copyright",
|
||||
... pub_date = datetime(2006, 6, 16, 13, 00))
|
||||
... pub_date = datetime(2006, 6, 16, 13, 00, 11, 345))
|
||||
>>> a1.save(); a2.save()
|
||||
>>> a1.categories = [sports, op_ed]
|
||||
>>> a2.categories = [music, op_ed]
|
||||
@ -181,7 +184,7 @@ __test__ = {'API_TESTS':"""
|
||||
|
||||
# Serializer output can be restricted to a subset of fields
|
||||
>>> print serializers.serialize("json", Article.objects.all(), fields=('headline','pub_date'))
|
||||
[{"pk": 1, "model": "serializers.article", "fields": {"headline": "Just kidding; I love TV poker", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 2, "model": "serializers.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 3, "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00"}}]
|
||||
[{"pk": 1, "model": "serializers.article", "fields": {"headline": "Just kidding; I love TV poker", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 2, "model": "serializers.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:11"}}, {"pk": 3, "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00"}}]
|
||||
|
||||
# Every string is serialized as a unicode object, also primary key
|
||||
# which is 'varchar'
|
||||
@ -207,4 +210,11 @@ u'G\u0119\u015bl\u0105 ja\u017a\u0144'
|
||||
>>> print list(serializers.deserialize('json', serializers.serialize('json', [mv2])))[0].object.id
|
||||
None
|
||||
|
||||
# Serialization and deserialization of floats:
|
||||
>>> sc = Score(score=3.4)
|
||||
>>> print serializers.serialize("json", [sc])
|
||||
[{"pk": null, "model": "serializers.score", "fields": {"score": 3.4}}]
|
||||
>>> print list(serializers.deserialize('json', serializers.serialize('json', [sc])))[0].object.score
|
||||
3.4
|
||||
|
||||
"""}
|
||||
|
@ -54,7 +54,7 @@ Is updated
|
||||
pre_delete signal, Tom Smith
|
||||
instance.id is not None: True
|
||||
post_delete signal, Tom Smith
|
||||
instance.id is None: True
|
||||
instance.id is None: False
|
||||
|
||||
>>> p2 = Person(first_name='James', last_name='Jones')
|
||||
>>> p2.id = 99999
|
||||
@ -73,7 +73,7 @@ Is created
|
||||
pre_delete signal, James Jones
|
||||
instance.id is not None: True
|
||||
post_delete signal, James Jones
|
||||
instance.id is None: True
|
||||
instance.id is None: False
|
||||
|
||||
>>> Person.objects.all()
|
||||
[<Person: James Jones>]
|
||||
|
0
tests/modeltests/user_commands/__init__.py
Normal file
0
tests/modeltests/user_commands/__init__.py
Normal file
@ -0,0 +1,9 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Dance around like a madman."
|
||||
args = ''
|
||||
requires_model_validation = True
|
||||
|
||||
def handle(self, *args, **options):
|
||||
print "I don't feel like dancing."
|
30
tests/modeltests/user_commands/models.py
Normal file
30
tests/modeltests/user_commands/models.py
Normal file
@ -0,0 +1,30 @@
|
||||
"""
|
||||
37. User-registered management commands
|
||||
|
||||
The manage.py utility provides a number of useful commands for managing a
|
||||
Django project. If you want to add a utility command of your own, you can.
|
||||
|
||||
The user-defined command 'dance' is defined in the management/commands
|
||||
subdirectory of this test application. It is a simple command that responds
|
||||
with a printed message when invoked.
|
||||
|
||||
For more details on how to define your own manage.py commands, look at the
|
||||
django.core.management.commands directory. This directory contains the
|
||||
definitions for the base Django manage.py commands.
|
||||
"""
|
||||
|
||||
__test__ = {'API_TESTS': """
|
||||
>>> from django.core import management
|
||||
|
||||
# Invoke a simple user-defined command
|
||||
>>> management.call_command('dance')
|
||||
I don't feel like dancing.
|
||||
|
||||
# Invoke a command that doesn't exist
|
||||
>>> management.call_command('explode')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
CommandError: Unknown command: 'explode'
|
||||
|
||||
|
||||
"""}
|
@ -8,7 +8,7 @@
|
||||
>>> q['foo']
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
MultiValueDictKeyError: "Key 'foo' not found in <MultiValueDict: {}>"
|
||||
MultiValueDictKeyError: "Key 'foo' not found in <QueryDict: {}>"
|
||||
|
||||
>>> q['something'] = 'bar'
|
||||
Traceback (most recent call last):
|
||||
@ -89,7 +89,7 @@ AttributeError: This QueryDict instance is immutable
|
||||
>>> q['foo']
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
MultiValueDictKeyError: "Key 'foo' not found in <MultiValueDict: {}>"
|
||||
MultiValueDictKeyError: "Key 'foo' not found in <QueryDict: {}>"
|
||||
|
||||
>>> q['name'] = 'john'
|
||||
|
||||
@ -201,7 +201,7 @@ u'bar'
|
||||
>>> q['bar']
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
MultiValueDictKeyError: "Key 'bar' not found in <MultiValueDict: {u'foo': [u'bar']}>"
|
||||
MultiValueDictKeyError: "Key 'bar' not found in <QueryDict: {u'foo': [u'bar']}>"
|
||||
|
||||
>>> q['something'] = 'bar'
|
||||
Traceback (most recent call last):
|
||||
|
@ -0,0 +1,12 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
class TestModel(models.Model):
|
||||
text = models.CharField(max_length=10, default=_('Anything'))
|
||||
|
||||
__test__ = {'API_TESTS': '''
|
||||
>>> tm = TestModel()
|
||||
>>> tm.save()
|
||||
'''
|
||||
}
|
||||
|
@ -30,4 +30,12 @@ True
|
||||
>>> s4 = ugettext_lazy('Some other string')
|
||||
>>> s == s4
|
||||
False
|
||||
|
||||
unicode(string_concat(...)) should not raise a TypeError - #4796
|
||||
|
||||
>>> import django.utils.translation
|
||||
>>> reload(django.utils.translation)
|
||||
<module 'django.utils.translation' from ...>
|
||||
>>> unicode(django.utils.translation.string_concat("dja", "ngo"))
|
||||
u'django'
|
||||
"""
|
||||
|
@ -43,9 +43,9 @@ class MonthArchiveTest(TestCase):
|
||||
author.save()
|
||||
|
||||
# 2004 was a leap year, so it should be weird enough to not cheat
|
||||
first_second_of_feb = datetime(2004, 2, 1, 0, 0, 0)
|
||||
first_second_of_mar = datetime(2004, 3, 1, 0, 0, 0)
|
||||
one_microsecond = timedelta(0, 0, 1)
|
||||
first_second_of_feb = datetime(2004, 2, 1, 0, 0, 1)
|
||||
first_second_of_mar = datetime(2004, 3, 1, 0, 0, 1)
|
||||
two_seconds = timedelta(0, 2, 0)
|
||||
article = Article(title="example", author=author)
|
||||
|
||||
article.date_created = first_second_of_feb
|
||||
@ -53,12 +53,12 @@ class MonthArchiveTest(TestCase):
|
||||
response = self.client.get('/views/date_based/archive_month/2004/02/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
article.date_created = first_second_of_feb-one_microsecond
|
||||
article.date_created = first_second_of_feb-two_seconds
|
||||
article.save()
|
||||
response = self.client.get('/views/date_based/archive_month/2004/02/')
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
article.date_created = first_second_of_mar-one_microsecond
|
||||
article.date_created = first_second_of_mar-two_seconds
|
||||
article.save()
|
||||
response = self.client.get('/views/date_based/archive_month/2004/02/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
Loading…
x
Reference in New Issue
Block a user