mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +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:
		
							
								
								
									
										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,7 +14,8 @@ def compile_messages(locale=None): | ||||
|     basedirs = [os.path.join('conf', 'locale'), 'locale'] | ||||
|     if os.environ.get('DJANGO_SETTINGS_MODULE'): | ||||
|         from django.conf import settings | ||||
|         basedirs += settings.LOCALE_PATHS | ||||
|         if hasattr(settings, 'LOCALE_PATHS'): | ||||
|             basedirs += settings.LOCALE_PATHS | ||||
|  | ||||
|     # Gather existing directories. | ||||
|     basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs))) | ||||
|   | ||||
| @@ -74,59 +74,62 @@ def make_messages(): | ||||
|         if os.path.exists(potfile): | ||||
|             os.unlink(potfile) | ||||
|  | ||||
|         all_files = [] | ||||
|         for (dirpath, dirnames, filenames) in os.walk("."): | ||||
|             for file in filenames: | ||||
|                 if domain == 'djangojs' and file.endswith('.js'): | ||||
|                     if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) | ||||
|             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() | ||||
|                 src = pythonize_re.sub('\n#', src) | ||||
|                 open(os.path.join(dirpath, '%s.py' % file), "wb").write(src) | ||||
|                 thefile = '%s.py' % file | ||||
|                 cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( | ||||
|                     os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile)) | ||||
|                 (stdin, stdout, stderr) = os.popen3(cmd, 't') | ||||
|                 msgs = stdout.read() | ||||
|                 errors = stderr.read() | ||||
|                 if errors: | ||||
|                     print "errors happened while running xgettext on %s" % file | ||||
|                     print errors | ||||
|                     sys.exit(8) | ||||
|                 old = '#: '+os.path.join(dirpath, thefile)[2:] | ||||
|                 new = '#: '+os.path.join(dirpath, file)[2:] | ||||
|                 msgs = msgs.replace(old, new) | ||||
|                 if msgs: | ||||
|                     open(potfile, 'ab').write(msgs) | ||||
|                 os.unlink(os.path.join(dirpath, thefile)) | ||||
|             elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')): | ||||
|                 thefile = file | ||||
|                 if file.endswith('.html'): | ||||
|                     src = open(os.path.join(dirpath, file), "rb").read() | ||||
|                     src = pythonize_re.sub('\n#', src) | ||||
|                     open(os.path.join(dirpath, '%s.py' % file), "wb").write(src) | ||||
|                     thefile = '%s.py' % file | ||||
|                     cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( | ||||
|                         os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile)) | ||||
|                     (stdin, stdout, stderr) = os.popen3(cmd, 't') | ||||
|                     msgs = stdout.read() | ||||
|                     errors = stderr.read() | ||||
|                     if errors: | ||||
|                         print "errors happened while running xgettext on %s" % file | ||||
|                         print errors | ||||
|                         sys.exit(8) | ||||
|                     open(os.path.join(dirpath, thefile), "wb").write(templatize(src)) | ||||
|                 if verbose: | ||||
|                     sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) | ||||
|                 cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( | ||||
|                     domain, os.path.join(dirpath, thefile)) | ||||
|                 (stdin, stdout, stderr) = os.popen3(cmd, 't') | ||||
|                 msgs = stdout.read() | ||||
|                 errors = stderr.read() | ||||
|                 if errors: | ||||
|                     print "errors happened while running xgettext on %s" % file | ||||
|                     print errors | ||||
|                     sys.exit(8) | ||||
|                 if thefile != file: | ||||
|                     old = '#: '+os.path.join(dirpath, thefile)[2:] | ||||
|                     new = '#: '+os.path.join(dirpath, file)[2:] | ||||
|                     msgs = msgs.replace(old, new) | ||||
|                     if msgs: | ||||
|                         open(potfile, 'ab').write(msgs) | ||||
|                 if os.path.exists(potfile): | ||||
|                     # Strip the header | ||||
|                     msgs = '\n'.join(dropwhile(len, msgs.split('\n'))) | ||||
|                 else: | ||||
|                     msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8') | ||||
|                 if msgs: | ||||
|                     open(potfile, 'ab').write(msgs) | ||||
|                 if thefile != file: | ||||
|                     os.unlink(os.path.join(dirpath, thefile)) | ||||
|                 elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')): | ||||
|                     thefile = file | ||||
|                     if file.endswith('.html'): | ||||
|                         src = open(os.path.join(dirpath, file), "rb").read() | ||||
|                         thefile = '%s.py' % file | ||||
|                         open(os.path.join(dirpath, thefile), "wb").write(templatize(src)) | ||||
|                     if verbose: | ||||
|                         sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) | ||||
|                     cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( | ||||
|                         domain, os.path.join(dirpath, thefile)) | ||||
|                     (stdin, stdout, stderr) = os.popen3(cmd, 't') | ||||
|                     msgs = stdout.read() | ||||
|                     errors = stderr.read() | ||||
|                     if errors: | ||||
|                         print "errors happened while running xgettext on %s" % file | ||||
|                         print errors | ||||
|                         sys.exit(8) | ||||
|                     if thefile != file: | ||||
|                         old = '#: '+os.path.join(dirpath, thefile)[2:] | ||||
|                         new = '#: '+os.path.join(dirpath, file)[2:] | ||||
|                         msgs = msgs.replace(old, new) | ||||
|                     if os.path.exists(potfile): | ||||
|                         # Strip the header | ||||
|                         msgs = '\n'.join(dropwhile(len, msgs.split('\n'))) | ||||
|                     else: | ||||
|                         msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8') | ||||
|                     if msgs: | ||||
|                         open(potfile, 'ab').write(msgs) | ||||
|                     if thefile != file: | ||||
|                         os.unlink(os.path.join(dirpath, thefile)) | ||||
|  | ||||
|         if os.path.exists(potfile): | ||||
|             (stdin, stdout, stderr) = os.popen3('msguniq --to-code=utf-8 "%s"' % potfile, 'b') | ||||
|   | ||||
										
											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' | ||||
