mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
gis: Merged revisions 7105-7168 via svnmerge from trunk.
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@7176 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
0b52413cc9
commit
22e016ff6c
3
AUTHORS
3
AUTHORS
@ -56,6 +56,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
David Ascher <http://ascher.ca/>
|
David Ascher <http://ascher.ca/>
|
||||||
Jökull Sólberg Auðunsson <jokullsolberg@gmail.com>
|
Jökull Sólberg Auðunsson <jokullsolberg@gmail.com>
|
||||||
Arthur <avandorp@gmail.com>
|
Arthur <avandorp@gmail.com>
|
||||||
|
David Avsajanishvili <avsd05@gmail.com>
|
||||||
axiak@mit.edu
|
axiak@mit.edu
|
||||||
Jiri Barton
|
Jiri Barton
|
||||||
Ned Batchelder <http://www.nedbatchelder.com/>
|
Ned Batchelder <http://www.nedbatchelder.com/>
|
||||||
@ -70,6 +71,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
boobsd@gmail.com
|
boobsd@gmail.com
|
||||||
Andrew Brehaut <http://brehaut.net/blog>
|
Andrew Brehaut <http://brehaut.net/blog>
|
||||||
brut.alll@gmail.com
|
brut.alll@gmail.com
|
||||||
|
btoll@bestweb.net
|
||||||
Jonathan Buchanan <jonathan.buchanan@gmail.com>
|
Jonathan Buchanan <jonathan.buchanan@gmail.com>
|
||||||
Can Burak Çilingir <canburak@cs.bilgi.edu.tr>
|
Can Burak Çilingir <canburak@cs.bilgi.edu.tr>
|
||||||
Trevor Caira <trevor@caira.com>
|
Trevor Caira <trevor@caira.com>
|
||||||
@ -168,6 +170,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Rob Hudson <http://rob.cogit8.org/>
|
Rob Hudson <http://rob.cogit8.org/>
|
||||||
Jason Huggins <http://www.jrandolph.com/blog/>
|
Jason Huggins <http://www.jrandolph.com/blog/>
|
||||||
Hyun Mi Ae
|
Hyun Mi Ae
|
||||||
|
Ibon <ibonso@gmail.com>
|
||||||
Tom Insam
|
Tom Insam
|
||||||
Baurzhan Ismagulov <ibr@radix50.net>
|
Baurzhan Ismagulov <ibr@radix50.net>
|
||||||
james_027@yahoo.com
|
james_027@yahoo.com
|
||||||
|
@ -48,10 +48,11 @@ LANGUAGES = (
|
|||||||
('en', gettext_noop('English')),
|
('en', gettext_noop('English')),
|
||||||
('es', gettext_noop('Spanish')),
|
('es', gettext_noop('Spanish')),
|
||||||
('es-ar', gettext_noop('Argentinean Spanish')),
|
('es-ar', gettext_noop('Argentinean Spanish')),
|
||||||
|
('eu', gettext_noop('Basque')),
|
||||||
('fa', gettext_noop('Persian')),
|
('fa', gettext_noop('Persian')),
|
||||||
('fi', gettext_noop('Finnish')),
|
('fi', gettext_noop('Finnish')),
|
||||||
('fr', gettext_noop('French')),
|
('fr', gettext_noop('French')),
|
||||||
('ga', gettext_noop('Gaeilge')),
|
('ga', gettext_noop('Irish')),
|
||||||
('gl', gettext_noop('Galician')),
|
('gl', gettext_noop('Galician')),
|
||||||
('hu', gettext_noop('Hungarian')),
|
('hu', gettext_noop('Hungarian')),
|
||||||
('he', gettext_noop('Hebrew')),
|
('he', gettext_noop('Hebrew')),
|
||||||
@ -59,6 +60,7 @@ LANGUAGES = (
|
|||||||
('is', gettext_noop('Icelandic')),
|
('is', gettext_noop('Icelandic')),
|
||||||
('it', gettext_noop('Italian')),
|
('it', gettext_noop('Italian')),
|
||||||
('ja', gettext_noop('Japanese')),
|
('ja', gettext_noop('Japanese')),
|
||||||
|
('ka', gettext_noop('Georgian')),
|
||||||
('ko', gettext_noop('Korean')),
|
('ko', gettext_noop('Korean')),
|
||||||
('km', gettext_noop('Khmer')),
|
('km', gettext_noop('Khmer')),
|
||||||
('kn', gettext_noop('Kannada')),
|
('kn', gettext_noop('Kannada')),
|
||||||
|
BIN
django/conf/locale/eu/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/eu/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
4248
django/conf/locale/eu/LC_MESSAGES/django.po
Normal file
4248
django/conf/locale/eu/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/eu/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/eu/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
117
django/conf/locale/eu/LC_MESSAGES/djangojs.po
Normal file
117
django/conf/locale/eu/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
# Spanish translation for the django-admin JS files.
|
||||||
|
# Copyright (C)
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Django JavaScript 1.0\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-07-14 13:47-0500\n"
|
||||||
|
"PO-Revision-Date: 2007-07-14 13:41-0500\n"
|
||||||
|
"Last-Translator: Jorge Gajon <gajon@gajon.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr ""
|
||||||
|
"Urtarrila Otsaila Martxoa Apirila Maiatza Ekaina Uztaila Abuztua Iraila Urria "
|
||||||
|
"Azaroa Abendua"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr "I A A A O O L"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr "Igandea Astelehene Asteartea Asteazkena Osteguna Ostirala Larunbata"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr "%s Erabilgarri"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr "Denak aukeratu"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr "Gehitu"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr "Ezabatu"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr "%s Aukeratuak"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr "Egin zure aukerak eta click egin "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr "Denak garbitu"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Now"
|
||||||
|
msgstr "Orain"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr "Erlojua"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr "Aukeratu ordu bat"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr "Gauerdia"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr "6 a.m."
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr "Eguerdia"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Atzera"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Gaur"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr "Egutegia"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "Atzo"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr "Bihar"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr "Erakutsi"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr "Izkutatu"
|
BIN
django/conf/locale/ka/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/ka/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
4369
django/conf/locale/ka/LC_MESSAGES/django.po
Normal file
4369
django/conf/locale/ka/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ka/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/ka/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
118
django/conf/locale/ka/LC_MESSAGES/djangojs.po
Normal file
118
django/conf/locale/ka/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# Translation of Django Java-script part to Georgian.
|
||||||
|
# Copyright (C) 2008
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: django 0.97\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2008-02-16 22:31+0400\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: David Avsajanishvili <avsd05@gmail.com>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr "მისაწვდომი %s"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr "ავირჩიოთ ყველა"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr "დავამატოთ"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr "წავშალოთ"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr "არჩეული %s"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr "აირჩიეთ და დააწკაპეთ "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr "გავასუფთავოთ ყველა"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr "იანვარი თებერვალი მარტი აპრილი მაისი ივნისი ივლისი აგვისტო სექტემბერი "
|
||||||
|
"ოქტომბერი ნოემბერი დეკემბერი"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr "კ ო ს ო ხ პ შ"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr "კვირა ორშაბათი სამშაბათი ოთხშაბათი ხუთშაბათი პარასკევი შაბათი"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr "ვაჩვენოთ"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr "დავმალოთ"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Now"
|
||||||
|
msgstr "ახლა"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr "საათი"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr "ავირჩიოთ დრო"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr "შუაღამე"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr "დილის 6 სთ"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr "შუადღე"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "უარი"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "დღეს"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr "კალენდარი"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "გუშინ"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr "ხვალ"
|
@ -1,3 +1,11 @@
|
|||||||
|
import base64
|
||||||
|
import md5
|
||||||
|
import cPickle as pickle
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django import http, template
|
from django import http, template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@ -5,8 +13,6 @@ from django.contrib.auth import authenticate, login
|
|||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
import base64, datetime, md5
|
|
||||||
import cPickle as pickle
|
|
||||||
|
|
||||||
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
||||||
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
||||||
@ -104,4 +110,4 @@ def staff_member_required(view_func):
|
|||||||
else:
|
else:
|
||||||
return _display_login_form(request, ERROR_MESSAGE)
|
return _display_login_form(request, ERROR_MESSAGE)
|
||||||
|
|
||||||
return _checklogin
|
return wraps(view_func)(_checklogin)
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
try:
|
||||||
|
from functools import wraps, update_wrapper
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps, update_wrapper # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.utils.http import urlquote
|
from django.utils.http import urlquote
|
||||||
@ -51,7 +56,7 @@ class _CheckLogin(object):
|
|||||||
self.test_func = test_func
|
self.test_func = test_func
|
||||||
self.login_url = login_url
|
self.login_url = login_url
|
||||||
self.redirect_field_name = redirect_field_name
|
self.redirect_field_name = redirect_field_name
|
||||||
self.__name__ = view_func.__name__
|
update_wrapper(self, view_func)
|
||||||
|
|
||||||
def __get__(self, obj, cls=None):
|
def __get__(self, obj, cls=None):
|
||||||
view_func = self.view_func.__get__(obj, cls)
|
view_func = self.view_func.__get__(obj, cls)
|
||||||
|
@ -8,8 +8,6 @@ from django.utils.translation import get_date_formats
|
|||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.views.generic import date_based
|
from django.views.generic import date_based
|
||||||
import datetime
|
|
||||||
import time
|
|
||||||
|
|
||||||
class CalendarPlugin(DatabrowsePlugin):
|
class CalendarPlugin(DatabrowsePlugin):
|
||||||
def __init__(self, field_names=None):
|
def __init__(self, field_names=None):
|
||||||
|
@ -7,8 +7,6 @@ from django.utils.text import capfirst
|
|||||||
from django.utils.encoding import smart_str, force_unicode
|
from django.utils.encoding import smart_str, force_unicode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.views.generic import date_based
|
from django.views.generic import date_based
|
||||||
import datetime
|
|
||||||
import time
|
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
class FieldChoicePlugin(DatabrowsePlugin):
|
class FieldChoicePlugin(DatabrowsePlugin):
|
||||||
|
@ -2,8 +2,6 @@ from django.db.models import FieldDoesNotExist, DateTimeField
|
|||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.contrib.databrowse.datastructures import EasyModel, EasyChoice
|
from django.contrib.databrowse.datastructures import EasyModel, EasyChoice
|
||||||
import datetime
|
|
||||||
import time
|
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# CHOICES #
|
# CHOICES #
|
||||||
|
@ -3,7 +3,6 @@ Formtools Preview application.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.template.context import RequestContext
|
from django.template.context import RequestContext
|
||||||
|
@ -3,8 +3,6 @@ from django.contrib.formtools import preview
|
|||||||
from django import http
|
from django import http
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.client import Client
|
|
||||||
|
|
||||||
|
|
||||||
success_string = "Done was called!"
|
success_string = "Done was called!"
|
||||||
test_data = {'field1': u'foo',
|
test_data = {'field1': u'foo',
|
||||||
@ -88,6 +86,3 @@ class PreviewTests(TestCase):
|
|||||||
response = self.client.post('/test1/', test_data)
|
response = self.client.post('/test1/', test_data)
|
||||||
self.assertEqual(response.content, success_string)
|
self.assertEqual(response.content, success_string)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
|
@ -2,8 +2,7 @@ from django.utils.translation import ungettext, ugettext as _
|
|||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
from django import template
|
from django import template
|
||||||
from django.template import defaultfilters
|
from django.template import defaultfilters
|
||||||
from django.conf import settings
|
from datetime import date
|
||||||
from datetime import date, timedelta
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
@ -7,7 +7,6 @@ from django.newforms import ValidationError
|
|||||||
from django.newforms.fields import RegexField, CharField, Select, EMPTY_VALUES
|
from django.newforms.fields import RegexField, CharField, Select, EMPTY_VALUES
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode
|
||||||
from django.utils.translation import ugettext
|
from django.utils.translation import ugettext
|
||||||
import re
|
|
||||||
|
|
||||||
class ARProvinceSelect(Select):
|
class ARProvinceSelect(Select):
|
||||||
"""
|
"""
|
||||||
|
@ -7,8 +7,6 @@ from django.newforms import ValidationError
|
|||||||
from django.utils.translation import ugettext
|
from django.utils.translation import ugettext
|
||||||
from django.newforms.fields import RegexField, Select
|
from django.newforms.fields import RegexField, Select
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
class JPPostalCodeField(RegexField):
|
class JPPostalCodeField(RegexField):
|
||||||
"""
|
"""
|
||||||
A form field that validates its input is a Japanese postcode.
|
A form field that validates its input is a Japanese postcode.
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import datetime
|
|
||||||
import base64
|
import base64
|
||||||
import md5
|
import md5
|
||||||
import random
|
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
@ -14,7 +14,6 @@ u'lorem ipsum dolor'
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from django.contrib.webdesign.lorem_ipsum import *
|
from django.contrib.webdesign.lorem_ipsum import *
|
||||||
import datetime
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import doctest
|
import doctest
|
||||||
|
@ -109,7 +109,8 @@ class BaseHandler(object):
|
|||||||
except exceptions.PermissionDenied:
|
except exceptions.PermissionDenied:
|
||||||
return http.HttpResponseForbidden('<h1>Permission denied</h1>')
|
return http.HttpResponseForbidden('<h1>Permission denied</h1>')
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
pass # See http://code.djangoproject.com/ticket/1023
|
# Allow sys.exit() to actually exit. See tickets #1023 and #4701
|
||||||
|
raise
|
||||||
except: # Handle everything else, including SuspiciousOperation, etc.
|
except: # Handle everything else, including SuspiciousOperation, etc.
|
||||||
# Get the exception info now, in case another exception is thrown later.
|
# Get the exception info now, in case another exception is thrown later.
|
||||||
exc_info = sys.exc_info()
|
exc_info = sys.exc_info()
|
||||||
|
@ -30,7 +30,8 @@ class Command(BaseCommand):
|
|||||||
show_traceback = options.get('traceback', False)
|
show_traceback = options.get('traceback', False)
|
||||||
|
|
||||||
# Keep a count of the installed objects and fixtures
|
# Keep a count of the installed objects and fixtures
|
||||||
count = [0, 0]
|
fixture_count = 0
|
||||||
|
object_count = 0
|
||||||
models = set()
|
models = set()
|
||||||
|
|
||||||
humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path'
|
humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path'
|
||||||
@ -65,7 +66,12 @@ class Command(BaseCommand):
|
|||||||
else:
|
else:
|
||||||
print "Skipping fixture '%s': %s is not a known serialization format" % (fixture_name, format)
|
print "Skipping fixture '%s': %s is not a known serialization format" % (fixture_name, format)
|
||||||
|
|
||||||
for fixture_dir in app_fixtures + list(settings.FIXTURE_DIRS) + ['']:
|
if os.path.isabs(fixture_name):
|
||||||
|
fixture_dirs = [fixture_name]
|
||||||
|
else:
|
||||||
|
fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + ['']
|
||||||
|
|
||||||
|
for fixture_dir in fixture_dirs:
|
||||||
if verbosity > 1:
|
if verbosity > 1:
|
||||||
print "Checking %s for fixtures..." % humanize(fixture_dir)
|
print "Checking %s for fixtures..." % humanize(fixture_dir)
|
||||||
|
|
||||||
@ -86,14 +92,14 @@ class Command(BaseCommand):
|
|||||||
transaction.leave_transaction_management()
|
transaction.leave_transaction_management()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
count[1] += 1
|
fixture_count += 1
|
||||||
if verbosity > 0:
|
if verbosity > 0:
|
||||||
print "Installing %s fixture '%s' from %s." % \
|
print "Installing %s fixture '%s' from %s." % \
|
||||||
(format, fixture_name, humanize(fixture_dir))
|
(format, fixture_name, humanize(fixture_dir))
|
||||||
try:
|
try:
|
||||||
objects = serializers.deserialize(format, fixture)
|
objects = serializers.deserialize(format, fixture)
|
||||||
for obj in objects:
|
for obj in objects:
|
||||||
count[0] += 1
|
object_count += 1
|
||||||
models.add(obj.object.__class__)
|
models.add(obj.object.__class__)
|
||||||
obj.save()
|
obj.save()
|
||||||
label_found = True
|
label_found = True
|
||||||
@ -113,7 +119,7 @@ class Command(BaseCommand):
|
|||||||
print "No %s fixture '%s' in %s." % \
|
print "No %s fixture '%s' in %s." % \
|
||||||
(format, fixture_name, humanize(fixture_dir))
|
(format, fixture_name, humanize(fixture_dir))
|
||||||
|
|
||||||
if count[0] > 0:
|
if object_count > 0:
|
||||||
sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
|
sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
|
||||||
if sequence_sql:
|
if sequence_sql:
|
||||||
if verbosity > 1:
|
if verbosity > 1:
|
||||||
@ -124,9 +130,9 @@ class Command(BaseCommand):
|
|||||||
transaction.commit()
|
transaction.commit()
|
||||||
transaction.leave_transaction_management()
|
transaction.leave_transaction_management()
|
||||||
|
|
||||||
if count[0] == 0:
|
if object_count == 0:
|
||||||
if verbosity >= 2:
|
if verbosity >= 2:
|
||||||
print "No fixtures found."
|
print "No fixtures found."
|
||||||
else:
|
else:
|
||||||
if verbosity > 0:
|
if verbosity > 0:
|
||||||
print "Installed %d object(s) from %d fixture(s)" % tuple(count)
|
print "Installed %d object(s) from %d fixture(s)" % (object_count, fixture_count)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from django.core.management.base import AppCommand
|
from django.core.management.base import AppCommand
|
||||||
|
|
||||||
class Command(AppCommand):
|
class Command(AppCommand):
|
||||||
help = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)."
|
help = "Prints the CREATE TABLE, custom SQL and CREATE INDEX SQL statements for the given model module name(s)."
|
||||||
|
|
||||||
output_transaction = True
|
output_transaction = True
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ Serialize data to/from JSON
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from django.utils import simplejson
|
from django.utils import simplejson
|
||||||
from django.utils.simplejson import decoder
|
|
||||||
from django.core.serializers.python import Serializer as PythonSerializer
|
from django.core.serializers.python import Serializer as PythonSerializer
|
||||||
from django.core.serializers.python import Deserializer as PythonDeserializer
|
from django.core.serializers.python import Deserializer as PythonDeserializer
|
||||||
try:
|
try:
|
||||||
|
@ -4,7 +4,6 @@ YAML serializer.
|
|||||||
Requires PyYaml (http://pyyaml.org/), but that's checked for in __init__.
|
Requires PyYaml (http://pyyaml.org/), but that's checked for in __init__.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.core.serializers.python import Serializer as PythonSerializer
|
from django.core.serializers.python import Serializer as PythonSerializer
|
||||||
from django.core.serializers.python import Deserializer as PythonDeserializer
|
from django.core.serializers.python import Deserializer as PythonDeserializer
|
||||||
|
@ -21,7 +21,6 @@ if (version < (1,2,1) or (version[:3] == (1, 2, 1) and
|
|||||||
|
|
||||||
from MySQLdb.converters import conversions
|
from MySQLdb.converters import conversions
|
||||||
from MySQLdb.constants import FIELD_TYPE
|
from MySQLdb.constants import FIELD_TYPE
|
||||||
import types
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# Raise exceptions for database warnings if DEBUG is on
|
# Raise exceptions for database warnings if DEBUG is on
|
||||||
|
@ -27,6 +27,11 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||||||
def deferrable_sql(self):
|
def deferrable_sql(self):
|
||||||
return " DEFERRABLE INITIALLY DEFERRED"
|
return " DEFERRABLE INITIALLY DEFERRED"
|
||||||
|
|
||||||
|
def field_cast_sql(self, db_type):
|
||||||
|
if db_type == 'inet':
|
||||||
|
return 'HOST(%s)'
|
||||||
|
return '%s'
|
||||||
|
|
||||||
def last_insert_id(self, cursor, table_name, pk_name):
|
def last_insert_id(self, cursor, table_name, pk_name):
|
||||||
cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (table_name, pk_name))
|
cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (table_name, pk_name))
|
||||||
return cursor.fetchone()[0]
|
return cursor.fetchone()[0]
|
||||||
|
@ -41,7 +41,9 @@ class ModelBase(type):
|
|||||||
|
|
||||||
# Build complete list of parents
|
# Build complete list of parents
|
||||||
for base in parents:
|
for base in parents:
|
||||||
if base is not Model:
|
# Things without _meta aren't functional models, so they're
|
||||||
|
# uninteresting parents.
|
||||||
|
if hasattr(base, '_meta'):
|
||||||
new_class._meta.parents.append(base)
|
new_class._meta.parents.append(base)
|
||||||
new_class._meta.parents.extend(base._meta.parents)
|
new_class._meta.parents.extend(base._meta.parents)
|
||||||
|
|
||||||
@ -133,13 +135,16 @@ class Model(object):
|
|||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not self.__eq__(other)
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(self._get_pk_val())
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs)
|
dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs)
|
||||||
|
|
||||||
# There is a rather weird disparity here; if kwargs, it's set, then args
|
# There is a rather weird disparity here; if kwargs, it's set, then args
|
||||||
# overrides it. It should be one or the other; don't duplicate the work
|
# overrides it. It should be one or the other; don't duplicate the work
|
||||||
# The reason for the kwargs check is that standard iterator passes in by
|
# The reason for the kwargs check is that standard iterator passes in by
|
||||||
# args, and nstantiation for iteration is 33% faster.
|
# args, and instantiation for iteration is 33% faster.
|
||||||
args_len = len(args)
|
args_len = len(args)
|
||||||
if args_len > len(self._meta.fields):
|
if args_len > len(self._meta.fields):
|
||||||
# Daft, but matches old exception sans the err msg.
|
# Daft, but matches old exception sans the err msg.
|
||||||
|
@ -228,7 +228,11 @@ class Field(object):
|
|||||||
value = int(value)
|
value = int(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError("The __year lookup type requires an integer argument")
|
raise ValueError("The __year lookup type requires an integer argument")
|
||||||
return ['%s-01-01 00:00:00' % value, '%s-12-31 23:59:59.999999' % value]
|
if settings.DATABASE_ENGINE == 'sqlite3':
|
||||||
|
first = '%s-01-01'
|
||||||
|
else:
|
||||||
|
first = '%s-01-01 00:00:00'
|
||||||
|
return [first % value, '%s-12-31 23:59:59.999999' % value]
|
||||||
raise TypeError("Field has invalid lookup: %s" % lookup_type)
|
raise TypeError("Field has invalid lookup: %s" % lookup_type)
|
||||||
|
|
||||||
def has_default(self):
|
def has_default(self):
|
||||||
@ -451,6 +455,9 @@ class BooleanField(Field):
|
|||||||
kwargs['blank'] = True
|
kwargs['blank'] = True
|
||||||
Field.__init__(self, *args, **kwargs)
|
Field.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "BooleanField"
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value in (True, False): return value
|
if value in (True, False): return value
|
||||||
if value in ('t', 'True', '1'): return True
|
if value in ('t', 'True', '1'): return True
|
||||||
@ -469,6 +476,9 @@ class CharField(Field):
|
|||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.TextField]
|
return [oldforms.TextField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "CharField"
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, basestring):
|
||||||
return value
|
return value
|
||||||
@ -499,6 +509,9 @@ class DateField(Field):
|
|||||||
kwargs['blank'] = True
|
kwargs['blank'] = True
|
||||||
Field.__init__(self, verbose_name, name, **kwargs)
|
Field.__init__(self, verbose_name, name, **kwargs)
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "DateField"
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
@ -568,6 +581,9 @@ class DateField(Field):
|
|||||||
return super(DateField, self).formfield(**defaults)
|
return super(DateField, self).formfield(**defaults)
|
||||||
|
|
||||||
class DateTimeField(DateField):
|
class DateTimeField(DateField):
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "DateTimeField"
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
@ -638,6 +654,9 @@ class DecimalField(Field):
|
|||||||
self.max_digits, self.decimal_places = max_digits, decimal_places
|
self.max_digits, self.decimal_places = max_digits, decimal_places
|
||||||
Field.__init__(self, verbose_name, name, **kwargs)
|
Field.__init__(self, verbose_name, name, **kwargs)
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "DecimalField"
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
@ -697,9 +716,6 @@ class EmailField(CharField):
|
|||||||
kwargs['max_length'] = kwargs.get('max_length', 75)
|
kwargs['max_length'] = kwargs.get('max_length', 75)
|
||||||
CharField.__init__(self, *args, **kwargs)
|
CharField.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
def get_internal_type(self):
|
|
||||||
return "CharField"
|
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.EmailField]
|
return [oldforms.EmailField]
|
||||||
|
|
||||||
@ -717,6 +733,9 @@ class FileField(Field):
|
|||||||
kwargs['max_length'] = kwargs.get('max_length', 100)
|
kwargs['max_length'] = kwargs.get('max_length', 100)
|
||||||
Field.__init__(self, verbose_name, name, **kwargs)
|
Field.__init__(self, verbose_name, name, **kwargs)
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "FileField"
|
||||||
|
|
||||||
def get_db_prep_save(self, value):
|
def get_db_prep_save(self, value):
|
||||||
"Returns field's value prepared for saving into a database."
|
"Returns field's value prepared for saving into a database."
|
||||||
# Need to convert UploadedFile objects provided via a form to unicode for database insertion
|
# Need to convert UploadedFile objects provided via a form to unicode for database insertion
|
||||||
@ -826,12 +845,18 @@ class FilePathField(Field):
|
|||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [curry(oldforms.FilePathField, path=self.path, match=self.match, recursive=self.recursive)]
|
return [curry(oldforms.FilePathField, path=self.path, match=self.match, recursive=self.recursive)]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "FilePathField"
|
||||||
|
|
||||||
class FloatField(Field):
|
class FloatField(Field):
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.FloatField]
|
return [oldforms.FloatField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "FloatField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.FloatField}
|
defaults = {'form_class': forms.FloatField}
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
@ -854,6 +879,9 @@ class ImageField(FileField):
|
|||||||
if not self.height_field:
|
if not self.height_field:
|
||||||
setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self))
|
setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self))
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "ImageField"
|
||||||
|
|
||||||
def save_file(self, new_data, new_object, original_object, change, rel, save=True):
|
def save_file(self, new_data, new_object, original_object, change, rel, save=True):
|
||||||
FileField.save_file(self, new_data, new_object, original_object, change, rel, save)
|
FileField.save_file(self, new_data, new_object, original_object, change, rel, save)
|
||||||
# If the image has height and/or width field(s) and they haven't
|
# If the image has height and/or width field(s) and they haven't
|
||||||
@ -876,6 +904,9 @@ class IntegerField(Field):
|
|||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.IntegerField]
|
return [oldforms.IntegerField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "IntegerField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.IntegerField}
|
defaults = {'form_class': forms.IntegerField}
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
@ -890,6 +921,9 @@ class IPAddressField(Field):
|
|||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.IPAddressField]
|
return [oldforms.IPAddressField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "IPAddressField"
|
||||||
|
|
||||||
def validate(self, field_data, all_data):
|
def validate(self, field_data, all_data):
|
||||||
validators.isValidIPAddress4(field_data, None)
|
validators.isValidIPAddress4(field_data, None)
|
||||||
|
|
||||||
@ -904,6 +938,9 @@ class NullBooleanField(Field):
|
|||||||
kwargs['null'] = True
|
kwargs['null'] = True
|
||||||
Field.__init__(self, *args, **kwargs)
|
Field.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "NullBooleanField"
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value in (None, True, False): return value
|
if value in (None, True, False): return value
|
||||||
if value in ('None'): return None
|
if value in ('None'): return None
|
||||||
@ -923,6 +960,9 @@ class PhoneNumberField(IntegerField):
|
|||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.PhoneNumberField]
|
return [oldforms.PhoneNumberField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "PhoneNumberField"
|
||||||
|
|
||||||
def validate(self, field_data, all_data):
|
def validate(self, field_data, all_data):
|
||||||
validators.isValidPhone(field_data, all_data)
|
validators.isValidPhone(field_data, all_data)
|
||||||
|
|
||||||
@ -936,6 +976,9 @@ class PositiveIntegerField(IntegerField):
|
|||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.PositiveIntegerField]
|
return [oldforms.PositiveIntegerField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "PositiveIntegerField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'min_value': 0}
|
defaults = {'min_value': 0}
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
@ -945,6 +988,9 @@ class PositiveSmallIntegerField(IntegerField):
|
|||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.PositiveSmallIntegerField]
|
return [oldforms.PositiveSmallIntegerField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "PositiveSmallIntegerField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'min_value': 0}
|
defaults = {'min_value': 0}
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
@ -959,14 +1005,23 @@ class SlugField(CharField):
|
|||||||
kwargs['db_index'] = True
|
kwargs['db_index'] = True
|
||||||
super(SlugField, self).__init__(*args, **kwargs)
|
super(SlugField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "SlugField"
|
||||||
|
|
||||||
class SmallIntegerField(IntegerField):
|
class SmallIntegerField(IntegerField):
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.SmallIntegerField]
|
return [oldforms.SmallIntegerField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "SmallIntegerField"
|
||||||
|
|
||||||
class TextField(Field):
|
class TextField(Field):
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.LargeTextField]
|
return [oldforms.LargeTextField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "TextField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'widget': forms.Textarea}
|
defaults = {'widget': forms.Textarea}
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
@ -980,6 +1035,9 @@ class TimeField(Field):
|
|||||||
kwargs['editable'] = False
|
kwargs['editable'] = False
|
||||||
Field.__init__(self, verbose_name, name, **kwargs)
|
Field.__init__(self, verbose_name, name, **kwargs)
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "TimeField"
|
||||||
|
|
||||||
def get_db_prep_lookup(self, lookup_type, value):
|
def get_db_prep_lookup(self, lookup_type, value):
|
||||||
if settings.DATABASE_ENGINE == 'oracle':
|
if settings.DATABASE_ENGINE == 'oracle':
|
||||||
# Oracle requires a date in order to parse.
|
# Oracle requires a date in order to parse.
|
||||||
@ -1044,9 +1102,6 @@ class URLField(CharField):
|
|||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.URLField]
|
return [oldforms.URLField]
|
||||||
|
|
||||||
def get_internal_type(self):
|
|
||||||
return "CharField"
|
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.URLField, 'verify_exists': self.verify_exists}
|
defaults = {'form_class': forms.URLField, 'verify_exists': self.verify_exists}
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
@ -1056,6 +1111,9 @@ class USStateField(Field):
|
|||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.USStateField]
|
return [oldforms.USStateField]
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "USStateField"
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
from django.contrib.localflavor.us.forms import USStateSelect
|
from django.contrib.localflavor.us.forms import USStateSelect
|
||||||
defaults = {'widget': USStateSelect}
|
defaults = {'widget': USStateSelect}
|
||||||
@ -1067,9 +1125,6 @@ class XMLField(TextField):
|
|||||||
self.schema_path = schema_path
|
self.schema_path = schema_path
|
||||||
Field.__init__(self, verbose_name, name, **kwargs)
|
Field.__init__(self, verbose_name, name, **kwargs)
|
||||||
|
|
||||||
def get_internal_type(self):
|
|
||||||
return "TextField"
|
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [curry(oldforms.XMLLargeTextField, schema_path=self.schema_path)]
|
return [curry(oldforms.XMLLargeTextField, schema_path=self.schema_path)]
|
||||||
|
|
||||||
@ -1080,8 +1135,5 @@ class OrderingField(IntegerField):
|
|||||||
kwargs['null'] = True
|
kwargs['null'] = True
|
||||||
IntegerField.__init__(self, **kwargs )
|
IntegerField.__init__(self, **kwargs )
|
||||||
|
|
||||||
def get_internal_type(self):
|
|
||||||
return "IntegerField"
|
|
||||||
|
|
||||||
def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
|
def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
|
||||||
return [oldforms.HiddenField(name_prefix + self.name)]
|
return [oldforms.HiddenField(name_prefix + self.name)]
|
||||||
|
@ -23,26 +23,64 @@ RECURSIVE_RELATIONSHIP_CONSTANT = 'self'
|
|||||||
|
|
||||||
pending_lookups = {}
|
pending_lookups = {}
|
||||||
|
|
||||||
def add_lookup(rel_cls, field):
|
def add_lazy_relation(cls, field, relation):
|
||||||
name = field.rel.to
|
"""
|
||||||
module = rel_cls.__module__
|
Adds a lookup on ``cls`` when a related field is defined using a string,
|
||||||
key = (module, name)
|
i.e.::
|
||||||
# Has the model already been loaded?
|
|
||||||
# If so, resolve the string reference right away
|
class MyModel(Model):
|
||||||
model = get_model(rel_cls._meta.app_label, field.rel.to, False)
|
fk = ForeignKey("AnotherModel")
|
||||||
|
|
||||||
|
This string can be:
|
||||||
|
|
||||||
|
* RECURSIVE_RELATIONSHIP_CONSTANT (i.e. "self") to indicate a recursive
|
||||||
|
relation.
|
||||||
|
|
||||||
|
* The name of a model (i.e "AnotherModel") to indicate another model in
|
||||||
|
the same app.
|
||||||
|
|
||||||
|
* An app-label and model name (i.e. "someapp.AnotherModel") to indicate
|
||||||
|
another model in a different app.
|
||||||
|
|
||||||
|
If the other model hasn't yet been loaded -- almost a given if you're using
|
||||||
|
lazy relationships -- then the relation won't be set up until the
|
||||||
|
class_prepared signal fires at the end of model initialization.
|
||||||
|
"""
|
||||||
|
# Check for recursive relations
|
||||||
|
if relation == RECURSIVE_RELATIONSHIP_CONSTANT:
|
||||||
|
app_label = cls._meta.app_label
|
||||||
|
model_name = cls.__name__
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Look for an "app.Model" relation
|
||||||
|
try:
|
||||||
|
app_label, model_name = relation.split(".")
|
||||||
|
except ValueError:
|
||||||
|
# If we can't split, assume a model in current app
|
||||||
|
app_label = cls._meta.app_label
|
||||||
|
model_name = relation
|
||||||
|
|
||||||
|
# Try to look up the related model, and if it's already loaded resolve the
|
||||||
|
# string right away. If get_model returns None, it means that the related
|
||||||
|
# model isn't loaded yet, so we need to pend the relation until the class
|
||||||
|
# is prepared.
|
||||||
|
model = get_model(app_label, model_name, False)
|
||||||
if model:
|
if model:
|
||||||
field.rel.to = model
|
field.rel.to = model
|
||||||
field.do_related_class(model, rel_cls)
|
field.do_related_class(model, cls)
|
||||||
else:
|
else:
|
||||||
# Mark the related field for later lookup
|
key = (app_label, model_name)
|
||||||
pending_lookups.setdefault(key, []).append((rel_cls, field))
|
value = (cls, field)
|
||||||
|
pending_lookups.setdefault(key, []).append(value)
|
||||||
|
|
||||||
def do_pending_lookups(sender):
|
def do_pending_lookups(sender):
|
||||||
other_cls = sender
|
"""
|
||||||
key = (other_cls.__module__, other_cls.__name__)
|
Handle any pending relations to the sending model. Sent from class_prepared.
|
||||||
for rel_cls, field in pending_lookups.setdefault(key, []):
|
"""
|
||||||
field.rel.to = other_cls
|
key = (sender._meta.app_label, sender.__name__)
|
||||||
field.do_related_class(other_cls, rel_cls)
|
for cls, field in pending_lookups.pop(key, []):
|
||||||
|
field.rel.to = sender
|
||||||
|
field.do_related_class(sender, cls)
|
||||||
|
|
||||||
dispatcher.connect(do_pending_lookups, signal=signals.class_prepared)
|
dispatcher.connect(do_pending_lookups, signal=signals.class_prepared)
|
||||||
|
|
||||||
@ -66,9 +104,7 @@ class RelatedField(object):
|
|||||||
sup.contribute_to_class(cls, name)
|
sup.contribute_to_class(cls, name)
|
||||||
other = self.rel.to
|
other = self.rel.to
|
||||||
if isinstance(other, basestring):
|
if isinstance(other, basestring):
|
||||||
if other == RECURSIVE_RELATIONSHIP_CONSTANT:
|
add_lazy_relation(cls, self, other)
|
||||||
self.rel.to = cls.__name__
|
|
||||||
add_lookup(cls, self)
|
|
||||||
else:
|
else:
|
||||||
self.do_related_class(other, cls)
|
self.do_related_class(other, cls)
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ class QueryDict(MultiValueDict):
|
|||||||
dict.__setitem__(result, key, value)
|
dict.__setitem__(result, key, value)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __deepcopy__(self, memo={}):
|
def __deepcopy__(self, memo):
|
||||||
import copy
|
import copy
|
||||||
result = self.__class__('', mutable=True)
|
result = self.__class__('', mutable=True)
|
||||||
memo[id(self)] = result
|
memo[id(self)] = result
|
||||||
@ -223,7 +223,7 @@ class QueryDict(MultiValueDict):
|
|||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
"Returns a mutable copy of this object."
|
"Returns a mutable copy of this object."
|
||||||
return self.__deepcopy__()
|
return self.__deepcopy__({})
|
||||||
|
|
||||||
def urlencode(self):
|
def urlencode(self):
|
||||||
output = []
|
output = []
|
||||||
|
@ -22,23 +22,40 @@ def pretty_name(name):
|
|||||||
name = name[0].upper() + name[1:]
|
name = name[0].upper() + name[1:]
|
||||||
return name.replace('_', ' ')
|
return name.replace('_', ' ')
|
||||||
|
|
||||||
class DeclarativeFieldsMetaclass(type):
|
def get_declared_fields(bases, attrs, with_base_fields=True):
|
||||||
"""
|
"""
|
||||||
Metaclass that converts Field attributes to a dictionary called
|
Create a list of form field instances from the passed in 'attrs', plus any
|
||||||
'base_fields', taking into account parent class 'base_fields' as well.
|
similar fields on the base classes (in 'bases'). This is used by both the
|
||||||
|
Form and ModelForm metclasses.
|
||||||
|
|
||||||
|
If 'with_base_fields' is True, all fields from the bases are used.
|
||||||
|
Otherwise, only fields in the 'declared_fields' attribute on the bases are
|
||||||
|
used. The distinction is useful in ModelForm subclassing.
|
||||||
"""
|
"""
|
||||||
def __new__(cls, name, bases, attrs):
|
|
||||||
fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)]
|
fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)]
|
||||||
fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
|
fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
|
||||||
|
|
||||||
# If this class is subclassing another Form, add that Form's fields.
|
# If this class is subclassing another Form, add that Form's fields.
|
||||||
# Note that we loop over the bases in *reverse*. This is necessary in
|
# Note that we loop over the bases in *reverse*. This is necessary in
|
||||||
# order to preserve the correct order of fields.
|
# order to preserve the correct order of fields.
|
||||||
|
if with_base_fields:
|
||||||
for base in bases[::-1]:
|
for base in bases[::-1]:
|
||||||
if hasattr(base, 'base_fields'):
|
if hasattr(base, 'base_fields'):
|
||||||
fields = base.base_fields.items() + fields
|
fields = base.base_fields.items() + fields
|
||||||
|
else:
|
||||||
|
for base in bases[::-1]:
|
||||||
|
if hasattr(base, 'declared_fields'):
|
||||||
|
fields = base.declared_fields.items() + fields
|
||||||
|
|
||||||
attrs['base_fields'] = SortedDict(fields)
|
return SortedDict(fields)
|
||||||
|
|
||||||
|
class DeclarativeFieldsMetaclass(type):
|
||||||
|
"""
|
||||||
|
Metaclass that converts Field attributes to a dictionary called
|
||||||
|
'base_fields', taking into account parent class 'base_fields' as well.
|
||||||
|
"""
|
||||||
|
def __new__(cls, name, bases, attrs):
|
||||||
|
attrs['base_fields'] = get_declared_fields(bases, attrs)
|
||||||
return type.__new__(cls, name, bases, attrs)
|
return type.__new__(cls, name, bases, attrs)
|
||||||
|
|
||||||
class BaseForm(StrAndUnicode):
|
class BaseForm(StrAndUnicode):
|
||||||
|
@ -11,7 +11,7 @@ from django.utils.datastructures import SortedDict
|
|||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
from util import ValidationError, ErrorList
|
from util import ValidationError, ErrorList
|
||||||
from forms import BaseForm
|
from forms import BaseForm, get_declared_fields
|
||||||
from fields import Field, ChoiceField, EMPTY_VALUES
|
from fields import Field, ChoiceField, EMPTY_VALUES
|
||||||
from widgets import Select, SelectMultiple, MultipleHiddenInput
|
from widgets import Select, SelectMultiple, MultipleHiddenInput
|
||||||
|
|
||||||
@ -211,57 +211,39 @@ class ModelFormOptions(object):
|
|||||||
self.fields = getattr(options, 'fields', None)
|
self.fields = getattr(options, 'fields', None)
|
||||||
self.exclude = getattr(options, 'exclude', None)
|
self.exclude = getattr(options, 'exclude', None)
|
||||||
|
|
||||||
|
|
||||||
class ModelFormMetaclass(type):
|
class ModelFormMetaclass(type):
|
||||||
def __new__(cls, name, bases, attrs,
|
def __new__(cls, name, bases, attrs,
|
||||||
formfield_callback=lambda f: f.formfield()):
|
formfield_callback=lambda f: f.formfield()):
|
||||||
fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)]
|
try:
|
||||||
fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
|
parents = [b for b in bases if issubclass(b, ModelForm)]
|
||||||
|
except NameError:
|
||||||
|
# We are defining ModelForm itself.
|
||||||
|
parents = None
|
||||||
|
if not parents:
|
||||||
|
return super(ModelFormMetaclass, cls).__new__(cls, name, bases,
|
||||||
|
attrs)
|
||||||
|
|
||||||
# If this class is subclassing another Form, add that Form's fields.
|
new_class = type.__new__(cls, name, bases, attrs)
|
||||||
# Note that we loop over the bases in *reverse*. This is necessary in
|
declared_fields = get_declared_fields(bases, attrs, False)
|
||||||
# order to preserve the correct order of fields.
|
opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))
|
||||||
for base in bases[::-1]:
|
if opts.model:
|
||||||
if hasattr(base, 'base_fields'):
|
# If a model is defined, extract form fields from it.
|
||||||
fields = base.base_fields.items() + fields
|
fields = fields_for_model(opts.model, opts.fields,
|
||||||
declared_fields = SortedDict(fields)
|
|
||||||
|
|
||||||
opts = ModelFormOptions(attrs.get('Meta', None))
|
|
||||||
attrs['_meta'] = opts
|
|
||||||
|
|
||||||
# Don't allow more than one Meta model definition in bases. The fields
|
|
||||||
# would be generated correctly, but the save method won't deal with
|
|
||||||
# more than one object.
|
|
||||||
base_models = []
|
|
||||||
for base in bases:
|
|
||||||
base_opts = getattr(base, '_meta', None)
|
|
||||||
base_model = getattr(base_opts, 'model', None)
|
|
||||||
if base_model is not None:
|
|
||||||
base_models.append(base_model)
|
|
||||||
if len(base_models) > 1:
|
|
||||||
raise ImproperlyConfigured("%s's base classes define more than one model." % name)
|
|
||||||
|
|
||||||
# If a model is defined, extract form fields from it and add them to base_fields
|
|
||||||
if attrs['_meta'].model is not None:
|
|
||||||
# Don't allow a subclass to define a different Meta model than a
|
|
||||||
# parent class has. Technically the right fields would be generated,
|
|
||||||
# but the save method will not deal with more than one model.
|
|
||||||
for base in bases:
|
|
||||||
base_opts = getattr(base, '_meta', None)
|
|
||||||
base_model = getattr(base_opts, 'model', None)
|
|
||||||
if base_model and base_model is not opts.model:
|
|
||||||
raise ImproperlyConfigured('%s defines a different model than its parent.' % name)
|
|
||||||
model_fields = fields_for_model(opts.model, opts.fields,
|
|
||||||
opts.exclude, formfield_callback)
|
opts.exclude, formfield_callback)
|
||||||
# fields declared in base classes override fields from the model
|
# Override default model fields with any custom declared ones
|
||||||
model_fields.update(declared_fields)
|
# (plus, include all the other declared fields).
|
||||||
attrs['base_fields'] = model_fields
|
fields.update(declared_fields)
|
||||||
else:
|
else:
|
||||||
attrs['base_fields'] = declared_fields
|
fields = declared_fields
|
||||||
return type.__new__(cls, name, bases, attrs)
|
new_class.declared_fields = declared_fields
|
||||||
|
new_class.base_fields = fields
|
||||||
|
return new_class
|
||||||
|
|
||||||
class BaseModelForm(BaseForm):
|
class BaseModelForm(BaseForm):
|
||||||
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
|
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
|
||||||
initial=None, error_class=ErrorList, label_suffix=':', instance=None):
|
initial=None, error_class=ErrorList, label_suffix=':',
|
||||||
|
instance=None):
|
||||||
opts = self._meta
|
opts = self._meta
|
||||||
if instance is None:
|
if instance is None:
|
||||||
# if we didn't get an instance, instantiate a new one
|
# if we didn't get an instance, instantiate a new one
|
||||||
@ -277,7 +259,8 @@ class BaseModelForm(BaseForm):
|
|||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
"""
|
"""
|
||||||
Saves this ``form``'s cleaned_data into model instance ``self.instance``.
|
Saves this ``form``'s cleaned_data into model instance
|
||||||
|
``self.instance``.
|
||||||
|
|
||||||
If commit=True, then the changes to ``instance`` will be saved to the
|
If commit=True, then the changes to ``instance`` will be saved to the
|
||||||
database. Returns ``instance``.
|
database. Returns ``instance``.
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import random as random_module
|
import random as random_module
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.template import Variable, Library
|
from django.template import Variable, Library
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -35,7 +39,7 @@ def stringfilter(func):
|
|||||||
for attr in ('is_safe', 'needs_autoescape'):
|
for attr in ('is_safe', 'needs_autoescape'):
|
||||||
if hasattr(func, attr):
|
if hasattr(func, attr):
|
||||||
setattr(_dec, attr, getattr(func, attr))
|
setattr(_dec, attr, getattr(func, attr))
|
||||||
return _dec
|
return wraps(func)(_dec)
|
||||||
|
|
||||||
###################
|
###################
|
||||||
# STRINGS #
|
# STRINGS #
|
||||||
|
@ -100,7 +100,7 @@ __all__ = [
|
|||||||
|
|
||||||
import __future__
|
import __future__
|
||||||
|
|
||||||
import sys, traceback, inspect, linecache, os, re, types
|
import sys, traceback, inspect, linecache, os, re
|
||||||
import unittest, difflib, pdb, tempfile
|
import unittest, difflib, pdb, tempfile
|
||||||
import warnings
|
import warnings
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import datetime
|
|
||||||
import sys
|
import sys
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from urlparse import urlparse
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import authenticate, login
|
||||||
from django.core.handlers.base import BaseHandler
|
from django.core.handlers.base import BaseHandler
|
||||||
|
@ -146,4 +146,3 @@ def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[]):
|
|||||||
teardown_test_environment()
|
teardown_test_environment()
|
||||||
|
|
||||||
return len(result.failures) + len(result.errors)
|
return len(result.failures) + len(result.errors)
|
||||||
|
|
@ -3,7 +3,7 @@ class MergeDict(object):
|
|||||||
A simple class for creating new "virtual" dictionaries that actually look
|
A simple class for creating new "virtual" dictionaries that actually look
|
||||||
up values in more than one dictionary, passed in the constructor.
|
up values in more than one dictionary, passed in the constructor.
|
||||||
|
|
||||||
If a key appears in more than one of the passed in dictionaries, only the
|
If a key appears in more than one of the given dictionaries, only the
|
||||||
first occurrence will be used.
|
first occurrence will be used.
|
||||||
"""
|
"""
|
||||||
def __init__(self, *dicts):
|
def __init__(self, *dicts):
|
||||||
@ -145,7 +145,7 @@ class SortedDict(dict):
|
|||||||
"""Returns a copy of this object."""
|
"""Returns a copy of this object."""
|
||||||
# This way of initializing the copy means it works for subclasses, too.
|
# This way of initializing the copy means it works for subclasses, too.
|
||||||
obj = self.__class__(self)
|
obj = self.__class__(self)
|
||||||
obj.keyOrder = self.keyOrder
|
obj.keyOrder = self.keyOrder[:]
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@ -155,6 +155,10 @@ class SortedDict(dict):
|
|||||||
"""
|
"""
|
||||||
return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()])
|
return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()])
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
super(SortedDict, self).clear()
|
||||||
|
self.keyOrder = []
|
||||||
|
|
||||||
class MultiValueDictKeyError(KeyError):
|
class MultiValueDictKeyError(KeyError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
"Functions that help with dynamically creating decorators for views."
|
"Functions that help with dynamically creating decorators for views."
|
||||||
|
|
||||||
import types
|
import types
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
def decorator_from_middleware(middleware_class):
|
def decorator_from_middleware(middleware_class):
|
||||||
"""
|
"""
|
||||||
@ -53,5 +57,5 @@ def decorator_from_middleware(middleware_class):
|
|||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
return response
|
return response
|
||||||
return _wrapped_view
|
return wraps(view_func)(_wrapped_view)
|
||||||
return _decorator_from_middleware
|
return _decorator_from_middleware
|
||||||
|
@ -1,8 +1,120 @@
|
|||||||
|
# License for code in this file that was taken from Python 2.5.
|
||||||
|
|
||||||
|
# PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||||
|
# --------------------------------------------
|
||||||
|
#
|
||||||
|
# 1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||||
|
# ("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||||
|
# otherwise using this software ("Python") in source or binary form and
|
||||||
|
# its associated documentation.
|
||||||
|
#
|
||||||
|
# 2. Subject to the terms and conditions of this License Agreement, PSF
|
||||||
|
# hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
||||||
|
# license to reproduce, analyze, test, perform and/or display publicly,
|
||||||
|
# prepare derivative works, distribute, and otherwise use Python
|
||||||
|
# alone or in any derivative version, provided, however, that PSF's
|
||||||
|
# License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
|
||||||
|
# 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation;
|
||||||
|
# All Rights Reserved" are retained in Python alone or in any derivative
|
||||||
|
# version prepared by Licensee.
|
||||||
|
#
|
||||||
|
# 3. In the event Licensee prepares a derivative work that is based on
|
||||||
|
# or incorporates Python or any part thereof, and wants to make
|
||||||
|
# the derivative work available to others as provided herein, then
|
||||||
|
# Licensee hereby agrees to include in any such work a brief summary of
|
||||||
|
# the changes made to Python.
|
||||||
|
#
|
||||||
|
# 4. PSF is making Python available to Licensee on an "AS IS"
|
||||||
|
# basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||||
|
# IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||||
|
# DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||||
|
# FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||||
|
# INFRINGE ANY THIRD PARTY RIGHTS.
|
||||||
|
#
|
||||||
|
# 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||||
|
# FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||||
|
# A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||||
|
# OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||||
|
#
|
||||||
|
# 6. This License Agreement will automatically terminate upon a material
|
||||||
|
# breach of its terms and conditions.
|
||||||
|
#
|
||||||
|
# 7. Nothing in this License Agreement shall be deemed to create any
|
||||||
|
# relationship of agency, partnership, or joint venture between PSF and
|
||||||
|
# Licensee. This License Agreement does not grant permission to use PSF
|
||||||
|
# trademarks or trade name in a trademark sense to endorse or promote
|
||||||
|
# products or services of Licensee, or any third party.
|
||||||
|
#
|
||||||
|
# 8. By copying, installing or otherwise using Python, Licensee
|
||||||
|
# agrees to be bound by the terms and conditions of this License
|
||||||
|
# Agreement.
|
||||||
|
|
||||||
|
|
||||||
def curry(_curried_func, *args, **kwargs):
|
def curry(_curried_func, *args, **kwargs):
|
||||||
def _curried(*moreargs, **morekwargs):
|
def _curried(*moreargs, **morekwargs):
|
||||||
return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
|
return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
|
||||||
return _curried
|
return _curried
|
||||||
|
|
||||||
|
### Begin from Python 2.5 functools.py ########################################
|
||||||
|
|
||||||
|
# Summary of changes made to the Python 2.5 code below:
|
||||||
|
# * swapped ``partial`` for ``curry`` to maintain backwards-compatibility
|
||||||
|
# in Django.
|
||||||
|
# * Wrapped the ``setattr`` call in ``update_wrapper`` with a try-except
|
||||||
|
# block to make it compatible with Python 2.3, which doesn't allow
|
||||||
|
# assigning to ``__name__``.
|
||||||
|
|
||||||
|
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation.
|
||||||
|
# All Rights Reserved.
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# update_wrapper() and wraps() are tools to help write
|
||||||
|
# wrapper functions that can handle naive introspection
|
||||||
|
|
||||||
|
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
|
||||||
|
WRAPPER_UPDATES = ('__dict__',)
|
||||||
|
def update_wrapper(wrapper,
|
||||||
|
wrapped,
|
||||||
|
assigned = WRAPPER_ASSIGNMENTS,
|
||||||
|
updated = WRAPPER_UPDATES):
|
||||||
|
"""Update a wrapper function to look like the wrapped function
|
||||||
|
|
||||||
|
wrapper is the function to be updated
|
||||||
|
wrapped is the original function
|
||||||
|
assigned is a tuple naming the attributes assigned directly
|
||||||
|
from the wrapped function to the wrapper function (defaults to
|
||||||
|
functools.WRAPPER_ASSIGNMENTS)
|
||||||
|
updated is a tuple naming the attributes off the wrapper that
|
||||||
|
are updated with the corresponding attribute from the wrapped
|
||||||
|
function (defaults to functools.WRAPPER_UPDATES)
|
||||||
|
"""
|
||||||
|
for attr in assigned:
|
||||||
|
try:
|
||||||
|
setattr(wrapper, attr, getattr(wrapped, attr))
|
||||||
|
except TypeError: # Python 2.3 doesn't allow assigning to __name__.
|
||||||
|
pass
|
||||||
|
for attr in updated:
|
||||||
|
getattr(wrapper, attr).update(getattr(wrapped, attr))
|
||||||
|
# Return the wrapper so this can be used as a decorator via curry()
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
def wraps(wrapped,
|
||||||
|
assigned = WRAPPER_ASSIGNMENTS,
|
||||||
|
updated = WRAPPER_UPDATES):
|
||||||
|
"""Decorator factory to apply update_wrapper() to a wrapper function
|
||||||
|
|
||||||
|
Returns a decorator that invokes update_wrapper() with the decorated
|
||||||
|
function as the wrapper argument and the arguments to wraps() as the
|
||||||
|
remaining arguments. Default arguments are as for update_wrapper().
|
||||||
|
This is a convenience function to simplify applying curry() to
|
||||||
|
update_wrapper().
|
||||||
|
"""
|
||||||
|
return curry(update_wrapper, wrapped=wrapped,
|
||||||
|
assigned=assigned, updated=updated)
|
||||||
|
|
||||||
|
### End from Python 2.5 functools.py ##########################################
|
||||||
|
|
||||||
def memoize(func, cache, num_args):
|
def memoize(func, cache, num_args):
|
||||||
"""
|
"""
|
||||||
Wrap a function so that results for any argument tuple are stored in
|
Wrap a function so that results for any argument tuple are stored in
|
||||||
@ -18,7 +130,7 @@ def memoize(func, cache, num_args):
|
|||||||
result = func(*args)
|
result = func(*args)
|
||||||
cache[mem_args] = result
|
cache[mem_args] = result
|
||||||
return result
|
return result
|
||||||
return wrapper
|
return wraps(func)(wrapper)
|
||||||
|
|
||||||
class Promise(object):
|
class Promise(object):
|
||||||
"""
|
"""
|
||||||
@ -110,7 +222,7 @@ def lazy(func, *resultclasses):
|
|||||||
# Creates the proxy object, instead of the actual value.
|
# Creates the proxy object, instead of the actual value.
|
||||||
return __proxy__(args, kw)
|
return __proxy__(args, kw)
|
||||||
|
|
||||||
return __wrapper__
|
return wraps(func)(__wrapper__)
|
||||||
|
|
||||||
def allow_lazy(func, *resultclasses):
|
def allow_lazy(func, *resultclasses):
|
||||||
"""
|
"""
|
||||||
@ -126,4 +238,4 @@ def allow_lazy(func, *resultclasses):
|
|||||||
else:
|
else:
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
return lazy(func, *resultclasses)(*args, **kwargs)
|
return lazy(func, *resultclasses)(*args, **kwargs)
|
||||||
return wrapper
|
return wraps(func)(wrapper)
|
||||||
|
@ -11,6 +11,11 @@ Additionally, all headers from the response's Vary header will be taken into
|
|||||||
account on caching -- just like the middleware does.
|
account on caching -- just like the middleware does.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.utils.decorators import decorator_from_middleware
|
from django.utils.decorators import decorator_from_middleware
|
||||||
from django.utils.cache import patch_cache_control, add_never_cache_headers
|
from django.utils.cache import patch_cache_control, add_never_cache_headers
|
||||||
from django.middleware.cache import CacheMiddleware
|
from django.middleware.cache import CacheMiddleware
|
||||||
@ -26,7 +31,7 @@ def cache_control(**kwargs):
|
|||||||
patch_cache_control(response, **kwargs)
|
patch_cache_control(response, **kwargs)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
return _cache_controlled
|
return wraps(viewfunc)(_cache_controlled)
|
||||||
|
|
||||||
return _cache_controller
|
return _cache_controller
|
||||||
|
|
||||||
@ -39,4 +44,4 @@ def never_cache(view_func):
|
|||||||
response = view_func(request, *args, **kwargs)
|
response = view_func(request, *args, **kwargs)
|
||||||
add_never_cache_headers(response)
|
add_never_cache_headers(response)
|
||||||
return response
|
return response
|
||||||
return _wrapped_view_func
|
return wraps(view_func)(_wrapped_view_func)
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
Decorators for views based on HTTP headers.
|
Decorators for views based on HTTP headers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.utils.decorators import decorator_from_middleware
|
from django.utils.decorators import decorator_from_middleware
|
||||||
from django.middleware.http import ConditionalGetMiddleware
|
from django.middleware.http import ConditionalGetMiddleware
|
||||||
from django.http import HttpResponseNotAllowed
|
from django.http import HttpResponseNotAllowed
|
||||||
@ -24,7 +29,7 @@ def require_http_methods(request_method_list):
|
|||||||
if request.method not in request_method_list:
|
if request.method not in request_method_list:
|
||||||
return HttpResponseNotAllowed(request_method_list)
|
return HttpResponseNotAllowed(request_method_list)
|
||||||
return func(request, *args, **kwargs)
|
return func(request, *args, **kwargs)
|
||||||
return inner
|
return wraps(func)(inner)
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
require_GET = require_http_methods(["GET"])
|
require_GET = require_http_methods(["GET"])
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.utils.cache import patch_vary_headers
|
from django.utils.cache import patch_vary_headers
|
||||||
|
|
||||||
def vary_on_headers(*headers):
|
def vary_on_headers(*headers):
|
||||||
@ -16,7 +21,7 @@ def vary_on_headers(*headers):
|
|||||||
response = func(*args, **kwargs)
|
response = func(*args, **kwargs)
|
||||||
patch_vary_headers(response, headers)
|
patch_vary_headers(response, headers)
|
||||||
return response
|
return response
|
||||||
return inner_func
|
return wraps(func)(inner_func)
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
def vary_on_cookie(func):
|
def vary_on_cookie(func):
|
||||||
@ -32,4 +37,4 @@ def vary_on_cookie(func):
|
|||||||
response = func(*args, **kwargs)
|
response = func(*args, **kwargs)
|
||||||
patch_vary_headers(response, ('Cookie',))
|
patch_vary_headers(response, ('Cookie',))
|
||||||
return response
|
return response
|
||||||
return inner_func
|
return wraps(func)(inner_func)
|
||||||
|
@ -88,7 +88,7 @@ change:
|
|||||||
API changes may be necessary.
|
API changes may be necessary.
|
||||||
|
|
||||||
- Generic relations will most likely be moved out of core and into the
|
- Generic relations will most likely be moved out of core and into the
|
||||||
content-types contrib package to avoid core dependancies on optional
|
content-types contrib package to avoid core dependencies on optional
|
||||||
components.
|
components.
|
||||||
|
|
||||||
- The comments framework, which is yet undocumented, will likely get a complete
|
- The comments framework, which is yet undocumented, will likely get a complete
|
||||||
|
@ -215,7 +215,7 @@ each ``TaggedItem`` will have a ``content_object`` field that returns the
|
|||||||
object it's related to, and you can also assign to that field or use it when
|
object it's related to, and you can also assign to that field or use it when
|
||||||
creating a ``TaggedItem``::
|
creating a ``TaggedItem``::
|
||||||
|
|
||||||
>>> from django.contrib.models.auth import User
|
>>> from django.contrib.auth.models import User
|
||||||
>>> guido = User.objects.get(username='Guido')
|
>>> guido = User.objects.get(username='Guido')
|
||||||
>>> t = TaggedItem(content_object=guido, tag='bdfl')
|
>>> t = TaggedItem(content_object=guido, tag='bdfl')
|
||||||
>>> t.save()
|
>>> t.save()
|
||||||
@ -235,7 +235,7 @@ a "reverse" generic relationship to enable an additional API. For example::
|
|||||||
``Bookmark`` instances will each have a ``tags`` attribute, which can
|
``Bookmark`` instances will each have a ``tags`` attribute, which can
|
||||||
be used to retrieve their associated ``TaggedItems``::
|
be used to retrieve their associated ``TaggedItems``::
|
||||||
|
|
||||||
>>> b = Bookmark('http://www.djangoproject.com/')
|
>>> b = Bookmark(url='http://www.djangoproject.com/')
|
||||||
>>> b.save()
|
>>> b.save()
|
||||||
>>> t1 = TaggedItem(content_object=b, tag='django')
|
>>> t1 = TaggedItem(content_object=b, tag='django')
|
||||||
>>> t1.save()
|
>>> t1.save()
|
||||||
|
@ -1605,8 +1605,7 @@ the cache of all one-to-many relationships ahead of time. Example::
|
|||||||
print e.blog # Doesn't hit the database; uses cached version.
|
print e.blog # Doesn't hit the database; uses cached version.
|
||||||
print e.blog # Doesn't hit the database; uses cached version.
|
print e.blog # Doesn't hit the database; uses cached version.
|
||||||
|
|
||||||
``select_related()`` is documented in the "QuerySet methods that return new
|
``select_related()`` is documented in the `QuerySet methods that return new QuerySets`_ section above.
|
||||||
QuerySets" section above.
|
|
||||||
|
|
||||||
Backward
|
Backward
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
@ -5,7 +5,7 @@ Third-party distributions of Django
|
|||||||
Several third-party distributors are now providing versions of Django integrated
|
Several third-party distributors are now providing versions of Django integrated
|
||||||
with their package-management systems. These can make installation and upgrading
|
with their package-management systems. These can make installation and upgrading
|
||||||
much easier for users of Django since the integration includes the ability to
|
much easier for users of Django since the integration includes the ability to
|
||||||
automatically install dependancies (like database adapters) that Django
|
automatically install dependencies (like database adapters) that Django
|
||||||
requires.
|
requires.
|
||||||
|
|
||||||
Typically, these packages are based on the latest stable release of Django, so
|
Typically, these packages are based on the latest stable release of Django, so
|
||||||
|
@ -767,7 +767,7 @@ a command that can be executed as an action when you run ``manage.py``::
|
|||||||
views.py
|
views.py
|
||||||
|
|
||||||
In this example, the ``explode`` command will be made available to any project
|
In this example, the ``explode`` command will be made available to any project
|
||||||
that includes the ``fancy_blog`` application in ``settings.INSTALLED_APPS``.
|
that includes the ``blog`` application in ``settings.INSTALLED_APPS``.
|
||||||
|
|
||||||
The ``explode.py`` module has only one requirement -- it must define a class
|
The ``explode.py`` module has only one requirement -- it must define a class
|
||||||
called ``Command`` that extends ``django.core.management.base.BaseCommand``.
|
called ``Command`` that extends ``django.core.management.base.BaseCommand``.
|
||||||
|
@ -353,7 +353,7 @@ How do I install mod_python on Windows?
|
|||||||
working`_.
|
working`_.
|
||||||
|
|
||||||
.. _`win32 build of mod_python for Python 2.4`: http://www.lehuen.com/nicolas/index.php/2005/02/21/39-win32-build-of-mod_python-314-for-python-24
|
.. _`win32 build of mod_python for Python 2.4`: http://www.lehuen.com/nicolas/index.php/2005/02/21/39-win32-build-of-mod_python-314-for-python-24
|
||||||
.. _`Django on Windows howto`: http://thinkhole.org/wp/2006/04/03/django-on-windows-howto/
|
.. _`Django on Windows howto`: http://thinkhole.org/wp/django-on-windows/
|
||||||
.. _`Running mod_python on Apache on Windows2000`: http://groups-beta.google.com/group/comp.lang.python/msg/139af8c83a5a9d4f
|
.. _`Running mod_python on Apache on Windows2000`: http://groups-beta.google.com/group/comp.lang.python/msg/139af8c83a5a9d4f
|
||||||
.. _`guide to getting mod_python working`: http://www.dscpl.com.au/articles/modpython-001.html
|
.. _`guide to getting mod_python working`: http://www.dscpl.com.au/articles/modpython-001.html
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ Installing a distribution-specific package
|
|||||||
Check the `distribution specific notes`_ to see if your
|
Check the `distribution specific notes`_ to see if your
|
||||||
platform/distribution provides official Django packages/installers.
|
platform/distribution provides official Django packages/installers.
|
||||||
Distribution-provided packages will typically allow for automatic
|
Distribution-provided packages will typically allow for automatic
|
||||||
installation of dependancies and easy upgrade paths.
|
installation of dependencies and easy upgrade paths.
|
||||||
|
|
||||||
Installing an official release
|
Installing an official release
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -384,7 +384,7 @@ The admin represents this as an ``<input type="text">`` (a single-line input).
|
|||||||
``IPAddressField``
|
``IPAddressField``
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
An IP address, in string format (i.e. "24.124.1.30").
|
An IP address, in string format (e.g. "192.0.2.30").
|
||||||
|
|
||||||
The admin represents this as an ``<input type="text">`` (a single-line input).
|
The admin represents this as an ``<input type="text">`` (a single-line input).
|
||||||
|
|
||||||
@ -784,9 +784,17 @@ you can use the name of the model, rather than the model object itself::
|
|||||||
class Manufacturer(models.Model):
|
class Manufacturer(models.Model):
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
Note, however, that you can only use strings to refer to models in the same
|
Note, however, that this only refers to models in the same models.py file -- you
|
||||||
models.py file -- you cannot use a string to reference a model in a different
|
cannot use a string to reference a model defined in another application or
|
||||||
application, or to reference a model that has been imported from elsewhere.
|
imported from elsewhere.
|
||||||
|
|
||||||
|
**New in Django development version:** to refer to models defined in another
|
||||||
|
application, you must instead explicitially specify the application label. That
|
||||||
|
is, if the ``Manufacturer`` model above is defined in another application called
|
||||||
|
``production``, you'd need to use::
|
||||||
|
|
||||||
|
class Car(models.Model):
|
||||||
|
manufacturer = models.ForeignKey('production.Manufacturer')
|
||||||
|
|
||||||
Behind the scenes, Django appends ``"_id"`` to the field name to create its
|
Behind the scenes, Django appends ``"_id"`` to the field name to create its
|
||||||
database column name. In the above example, the database table for the ``Car``
|
database column name. In the above example, the database table for the ``Car``
|
||||||
@ -952,7 +960,7 @@ the relationship should work. All are optional:
|
|||||||
``limit_choices_to`` See the description under ``ForeignKey`` above.
|
``limit_choices_to`` See the description under ``ForeignKey`` above.
|
||||||
|
|
||||||
``symmetrical`` Only used in the definition of ManyToManyFields on self.
|
``symmetrical`` Only used in the definition of ManyToManyFields on self.
|
||||||
Consider the following model:
|
Consider the following model::
|
||||||
|
|
||||||
class Person(models.Model):
|
class Person(models.Model):
|
||||||
friends = models.ManyToManyField("self")
|
friends = models.ManyToManyField("self")
|
||||||
@ -1872,7 +1880,7 @@ more simply as::
|
|||||||
|
|
||||||
If you define a ``__unicode__()`` method on your model and not a ``__str__()``
|
If you define a ``__unicode__()`` method on your model and not a ``__str__()``
|
||||||
method, Django will automatically provide you with a ``__str__()`` that calls
|
method, Django will automatically provide you with a ``__str__()`` that calls
|
||||||
``__unicode()__`` and then converts the result correctly to a UTF-8 encoded
|
``__unicode__()`` and then converts the result correctly to a UTF-8 encoded
|
||||||
string object. This is recommended development practice: define only
|
string object. This is recommended development practice: define only
|
||||||
``__unicode__()`` and let Django take care of the conversion to string objects
|
``__unicode__()`` and let Django take care of the conversion to string objects
|
||||||
when required.
|
when required.
|
||||||
|
@ -320,3 +320,41 @@ parameter when declaring the form field::
|
|||||||
...
|
...
|
||||||
... class Meta:
|
... class Meta:
|
||||||
... model = Article
|
... model = Article
|
||||||
|
|
||||||
|
Form inheritance
|
||||||
|
----------------
|
||||||
|
|
||||||
|
As with basic forms, you can extend and reuse ``ModelForms`` by inheriting
|
||||||
|
them. This is useful if you need to declare extra fields or extra methods on a
|
||||||
|
parent class for use in a number of forms derived from models. For example,
|
||||||
|
using the previous ``ArticleForm`` class::
|
||||||
|
|
||||||
|
>>> class EnhancedArticleForm(ArticleForm):
|
||||||
|
... def clean_pub_date(self):
|
||||||
|
... ...
|
||||||
|
|
||||||
|
This creates a form that behaves identically to ``ArticleForm``, except there's
|
||||||
|
some extra validation and cleaning for the ``pub_date`` field.
|
||||||
|
|
||||||
|
You can also subclass the parent's ``Meta`` inner class if you want to change
|
||||||
|
the ``Meta.fields`` or ``Meta.excludes`` lists::
|
||||||
|
|
||||||
|
>>> class RestrictedArticleForm(EnhancedArticleForm):
|
||||||
|
... class Meta(ArticleForm.Meta):
|
||||||
|
... exclude = ['body']
|
||||||
|
|
||||||
|
This adds the extra method from the ``EnhancedArticleForm`` and modifies
|
||||||
|
the original ``ArticleForm.Meta`` to remove one field.
|
||||||
|
|
||||||
|
There are a couple of things to note, however.
|
||||||
|
|
||||||
|
* Normal Python name resolution rules apply. If you have multiple base
|
||||||
|
classes that declare a ``Meta`` inner class, only the first one will be
|
||||||
|
used. This means the child's ``Meta``, if it exists, otherwise the
|
||||||
|
``Meta`` of the first parent, etc.
|
||||||
|
|
||||||
|
* For technical reasons, a subclass cannot inherit from both a ``ModelForm``
|
||||||
|
and a ``Form`` simultaneously.
|
||||||
|
|
||||||
|
Chances are these notes won't affect you unless you're trying to do something
|
||||||
|
tricky with subclassing.
|
||||||
|
@ -576,7 +576,7 @@ Three things to note about 404 views:
|
|||||||
in the 404.
|
in the 404.
|
||||||
|
|
||||||
* The 404 view is passed a ``RequestContext`` and will have access to
|
* The 404 view is passed a ``RequestContext`` and will have access to
|
||||||
variables supplied by your ``TEMPLATE_CONTEXT_PROCESSORS`` (e.g.
|
variables supplied by your ``TEMPLATE_CONTEXT_PROCESSORS`` setting (e.g.,
|
||||||
``MEDIA_URL``).
|
``MEDIA_URL``).
|
||||||
|
|
||||||
* If ``DEBUG`` is set to ``True`` (in your settings module), then your 404
|
* If ``DEBUG`` is set to ``True`` (in your settings module), then your 404
|
||||||
|
@ -88,7 +88,7 @@ something like::
|
|||||||
|
|
||||||
for deserialized_object in serializers.deserialize("xml", data):
|
for deserialized_object in serializers.deserialize("xml", data):
|
||||||
if object_should_be_saved(deserialized_object):
|
if object_should_be_saved(deserialized_object):
|
||||||
obj.save()
|
deserialized_object.save()
|
||||||
|
|
||||||
In other words, the usual use is to examine the deserialized objects to make
|
In other words, the usual use is to examine the deserialized objects to make
|
||||||
sure that they are "appropriate" for saving before doing so. Of course, if you trust your data source you could just save the object and move on.
|
sure that they are "appropriate" for saving before doing so. Of course, if you trust your data source you could just save the object and move on.
|
||||||
|
@ -30,9 +30,9 @@ Optional arguments
|
|||||||
``context_instance``
|
``context_instance``
|
||||||
The context instance to render the template with. By default, the template
|
The context instance to render the template with. By default, the template
|
||||||
will be rendered with a ``Context`` instance (filled with values from
|
will be rendered with a ``Context`` instance (filled with values from
|
||||||
``dictionary``). If you need to use `context processors`_, you will want to
|
``dictionary``). If you need to use `context processors`_, render the
|
||||||
render the template with a ``RequestContext`` instance instead. Your code
|
template with a ``RequestContext`` instance instead. Your code might look
|
||||||
might look something like this::
|
something like this::
|
||||||
|
|
||||||
return render_to_response('my_template.html',
|
return render_to_response('my_template.html',
|
||||||
my_data_dictionary,
|
my_data_dictionary,
|
||||||
|
@ -1406,6 +1406,8 @@ Joins a list with a string, like Python's ``str.join(list)``.
|
|||||||
last
|
last
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
**New in Django development version.**
|
||||||
|
|
||||||
Returns the last item in a list.
|
Returns the last item in a list.
|
||||||
|
|
||||||
length
|
length
|
||||||
|
@ -395,6 +395,8 @@ See the `internationalization docs`_ for more.
|
|||||||
django.core.context_processors.media
|
django.core.context_processors.media
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
|
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
|
||||||
``RequestContext`` will contain a variable ``MEDIA_URL``, providing the
|
``RequestContext`` will contain a variable ``MEDIA_URL``, providing the
|
||||||
value of the `MEDIA_URL setting`_.
|
value of the `MEDIA_URL setting`_.
|
||||||
@ -1014,7 +1016,7 @@ This is not a very common situation, but it's useful if you're rendering a
|
|||||||
template yourself. For example::
|
template yourself. For example::
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
t = template.load_template('small_fragment.html')
|
t = template.loader.get_template('small_fragment.html')
|
||||||
return t.render(Context({'var': obj}, autoescape=context.autoescape))
|
return t.render(Context({'var': obj}, autoescape=context.autoescape))
|
||||||
|
|
||||||
If we had neglected to pass in the current ``context.autoescape`` value to our
|
If we had neglected to pass in the current ``context.autoescape`` value to our
|
||||||
|
@ -190,6 +190,28 @@ The remaining arguments should be tuples in this format::
|
|||||||
...where ``optional dictionary`` and ``optional name`` are optional. (See
|
...where ``optional dictionary`` and ``optional name`` are optional. (See
|
||||||
`Passing extra options to view functions`_ below.)
|
`Passing extra options to view functions`_ below.)
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Because `patterns()` is a function call, it accepts a maximum of 255
|
||||||
|
arguments (URL patterns, in this case). This is a limit for all Python
|
||||||
|
function calls. This is rarely a problem in practice, because you'll
|
||||||
|
typically structure your URL patterns modularly by using `include()`
|
||||||
|
sections. However, on the off-chance you do hit the 255-argument limit,
|
||||||
|
realize that `patterns()` returns a Python list, so you can split up the
|
||||||
|
construction of the list.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
...
|
||||||
|
)
|
||||||
|
urlpatterns += patterns('',
|
||||||
|
...
|
||||||
|
)
|
||||||
|
|
||||||
|
Python lists have unlimited size, so there's no limit to how many URL
|
||||||
|
patterns you can construct. The only limit is that you can only create 254
|
||||||
|
at a time (the 255th argument is the initial prefix argument).
|
||||||
|
|
||||||
url
|
url
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -61,13 +61,13 @@ _django_completion()
|
|||||||
||
|
||
|
||||||
# python manage.py, /some/path/python manage.py (if manage.py exists)
|
# python manage.py, /some/path/python manage.py (if manage.py exists)
|
||||||
( ${COMP_CWORD} -eq 2 &&
|
( ${COMP_CWORD} -eq 2 &&
|
||||||
( $( basename ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
|
( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
|
||||||
( $( basename ${COMP_WORDS[1]} ) == manage.py) &&
|
( $( basename -- ${COMP_WORDS[1]} ) == manage.py) &&
|
||||||
( -r ${COMP_WORDS[1]} ) )
|
( -r ${COMP_WORDS[1]} ) )
|
||||||
||
|
||
|
||||||
( ${COMP_CWORD} -eq 2 &&
|
( ${COMP_CWORD} -eq 2 &&
|
||||||
( $( basename ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
|
( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
|
||||||
( $( basename ${COMP_WORDS[1]} ) == django-admin.py) &&
|
( $( basename -- ${COMP_WORDS[1]} ) == django-admin.py) &&
|
||||||
( -r ${COMP_WORDS[1]} ) ) ]] ; then
|
( -r ${COMP_WORDS[1]} ) ) ]] ; then
|
||||||
|
|
||||||
case ${cur} in
|
case ${cur} in
|
||||||
@ -149,7 +149,7 @@ unset pythons
|
|||||||
if command -v whereis &>/dev/null; then
|
if command -v whereis &>/dev/null; then
|
||||||
python_interpreters=$(whereis python | cut -d " " -f 2-)
|
python_interpreters=$(whereis python | cut -d " " -f 2-)
|
||||||
for python in $python_interpreters; do
|
for python in $python_interpreters; do
|
||||||
pythons="${pythons} $(basename $python)"
|
pythons="${pythons} $(basename -- $python)"
|
||||||
done
|
done
|
||||||
pythons=$(echo $pythons | tr " " "\n" | sort -u | tr "\n" " ")
|
pythons=$(echo $pythons | tr " " "\n" | sort -u | tr "\n" " ")
|
||||||
else
|
else
|
||||||
|
11
setup.py
11
setup.py
@ -27,19 +27,16 @@ for scheme in INSTALL_SCHEMES.values():
|
|||||||
# an easy way to do this.
|
# an easy way to do this.
|
||||||
packages, data_files = [], []
|
packages, data_files = [], []
|
||||||
root_dir = os.path.dirname(__file__)
|
root_dir = os.path.dirname(__file__)
|
||||||
django_dir = os.path.join(root_dir, 'django')
|
if root_dir != '':
|
||||||
pieces = fullsplit(root_dir)
|
os.chdir(root_dir)
|
||||||
if pieces[-1] == '':
|
django_dir = 'django'
|
||||||
len_root_dir = len(pieces) - 1
|
|
||||||
else:
|
|
||||||
len_root_dir = len(pieces)
|
|
||||||
|
|
||||||
for dirpath, dirnames, filenames in os.walk(django_dir):
|
for dirpath, dirnames, filenames in os.walk(django_dir):
|
||||||
# Ignore dirnames that start with '.'
|
# Ignore dirnames that start with '.'
|
||||||
for i, dirname in enumerate(dirnames):
|
for i, dirname in enumerate(dirnames):
|
||||||
if dirname.startswith('.'): del dirnames[i]
|
if dirname.startswith('.'): del dirnames[i]
|
||||||
if '__init__.py' in filenames:
|
if '__init__.py' in filenames:
|
||||||
packages.append('.'.join(fullsplit(dirpath)[len_root_dir:]))
|
packages.append('.'.join(fullsplit(dirpath)))
|
||||||
elif filenames:
|
elif filenames:
|
||||||
data_files.append([dirpath, [os.path.join(dirpath, f) for f in filenames]])
|
data_files.append([dirpath, [os.path.join(dirpath, f) for f in filenames]])
|
||||||
|
|
||||||
|
@ -5,6 +5,11 @@
|
|||||||
This is a basic model with only two non-primary-key fields.
|
This is a basic model with only two non-primary-key fields.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
set
|
||||||
|
except NameError:
|
||||||
|
from sets import Set as set
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
@ -389,4 +394,10 @@ year, including Jan. 1 and Dec. 31.
|
|||||||
>>> a.save()
|
>>> a.save()
|
||||||
>>> Article.objects.get(pk=a.id).headline
|
>>> Article.objects.get(pk=a.id).headline
|
||||||
u'\u6797\u539f \u3081\u3050\u307f'
|
u'\u6797\u539f \u3081\u3050\u307f'
|
||||||
|
|
||||||
|
# Model instances have a hash function, so they can be used in sets or as
|
||||||
|
# dictionary keys. Two models compare as equal if their primary keys are equal.
|
||||||
|
>>> s = set([a10, a11, a12])
|
||||||
|
>>> Article.objects.get(headline='Article 11') in s
|
||||||
|
True
|
||||||
"""
|
"""
|
||||||
|
@ -155,29 +155,52 @@ familiar with the mechanics.
|
|||||||
... class Meta:
|
... class Meta:
|
||||||
... model = Category
|
... model = Category
|
||||||
|
|
||||||
>>> class BadForm(CategoryForm):
|
>>> class OddForm(CategoryForm):
|
||||||
... class Meta:
|
... class Meta:
|
||||||
... model = Article
|
... model = Article
|
||||||
Traceback (most recent call last):
|
|
||||||
...
|
OddForm is now an Article-related thing, because BadForm.Meta overrides
|
||||||
ImproperlyConfigured: BadForm defines a different model than its parent.
|
CategoryForm.Meta.
|
||||||
|
>>> OddForm.base_fields.keys()
|
||||||
|
['headline', 'slug', 'pub_date', 'writer', 'article', 'status', 'categories']
|
||||||
|
|
||||||
>>> class ArticleForm(ModelForm):
|
>>> class ArticleForm(ModelForm):
|
||||||
... class Meta:
|
... class Meta:
|
||||||
... model = Article
|
... model = Article
|
||||||
|
|
||||||
|
First class with a Meta class wins.
|
||||||
|
|
||||||
>>> class BadForm(ArticleForm, CategoryForm):
|
>>> class BadForm(ArticleForm, CategoryForm):
|
||||||
... pass
|
... pass
|
||||||
Traceback (most recent call last):
|
>>> OddForm.base_fields.keys()
|
||||||
...
|
['headline', 'slug', 'pub_date', 'writer', 'article', 'status', 'categories']
|
||||||
ImproperlyConfigured: BadForm's base classes define more than one model.
|
|
||||||
|
|
||||||
This one is OK since the subclass specifies the same model as the parent.
|
Subclassing without specifying a Meta on the class will use the parent's Meta
|
||||||
|
(or the first parent in the MRO if there are multiple parent classes).
|
||||||
|
|
||||||
>>> class SubCategoryForm(CategoryForm):
|
>>> class CategoryForm(ModelForm):
|
||||||
... class Meta:
|
... class Meta:
|
||||||
... model = Category
|
... model = Category
|
||||||
|
>>> class SubCategoryForm(CategoryForm):
|
||||||
|
... pass
|
||||||
|
>>> SubCategoryForm.base_fields.keys()
|
||||||
|
['name', 'slug', 'url']
|
||||||
|
|
||||||
|
We can also subclass the Meta inner class to change the fields list.
|
||||||
|
|
||||||
|
>>> class CategoryForm(ModelForm):
|
||||||
|
... checkbox = forms.BooleanField()
|
||||||
|
...
|
||||||
|
... class Meta:
|
||||||
|
... model = Category
|
||||||
|
>>> class SubCategoryForm(CategoryForm):
|
||||||
|
... class Meta(CategoryForm.Meta):
|
||||||
|
... exclude = ['url']
|
||||||
|
|
||||||
|
>>> print SubCategoryForm()
|
||||||
|
<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
|
||||||
|
<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr>
|
||||||
|
<tr><th><label for="id_checkbox">Checkbox:</label></th><td><input type="checkbox" name="checkbox" id="id_checkbox" /></td></tr>
|
||||||
|
|
||||||
# Old form_for_x tests #######################################################
|
# Old form_for_x tests #######################################################
|
||||||
|
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
"""
|
"""
|
||||||
24. Mutually referential many-to-one relationships
|
24. Mutually referential many-to-one relationships
|
||||||
|
|
||||||
To define a many-to-one relationship, use ``ForeignKey()`` .
|
Strings can be used instead of model literals to set up "lazy" relations.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.db.models import *
|
from django.db.models import *
|
||||||
|
|
||||||
class Parent(Model):
|
class Parent(Model):
|
||||||
name = CharField(max_length=100, core=True)
|
name = CharField(max_length=100, core=True)
|
||||||
|
|
||||||
|
# Use a simple string for forward declarations.
|
||||||
bestchild = ForeignKey("Child", null=True, related_name="favoured_by")
|
bestchild = ForeignKey("Child", null=True, related_name="favoured_by")
|
||||||
|
|
||||||
class Child(Model):
|
class Child(Model):
|
||||||
name = CharField(max_length=100)
|
name = CharField(max_length=100)
|
||||||
parent = ForeignKey(Parent)
|
|
||||||
|
# You can also explicitally specify the related app.
|
||||||
|
parent = ForeignKey("mutually_referential.Parent")
|
||||||
|
|
||||||
__test__ = {'API_TESTS':"""
|
__test__ = {'API_TESTS':"""
|
||||||
# Create a Parent
|
# Create a Parent
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
6. Specifying ordering
|
6. Specifying ordering
|
||||||
|
|
||||||
Specify default ordering for a model using the ``ordering`` attribute, which
|
Specify default ordering for a model using the ``ordering`` attribute, which
|
||||||
should be a list or tuple of field names. This tells Django how to order the
|
should be a list or tuple of field names. This tells Django how to order
|
||||||
results of ``get_list()`` and other similar functions.
|
queryset results.
|
||||||
|
|
||||||
If a field name in ``ordering`` starts with a hyphen, that field will be
|
If a field name in ``ordering`` starts with a hyphen, that field will be
|
||||||
ordered in descending order. Otherwise, it'll be ordered in ascending order.
|
ordered in descending order. Otherwise, it'll be ordered in ascending order.
|
||||||
|
@ -77,6 +77,8 @@ MultiValueDictKeyError: "Key 'lastname' not found in <MultiValueDict: {'position
|
|||||||
'not one'
|
'not one'
|
||||||
>>> d.keys() == d.copy().keys()
|
>>> d.keys() == d.copy().keys()
|
||||||
True
|
True
|
||||||
|
>>> d2 = d.copy()
|
||||||
|
>>> d2['four'] = 'four'
|
||||||
>>> print repr(d)
|
>>> print repr(d)
|
||||||
{'one': 'not one', 'two': 'two', 'three': 'three'}
|
{'one': 'not one', 'two': 'two', 'three': 'three'}
|
||||||
>>> d.pop('one', 'missing')
|
>>> d.pop('one', 'missing')
|
||||||
@ -99,6 +101,12 @@ Init from sequence of tuples
|
|||||||
>>> print repr(d)
|
>>> print repr(d)
|
||||||
{1: 'one', 0: 'zero', 2: 'two'}
|
{1: 'one', 0: 'zero', 2: 'two'}
|
||||||
|
|
||||||
|
>>> d.clear()
|
||||||
|
>>> d
|
||||||
|
{}
|
||||||
|
>>> d.keyOrder
|
||||||
|
[]
|
||||||
|
|
||||||
### DotExpandedDict ############################################################
|
### DotExpandedDict ############################################################
|
||||||
|
|
||||||
>>> d = DotExpandedDict({'person.1.firstname': ['Simon'], 'person.1.lastname': ['Willison'], 'person.2.firstname': ['Adrian'], 'person.2.lastname': ['Holovaty']})
|
>>> d = DotExpandedDict({'person.1.firstname': ['Simon'], 'person.1.lastname': ['Willison'], 'person.2.firstname': ['Adrian'], 'person.2.lastname': ['Holovaty']})
|
||||||
|
@ -56,4 +56,30 @@ datetime.date(1938, 6, 4)
|
|||||||
datetime.time(5, 30)
|
datetime.time(5, 30)
|
||||||
>>> d3.consumed_at
|
>>> d3.consumed_at
|
||||||
datetime.datetime(2007, 4, 20, 16, 19, 59)
|
datetime.datetime(2007, 4, 20, 16, 19, 59)
|
||||||
|
|
||||||
|
# Year boundary tests (ticket #3689)
|
||||||
|
|
||||||
|
>>> d = Donut(name='Date Test 2007', baked_date=datetime.datetime(year=2007, month=12, day=31), consumed_at=datetime.datetime(year=2007, month=12, day=31, hour=23, minute=59, second=59))
|
||||||
|
>>> d.save()
|
||||||
|
>>> d1 = Donut(name='Date Test 2006', baked_date=datetime.datetime(year=2006, month=1, day=1), consumed_at=datetime.datetime(year=2006, month=1, day=1))
|
||||||
|
>>> d1.save()
|
||||||
|
|
||||||
|
>>> Donut.objects.filter(baked_date__year=2007)
|
||||||
|
[<Donut: Date Test 2007>]
|
||||||
|
|
||||||
|
>>> Donut.objects.filter(baked_date__year=2006)
|
||||||
|
[<Donut: Date Test 2006>]
|
||||||
|
|
||||||
|
>>> Donut.objects.filter(consumed_at__year=2007).order_by('name')
|
||||||
|
[<Donut: Apple Fritter>, <Donut: Date Test 2007>]
|
||||||
|
|
||||||
|
>>> Donut.objects.filter(consumed_at__year=2006)
|
||||||
|
[<Donut: Date Test 2006>]
|
||||||
|
|
||||||
|
>>> Donut.objects.filter(consumed_at__year=2005)
|
||||||
|
[]
|
||||||
|
|
||||||
|
>>> Donut.objects.filter(consumed_at__year=2008)
|
||||||
|
[]
|
||||||
|
|
||||||
"""}
|
"""}
|
||||||
|
0
tests/regressiontests/decorators/__init__.py
Normal file
0
tests/regressiontests/decorators/__init__.py
Normal file
2
tests/regressiontests/decorators/models.py
Normal file
2
tests/regressiontests/decorators/models.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# A models.py so that tests run.
|
||||||
|
|
56
tests/regressiontests/decorators/tests.py
Normal file
56
tests/regressiontests/decorators/tests.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from sys import version_info
|
||||||
|
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.utils.functional import allow_lazy, lazy, memoize
|
||||||
|
from django.views.decorators.http import require_http_methods, require_GET, require_POST
|
||||||
|
from django.views.decorators.vary import vary_on_headers, vary_on_cookie
|
||||||
|
from django.views.decorators.cache import cache_page, never_cache, cache_control
|
||||||
|
from django.contrib.auth.decorators import login_required, permission_required, user_passes_test
|
||||||
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
|
|
||||||
|
def fully_decorated(request):
|
||||||
|
"""Expected __doc__"""
|
||||||
|
return HttpResponse('<html><body>dummy</body></html>')
|
||||||
|
fully_decorated.anything = "Expected __dict__"
|
||||||
|
|
||||||
|
# django.views.decorators.http
|
||||||
|
fully_decorated = require_http_methods(["GET"])(fully_decorated)
|
||||||
|
fully_decorated = require_GET(fully_decorated)
|
||||||
|
fully_decorated = require_POST(fully_decorated)
|
||||||
|
|
||||||
|
# django.views.decorators.vary
|
||||||
|
fully_decorated = vary_on_headers('Accept-language')(fully_decorated)
|
||||||
|
fully_decorated = vary_on_cookie(fully_decorated)
|
||||||
|
|
||||||
|
# django.views.decorators.cache
|
||||||
|
fully_decorated = cache_page(60*15)(fully_decorated)
|
||||||
|
fully_decorated = cache_control(private=True)(fully_decorated)
|
||||||
|
fully_decorated = never_cache(fully_decorated)
|
||||||
|
|
||||||
|
# django.contrib.auth.decorators
|
||||||
|
fully_decorated = user_passes_test(lambda u:True)(fully_decorated)
|
||||||
|
fully_decorated = login_required(fully_decorated)
|
||||||
|
fully_decorated = permission_required('change_world')(fully_decorated)
|
||||||
|
|
||||||
|
# django.contrib.admin.views.decorators
|
||||||
|
fully_decorated = staff_member_required(fully_decorated)
|
||||||
|
|
||||||
|
# django.utils.functional
|
||||||
|
fully_decorated = memoize(fully_decorated, {}, 1)
|
||||||
|
fully_decorated = allow_lazy(fully_decorated)
|
||||||
|
fully_decorated = lazy(fully_decorated)
|
||||||
|
|
||||||
|
class DecoratorsTest(TestCase):
|
||||||
|
|
||||||
|
def test_attributes(self):
|
||||||
|
"""
|
||||||
|
Tests that django decorators set certain attributes of the wrapped
|
||||||
|
function.
|
||||||
|
"""
|
||||||
|
# Only check __name__ on Python 2.4 or later since __name__ can't be
|
||||||
|
# assigned to in earlier Python versions.
|
||||||
|
if version_info[0] >= 2 and version_info[1] >= 4:
|
||||||
|
self.assertEquals(fully_decorated.__name__, 'fully_decorated')
|
||||||
|
self.assertEquals(fully_decorated.__doc__, 'Expected __doc__')
|
||||||
|
self.assertEquals(fully_decorated.__dict__['anything'], 'Expected __dict__')
|
@ -0,0 +1,9 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"pk": "1",
|
||||||
|
"model": "fixtures_regress.absolute",
|
||||||
|
"fields": {
|
||||||
|
"name": "Load Absolute Path Test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -1,6 +1,7 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
import os
|
||||||
|
|
||||||
class Animal(models.Model):
|
class Animal(models.Model):
|
||||||
name = models.CharField(max_length=150)
|
name = models.CharField(max_length=150)
|
||||||
@ -28,6 +29,16 @@ class Stuff(models.Model):
|
|||||||
name = None
|
name = None
|
||||||
return unicode(name) + u' is owned by ' + unicode(self.owner)
|
return unicode(name) + u' is owned by ' + unicode(self.owner)
|
||||||
|
|
||||||
|
class Absolute(models.Model):
|
||||||
|
name = models.CharField(max_length=40)
|
||||||
|
|
||||||
|
load_count = 0
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(Absolute, self).__init__(*args, **kwargs)
|
||||||
|
Absolute.load_count += 1
|
||||||
|
|
||||||
|
|
||||||
__test__ = {'API_TESTS':"""
|
__test__ = {'API_TESTS':"""
|
||||||
>>> from django.core import management
|
>>> from django.core import management
|
||||||
|
|
||||||
@ -49,4 +60,15 @@ __test__ = {'API_TESTS':"""
|
|||||||
>>> Stuff.objects.all()
|
>>> Stuff.objects.all()
|
||||||
[<Stuff: None is owned by None>]
|
[<Stuff: None is owned by None>]
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
# Regression test for ticket #6436 --
|
||||||
|
# os.path.join will throw away the initial parts of a path if it encounters
|
||||||
|
# an absolute path. This means that if a fixture is specified as an absolute path,
|
||||||
|
# we need to make sure we don't discover the absolute path in every fixture directory.
|
||||||
|
|
||||||
|
>>> load_absolute_path = os.path.join(os.path.dirname(__file__), 'fixtures', 'absolute.json')
|
||||||
|
>>> management.call_command('loaddata', load_absolute_path, verbosity=0)
|
||||||
|
>>> Absolute.load_count
|
||||||
|
1
|
||||||
|
|
||||||
"""}
|
"""}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
tests = """
|
tests = """
|
||||||
>>> from django.utils.translation.trans_real import parse_accept_lang_header
|
>>> from django.utils.translation.trans_real import parse_accept_lang_header
|
||||||
>>> p = parse_accept_lang_header
|
>>> p = parse_accept_lang_header
|
||||||
@ -83,7 +85,14 @@ source tree.
|
|||||||
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-ar,de'}
|
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-ar,de'}
|
||||||
>>> g(r)
|
>>> g(r)
|
||||||
'es-ar'
|
'es-ar'
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Python 2.3 returns slightly different results for completely bogus locales,
|
||||||
|
# so we omit this test for that anything below 2.4. It's relatively harmless in
|
||||||
|
# any cases (GIGO). This also means this won't be executed on Jython currently,
|
||||||
|
# but life's like that sometimes.
|
||||||
|
if sys.version_info >= (2, 4):
|
||||||
|
tests += """
|
||||||
This test assumes there won't be a Django translation to a US variation
|
This test assumes there won't be a Django translation to a US variation
|
||||||
of the Spanish language, a safe assumption. When the user sets it
|
of the Spanish language, a safe assumption. When the user sets it
|
||||||
as the preferred language, the main 'es' translation should be selected
|
as the preferred language, the main 'es' translation should be selected
|
||||||
@ -91,7 +100,9 @@ instead.
|
|||||||
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-us'}
|
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-us'}
|
||||||
>>> g(r)
|
>>> g(r)
|
||||||
'es'
|
'es'
|
||||||
|
"""
|
||||||
|
|
||||||
|
tests += """
|
||||||
This tests the following scenario: there isn't a main language (zh)
|
This tests the following scenario: there isn't a main language (zh)
|
||||||
translation of Django but there is a translation to variation (zh_CN)
|
translation of Django but there is a translation to variation (zh_CN)
|
||||||
the user sets zh-cn as the preferred language, it should be selected by
|
the user sets zh-cn as the preferred language, it should be selected by
|
||||||
|
@ -39,6 +39,7 @@ class Base(models.Model):
|
|||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
name = models.CharField(max_length=50)
|
name = models.CharField(max_length=50)
|
||||||
text = models.TextField()
|
text = models.TextField()
|
||||||
|
submitted_from = models.IPAddressField(blank=True, null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Article %s" % self.name
|
return "Article %s" % self.name
|
||||||
@ -98,4 +99,11 @@ __test__ = {'API_TESTS': ur"""
|
|||||||
|
|
||||||
>>> Article.objects.get(text__contains='quick brown fox')
|
>>> Article.objects.get(text__contains='quick brown fox')
|
||||||
<Article: Article Test>
|
<Article: Article Test>
|
||||||
|
|
||||||
|
# Regression test for #708: "like" queries on IP address fields require casting
|
||||||
|
# to text (on PostgreSQL).
|
||||||
|
>>> Article(name='IP test', text='The body', submitted_from='192.0.2.100').save()
|
||||||
|
>>> Article.objects.filter(submitted_from__contains='192.0.2')
|
||||||
|
[<Article: Article IP test>]
|
||||||
|
|
||||||
"""}
|
"""}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user