|  | ||||
| @@ -59,7 +58,7 @@ class SessionBase(object): | ||||
|  | ||||
|     def delete_test_cookie(self): | ||||
|         del self[self.TEST_COOKIE_NAME] | ||||
|          | ||||
|  | ||||
|     def encode(self, session_dict): | ||||
|         "Returns the given session dictionary pickled and encoded as a string." | ||||
|         pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL) | ||||
| @@ -77,28 +76,33 @@ class SessionBase(object): | ||||
|         # just return an empty dictionary (an empty session). | ||||
|         except: | ||||
|             return {} | ||||
|          | ||||
|  | ||||
|     def _get_new_session_key(self): | ||||
|         "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() | ||||
|             session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1), | ||||
|                                   pid, time.time(), settings.SECRET_KEY)).hexdigest() | ||||
|             if not self.exists(session_key): | ||||
|                 break | ||||
|         return session_key | ||||
|          | ||||
|  | ||||
|     def _get_session_key(self): | ||||
|         if self._session_key: | ||||
|             return self._session_key | ||||
|         else: | ||||
|             self._session_key = self._get_new_session_key() | ||||
|             return self._session_key | ||||
|      | ||||
|  | ||||
|     def _set_session_key(self, session_key): | ||||
|         self._session_key = session_key | ||||
|      | ||||
|  | ||||
|     session_key = property(_get_session_key, _set_session_key) | ||||
|  | ||||
|     def _get_session(self): | ||||
| @@ -114,9 +118,9 @@ class SessionBase(object): | ||||
|         return self._session_cache | ||||
|  | ||||
|     _session = property(_get_session) | ||||
|      | ||||
|  | ||||
|     # Methods that child classes must implement. | ||||
|      | ||||
|  | ||||
|     def exists(self, session_key): | ||||
|         """ | ||||
|         Returns True if the given session_key already exists. | ||||
| @@ -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,8 +111,26 @@ 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): | ||||
|     """ | ||||
| @@ -38,21 +142,9 @@ 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): | ||||
|         """ | ||||
|         Returns the script's main help text, as a string. | ||||
| @@ -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,16 +225,9 @@ 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): | ||||
|     """ | ||||
|     Configure the runtime environment. This can also be used by external | ||||
| @@ -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) | ||||
|  | ||||
|     >>> c = {'article': {'section':'News'}} | ||||
|     >>> resolve_variable('article.section', c) | ||||
|     u'News' | ||||
|     >>> resolve_variable('article', c) | ||||
|     {'section': 'News'} | ||||
|     >>> class AClass: pass | ||||
|     >>> c = AClass() | ||||
|     >>> c.article = AClass() | ||||
|     >>> c.article.section = 'News' | ||||
|     >>> resolve_variable('article.section', c) | ||||
|     u'News' | ||||
| 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'}} | ||||
|         >>> Variable('article.section').resolve(c) | ||||
|         u'News' | ||||
|         >>> Variable('article').resolve(c) | ||||
|         {'section': 'News'} | ||||
|         >>> class AClass: pass | ||||
|         >>> c = AClass() | ||||
|         >>> c.article = AClass() | ||||
|         >>> c.article.section = 'News' | ||||
|         >>> 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] | ||||
|     else: | ||||
|      | ||||
|     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,27 +745,27 @@ 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) | ||||
|         except UnicodeDecodeError: | ||||
|             # Failing to convert to unicode can happen sometimes (e.g. debug | ||||
|             # tracebacks). So we allow it in this particular instance. | ||||
|             pass | ||||
|     return current | ||||
|      | ||||
|         if isinstance(current, (basestring, Promise)): | ||||
|             try: | ||||
|                 current = force_unicode(current) | ||||
|             except UnicodeDecodeError: | ||||
|                 # Failing to convert to unicode can happen sometimes (e.g. debug | ||||
|                 # tracebacks). So we allow it in this particular instance. | ||||
|                 pass | ||||
|         return current | ||||
|  | ||||
| class Node(object): | ||||
|     def render(self, context): | ||||
| @@ -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 | ||||
|   | ||||
| @@ -63,6 +63,9 @@ class Movie(models.Model): | ||||
|  | ||||
|     def __unicode__(self): | ||||
|         return self.title | ||||
|          | ||||
| class Score(models.Model): | ||||
|     score = models.FloatField() | ||||
|  | ||||
| __test__ = {'API_TESTS':""" | ||||
| # Create some data: | ||||
| @@ -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)  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user