1
0
mirror of https://github.com/django/django.git synced 2025-07-04 01:39:20 +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:
Justin Bronn 2008-02-28 21:24:51 +00:00
parent 0b52413cc9
commit 22e016ff6c
76 changed files with 9570 additions and 238 deletions

View File

@ -56,6 +56,7 @@ answer newbie questions, and generally made Django that much better:
David Ascher <http://ascher.ca/>
Jökull Sólberg Auðunsson <jokullsolberg@gmail.com>
Arthur <avandorp@gmail.com>
David Avsajanishvili <avsd05@gmail.com>
axiak@mit.edu
Jiri Barton
Ned Batchelder <http://www.nedbatchelder.com/>
@ -70,6 +71,7 @@ answer newbie questions, and generally made Django that much better:
boobsd@gmail.com
Andrew Brehaut <http://brehaut.net/blog>
brut.alll@gmail.com
btoll@bestweb.net
Jonathan Buchanan <jonathan.buchanan@gmail.com>
Can Burak Çilingir <canburak@cs.bilgi.edu.tr>
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/>
Jason Huggins <http://www.jrandolph.com/blog/>
Hyun Mi Ae
Ibon <ibonso@gmail.com>
Tom Insam
Baurzhan Ismagulov <ibr@radix50.net>
james_027@yahoo.com

View File

@ -48,10 +48,11 @@ LANGUAGES = (
('en', gettext_noop('English')),
('es', gettext_noop('Spanish')),
('es-ar', gettext_noop('Argentinean Spanish')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('ga', gettext_noop('Gaeilge')),
('ga', gettext_noop('Irish')),
('gl', gettext_noop('Galician')),
('hu', gettext_noop('Hungarian')),
('he', gettext_noop('Hebrew')),
@ -59,6 +60,7 @@ LANGUAGES = (
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('ko', gettext_noop('Korean')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View 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"

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View 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 "ხვალ"

View File

@ -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.conf import settings
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.utils.translation import ugettext_lazy, ugettext as _
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.")
LOGIN_FORM_KEY = 'this_is_the_login_form'
@ -104,4 +110,4 @@ def staff_member_required(view_func):
else:
return _display_login_form(request, ERROR_MESSAGE)
return _checklogin
return wraps(view_func)(_checklogin)

View File

@ -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.http import HttpResponseRedirect
from django.utils.http import urlquote
@ -51,7 +56,7 @@ class _CheckLogin(object):
self.test_func = test_func
self.login_url = login_url
self.redirect_field_name = redirect_field_name
self.__name__ = view_func.__name__
update_wrapper(self, view_func)
def __get__(self, obj, cls=None):
view_func = self.view_func.__get__(obj, cls)

View File

@ -8,8 +8,6 @@ from django.utils.translation import get_date_formats
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
from django.views.generic import date_based
import datetime
import time
class CalendarPlugin(DatabrowsePlugin):
def __init__(self, field_names=None):

View File

@ -7,8 +7,6 @@ from django.utils.text import capfirst
from django.utils.encoding import smart_str, force_unicode
from django.utils.safestring import mark_safe
from django.views.generic import date_based
import datetime
import time
import urllib
class FieldChoicePlugin(DatabrowsePlugin):

View File

@ -2,8 +2,6 @@ from django.db.models import FieldDoesNotExist, DateTimeField
from django.http import Http404
from django.shortcuts import render_to_response
from django.contrib.databrowse.datastructures import EasyModel, EasyChoice
import datetime
import time
###########
# CHOICES #

View File

@ -3,7 +3,6 @@ Formtools Preview application.
"""
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404
from django.shortcuts import render_to_response
from django.template.context import RequestContext

View File

@ -3,8 +3,6 @@ from django.contrib.formtools import preview
from django import http
from django.conf import settings
from django.test import TestCase
from django.test.client import Client
success_string = "Done was called!"
test_data = {'field1': u'foo',
@ -88,6 +86,3 @@ class PreviewTests(TestCase):
response = self.client.post('/test1/', test_data)
self.assertEqual(response.content, success_string)
if __name__ == '__main__':
unittest.main()

View File

@ -2,8 +2,7 @@ from django.utils.translation import ungettext, ugettext as _
from django.utils.encoding import force_unicode
from django import template
from django.template import defaultfilters
from django.conf import settings
from datetime import date, timedelta
from datetime import date
import re
register = template.Library()

View File

@ -7,7 +7,6 @@ from django.newforms import ValidationError
from django.newforms.fields import RegexField, CharField, Select, EMPTY_VALUES
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext
import re
class ARProvinceSelect(Select):
"""

View File

@ -7,8 +7,6 @@ from django.newforms import ValidationError
from django.utils.translation import ugettext
from django.newforms.fields import RegexField, Select
import re
class JPPostalCodeField(RegexField):
"""
A form field that validates its input is a Japanese postcode.

View File

@ -1,10 +1,5 @@
import os
import sys
import time
import datetime
import base64
import md5
import random
import cPickle as pickle
from django.db import models

View File

@ -14,7 +14,6 @@ u'lorem ipsum dolor'
"""
from django.contrib.webdesign.lorem_ipsum import *
import datetime
if __name__ == '__main__':
import doctest

View File

@ -109,7 +109,8 @@ class BaseHandler(object):
except exceptions.PermissionDenied:
return http.HttpResponseForbidden('<h1>Permission denied</h1>')
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.
# Get the exception info now, in case another exception is thrown later.
exc_info = sys.exc_info()

View File

@ -30,7 +30,8 @@ class Command(BaseCommand):
show_traceback = options.get('traceback', False)
# Keep a count of the installed objects and fixtures
count = [0, 0]
fixture_count = 0
object_count = 0
models = set()
humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path'
@ -65,7 +66,12 @@ class Command(BaseCommand):
else:
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:
print "Checking %s for fixtures..." % humanize(fixture_dir)
@ -86,14 +92,14 @@ class Command(BaseCommand):
transaction.leave_transaction_management()
return
else:
count[1] += 1
fixture_count += 1
if verbosity > 0:
print "Installing %s fixture '%s' from %s." % \
(format, fixture_name, humanize(fixture_dir))
try:
objects = serializers.deserialize(format, fixture)
for obj in objects:
count[0] += 1
object_count += 1
models.add(obj.object.__class__)
obj.save()
label_found = True
@ -113,7 +119,7 @@ class Command(BaseCommand):
print "No %s fixture '%s' in %s." % \
(format, fixture_name, humanize(fixture_dir))
if count[0] > 0:
if object_count > 0:
sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
if sequence_sql:
if verbosity > 1:
@ -124,9 +130,9 @@ class Command(BaseCommand):
transaction.commit()
transaction.leave_transaction_management()
if count[0] == 0:
if object_count == 0:
if verbosity >= 2:
print "No fixtures found."
else:
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)

View File

@ -1,7 +1,7 @@
from django.core.management.base import 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

View File

@ -4,7 +4,6 @@ Serialize data to/from JSON
import datetime
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 Deserializer as PythonDeserializer
try:

View File

@ -4,7 +4,6 @@ YAML serializer.
Requires PyYaml (http://pyyaml.org/), but that's checked for in __init__.
"""
import datetime
from django.db import models
from django.core.serializers.python import Serializer as PythonSerializer
from django.core.serializers.python import Deserializer as PythonDeserializer

View File

@ -21,7 +21,6 @@ if (version < (1,2,1) or (version[:3] == (1, 2, 1) and
from MySQLdb.converters import conversions
from MySQLdb.constants import FIELD_TYPE
import types
import re
# Raise exceptions for database warnings if DEBUG is on

View File

@ -27,6 +27,11 @@ class DatabaseOperations(BaseDatabaseOperations):
def deferrable_sql(self):
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):
cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (table_name, pk_name))
return cursor.fetchone()[0]

View File

@ -41,7 +41,9 @@ class ModelBase(type):
# Build complete list of 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.extend(base._meta.parents)
@ -133,13 +135,16 @@ class Model(object):
def __ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
return hash(self._get_pk_val())
def __init__(self, *args, **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
# 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
# args, and nstantiation for iteration is 33% faster.
# args, and instantiation for iteration is 33% faster.
args_len = len(args)
if args_len > len(self._meta.fields):
# Daft, but matches old exception sans the err msg.

View File

@ -228,7 +228,11 @@ class Field(object):
value = int(value)
except ValueError:
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)
def has_default(self):
@ -451,6 +455,9 @@ class BooleanField(Field):
kwargs['blank'] = True
Field.__init__(self, *args, **kwargs)
def get_internal_type(self):
return "BooleanField"
def to_python(self, value):
if value in (True, False): return value
if value in ('t', 'True', '1'): return True
@ -469,6 +476,9 @@ class CharField(Field):
def get_manipulator_field_objs(self):
return [oldforms.TextField]
def get_internal_type(self):
return "CharField"
def to_python(self, value):
if isinstance(value, basestring):
return value
@ -499,6 +509,9 @@ class DateField(Field):
kwargs['blank'] = True
Field.__init__(self, verbose_name, name, **kwargs)
def get_internal_type(self):
return "DateField"
def to_python(self, value):
if value is None:
return value
@ -568,6 +581,9 @@ class DateField(Field):
return super(DateField, self).formfield(**defaults)
class DateTimeField(DateField):
def get_internal_type(self):
return "DateTimeField"
def to_python(self, value):
if value is None:
return value
@ -638,6 +654,9 @@ class DecimalField(Field):
self.max_digits, self.decimal_places = max_digits, decimal_places
Field.__init__(self, verbose_name, name, **kwargs)
def get_internal_type(self):
return "DecimalField"
def to_python(self, value):
if value is None:
return value
@ -697,9 +716,6 @@ class EmailField(CharField):
kwargs['max_length'] = kwargs.get('max_length', 75)
CharField.__init__(self, *args, **kwargs)
def get_internal_type(self):
return "CharField"
def get_manipulator_field_objs(self):
return [oldforms.EmailField]
@ -717,6 +733,9 @@ class FileField(Field):
kwargs['max_length'] = kwargs.get('max_length', 100)
Field.__init__(self, verbose_name, name, **kwargs)
def get_internal_type(self):
return "FileField"
def get_db_prep_save(self, value):
"Returns field's value prepared for saving into a database."
# 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):
return [curry(oldforms.FilePathField, path=self.path, match=self.match, recursive=self.recursive)]
def get_internal_type(self):
return "FilePathField"
class FloatField(Field):
empty_strings_allowed = False
def get_manipulator_field_objs(self):
return [oldforms.FloatField]
def get_internal_type(self):
return "FloatField"
def formfield(self, **kwargs):
defaults = {'form_class': forms.FloatField}
defaults.update(kwargs)
@ -854,6 +879,9 @@ class ImageField(FileField):
if not self.height_field:
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):
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
@ -876,6 +904,9 @@ class IntegerField(Field):
def get_manipulator_field_objs(self):
return [oldforms.IntegerField]
def get_internal_type(self):
return "IntegerField"
def formfield(self, **kwargs):
defaults = {'form_class': forms.IntegerField}
defaults.update(kwargs)
@ -890,6 +921,9 @@ class IPAddressField(Field):
def get_manipulator_field_objs(self):
return [oldforms.IPAddressField]
def get_internal_type(self):
return "IPAddressField"
def validate(self, field_data, all_data):
validators.isValidIPAddress4(field_data, None)
@ -904,6 +938,9 @@ class NullBooleanField(Field):
kwargs['null'] = True
Field.__init__(self, *args, **kwargs)
def get_internal_type(self):
return "NullBooleanField"
def to_python(self, value):
if value in (None, True, False): return value
if value in ('None'): return None
@ -923,6 +960,9 @@ class PhoneNumberField(IntegerField):
def get_manipulator_field_objs(self):
return [oldforms.PhoneNumberField]
def get_internal_type(self):
return "PhoneNumberField"
def validate(self, field_data, all_data):
validators.isValidPhone(field_data, all_data)
@ -936,6 +976,9 @@ class PositiveIntegerField(IntegerField):
def get_manipulator_field_objs(self):
return [oldforms.PositiveIntegerField]
def get_internal_type(self):
return "PositiveIntegerField"
def formfield(self, **kwargs):
defaults = {'min_value': 0}
defaults.update(kwargs)
@ -945,6 +988,9 @@ class PositiveSmallIntegerField(IntegerField):
def get_manipulator_field_objs(self):
return [oldforms.PositiveSmallIntegerField]
def get_internal_type(self):
return "PositiveSmallIntegerField"
def formfield(self, **kwargs):
defaults = {'min_value': 0}
defaults.update(kwargs)
@ -959,14 +1005,23 @@ class SlugField(CharField):
kwargs['db_index'] = True
super(SlugField, self).__init__(*args, **kwargs)
def get_internal_type(self):
return "SlugField"
class SmallIntegerField(IntegerField):
def get_manipulator_field_objs(self):
return [oldforms.SmallIntegerField]
def get_internal_type(self):
return "SmallIntegerField"
class TextField(Field):
def get_manipulator_field_objs(self):
return [oldforms.LargeTextField]
def get_internal_type(self):
return "TextField"
def formfield(self, **kwargs):
defaults = {'widget': forms.Textarea}
defaults.update(kwargs)
@ -980,6 +1035,9 @@ class TimeField(Field):
kwargs['editable'] = False
Field.__init__(self, verbose_name, name, **kwargs)
def get_internal_type(self):
return "TimeField"
def get_db_prep_lookup(self, lookup_type, value):
if settings.DATABASE_ENGINE == 'oracle':
# Oracle requires a date in order to parse.
@ -1044,9 +1102,6 @@ class URLField(CharField):
def get_manipulator_field_objs(self):
return [oldforms.URLField]
def get_internal_type(self):
return "CharField"
def formfield(self, **kwargs):
defaults = {'form_class': forms.URLField, 'verify_exists': self.verify_exists}
defaults.update(kwargs)
@ -1056,6 +1111,9 @@ class USStateField(Field):
def get_manipulator_field_objs(self):
return [oldforms.USStateField]
def get_internal_type(self):
return "USStateField"
def formfield(self, **kwargs):
from django.contrib.localflavor.us.forms import USStateSelect
defaults = {'widget': USStateSelect}
@ -1067,9 +1125,6 @@ class XMLField(TextField):
self.schema_path = schema_path
Field.__init__(self, verbose_name, name, **kwargs)
def get_internal_type(self):
return "TextField"
def get_manipulator_field_objs(self):
return [curry(oldforms.XMLLargeTextField, schema_path=self.schema_path)]
@ -1080,8 +1135,5 @@ class OrderingField(IntegerField):
kwargs['null'] = True
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):
return [oldforms.HiddenField(name_prefix + self.name)]

View File

@ -23,26 +23,64 @@ RECURSIVE_RELATIONSHIP_CONSTANT = 'self'
pending_lookups = {}
def add_lookup(rel_cls, field):
name = field.rel.to
module = rel_cls.__module__
key = (module, name)
# Has the model already been loaded?
# If so, resolve the string reference right away
model = get_model(rel_cls._meta.app_label, field.rel.to, False)
def add_lazy_relation(cls, field, relation):
"""
Adds a lookup on ``cls`` when a related field is defined using a string,
i.e.::
class MyModel(Model):
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:
field.rel.to = model
field.do_related_class(model, rel_cls)
field.do_related_class(model, cls)
else:
# Mark the related field for later lookup
pending_lookups.setdefault(key, []).append((rel_cls, field))
key = (app_label, model_name)
value = (cls, field)
pending_lookups.setdefault(key, []).append(value)
def do_pending_lookups(sender):
other_cls = sender
key = (other_cls.__module__, other_cls.__name__)
for rel_cls, field in pending_lookups.setdefault(key, []):
field.rel.to = other_cls
field.do_related_class(other_cls, rel_cls)
"""
Handle any pending relations to the sending model. Sent from class_prepared.
"""
key = (sender._meta.app_label, sender.__name__)
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)
@ -66,9 +104,7 @@ class RelatedField(object):
sup.contribute_to_class(cls, name)
other = self.rel.to
if isinstance(other, basestring):
if other == RECURSIVE_RELATIONSHIP_CONSTANT:
self.rel.to = cls.__name__
add_lookup(cls, self)
add_lazy_relation(cls, self, other)
else:
self.do_related_class(other, cls)

View File

@ -171,7 +171,7 @@ class QueryDict(MultiValueDict):
dict.__setitem__(result, key, value)
return result
def __deepcopy__(self, memo={}):
def __deepcopy__(self, memo):
import copy
result = self.__class__('', mutable=True)
memo[id(self)] = result
@ -223,7 +223,7 @@ class QueryDict(MultiValueDict):
def copy(self):
"Returns a mutable copy of this object."
return self.__deepcopy__()
return self.__deepcopy__({})
def urlencode(self):
output = []

View File

@ -22,23 +22,40 @@ def pretty_name(name):
name = name[0].upper() + name[1:]
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
'base_fields', taking into account parent class 'base_fields' as well.
Create a list of form field instances from the passed in 'attrs', plus any
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.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.
# Note that we loop over the bases in *reverse*. This is necessary in
# order to preserve the correct order of fields.
if with_base_fields:
for base in bases[::-1]:
if hasattr(base, 'base_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)
class BaseForm(StrAndUnicode):

View File

@ -11,7 +11,7 @@ from django.utils.datastructures import SortedDict
from django.core.exceptions import ImproperlyConfigured
from util import ValidationError, ErrorList
from forms import BaseForm
from forms import BaseForm, get_declared_fields
from fields import Field, ChoiceField, EMPTY_VALUES
from widgets import Select, SelectMultiple, MultipleHiddenInput
@ -211,57 +211,39 @@ class ModelFormOptions(object):
self.fields = getattr(options, 'fields', None)
self.exclude = getattr(options, 'exclude', None)
class ModelFormMetaclass(type):
def __new__(cls, name, bases, attrs,
formfield_callback=lambda f: f.formfield()):
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))
try:
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.
# Note that we loop over the bases in *reverse*. This is necessary in
# order to preserve the correct order of fields.
for base in bases[::-1]:
if hasattr(base, 'base_fields'):
fields = base.base_fields.items() + 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,
new_class = type.__new__(cls, name, bases, attrs)
declared_fields = get_declared_fields(bases, attrs, False)
opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))
if opts.model:
# If a model is defined, extract form fields from it.
fields = fields_for_model(opts.model, opts.fields,
opts.exclude, formfield_callback)
# fields declared in base classes override fields from the model
model_fields.update(declared_fields)
attrs['base_fields'] = model_fields
# Override default model fields with any custom declared ones
# (plus, include all the other declared fields).
fields.update(declared_fields)
else:
attrs['base_fields'] = declared_fields
return type.__new__(cls, name, bases, attrs)
fields = declared_fields
new_class.declared_fields = declared_fields
new_class.base_fields = fields
return new_class
class BaseModelForm(BaseForm):
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
if instance is None:
# if we didn't get an instance, instantiate a new one
@ -277,7 +259,8 @@ class BaseModelForm(BaseForm):
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
database. Returns ``instance``.

View File

@ -2,6 +2,10 @@
import re
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.conf import settings
@ -35,7 +39,7 @@ def stringfilter(func):
for attr in ('is_safe', 'needs_autoescape'):
if hasattr(func, attr):
setattr(_dec, attr, getattr(func, attr))
return _dec
return wraps(func)(_dec)
###################
# STRINGS #

View File

@ -100,7 +100,7 @@ __all__ = [
import __future__
import sys, traceback, inspect, linecache, os, re, types
import sys, traceback, inspect, linecache, os, re
import unittest, difflib, pdb, tempfile
import warnings
from StringIO import StringIO

View File

@ -1,7 +1,5 @@
import datetime
import sys
from cStringIO import StringIO
from urlparse import urlparse
from django.conf import settings
from django.contrib.auth import authenticate, login
from django.core.handlers.base import BaseHandler

View File

@ -146,4 +146,3 @@ def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[]):
teardown_test_environment()
return len(result.failures) + len(result.errors)

View File

@ -3,7 +3,7 @@ class MergeDict(object):
A simple class for creating new "virtual" dictionaries that actually look
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.
"""
def __init__(self, *dicts):
@ -145,7 +145,7 @@ class SortedDict(dict):
"""Returns a copy of this object."""
# This way of initializing the copy means it works for subclasses, too.
obj = self.__class__(self)
obj.keyOrder = self.keyOrder
obj.keyOrder = self.keyOrder[:]
return obj
def __repr__(self):
@ -155,6 +155,10 @@ class SortedDict(dict):
"""
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):
pass

View File

@ -1,6 +1,10 @@
"Functions that help with dynamically creating decorators for views."
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):
"""
@ -53,5 +57,5 @@ def decorator_from_middleware(middleware_class):
if result is not None:
return result
return response
return _wrapped_view
return wraps(view_func)(_wrapped_view)
return _decorator_from_middleware

View File

@ -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 _curried(*moreargs, **morekwargs):
return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
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):
"""
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)
cache[mem_args] = result
return result
return wrapper
return wraps(func)(wrapper)
class Promise(object):
"""
@ -110,7 +222,7 @@ def lazy(func, *resultclasses):
# Creates the proxy object, instead of the actual value.
return __proxy__(args, kw)
return __wrapper__
return wraps(func)(__wrapper__)
def allow_lazy(func, *resultclasses):
"""
@ -126,4 +238,4 @@ def allow_lazy(func, *resultclasses):
else:
return func(*args, **kwargs)
return lazy(func, *resultclasses)(*args, **kwargs)
return wrapper
return wraps(func)(wrapper)

View File

@ -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.
"""
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.cache import patch_cache_control, add_never_cache_headers
from django.middleware.cache import CacheMiddleware
@ -26,7 +31,7 @@ def cache_control(**kwargs):
patch_cache_control(response, **kwargs)
return response
return _cache_controlled
return wraps(viewfunc)(_cache_controlled)
return _cache_controller
@ -39,4 +44,4 @@ def never_cache(view_func):
response = view_func(request, *args, **kwargs)
add_never_cache_headers(response)
return response
return _wrapped_view_func
return wraps(view_func)(_wrapped_view_func)

View File

@ -2,6 +2,11 @@
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.middleware.http import ConditionalGetMiddleware
from django.http import HttpResponseNotAllowed
@ -24,7 +29,7 @@ def require_http_methods(request_method_list):
if request.method not in request_method_list:
return HttpResponseNotAllowed(request_method_list)
return func(request, *args, **kwargs)
return inner
return wraps(func)(inner)
return decorator
require_GET = require_http_methods(["GET"])

View File

@ -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
def vary_on_headers(*headers):
@ -16,7 +21,7 @@ def vary_on_headers(*headers):
response = func(*args, **kwargs)
patch_vary_headers(response, headers)
return response
return inner_func
return wraps(func)(inner_func)
return decorator
def vary_on_cookie(func):
@ -32,4 +37,4 @@ def vary_on_cookie(func):
response = func(*args, **kwargs)
patch_vary_headers(response, ('Cookie',))
return response
return inner_func
return wraps(func)(inner_func)

View File

@ -88,7 +88,7 @@ change:
API changes may be necessary.
- 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.
- The comments framework, which is yet undocumented, will likely get a complete

View File

@ -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
creating a ``TaggedItem``::
>>> from django.contrib.models.auth import User
>>> from django.contrib.auth.models import User
>>> guido = User.objects.get(username='Guido')
>>> t = TaggedItem(content_object=guido, tag='bdfl')
>>> 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
be used to retrieve their associated ``TaggedItems``::
>>> b = Bookmark('http://www.djangoproject.com/')
>>> b = Bookmark(url='http://www.djangoproject.com/')
>>> b.save()
>>> t1 = TaggedItem(content_object=b, tag='django')
>>> t1.save()

View File

@ -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.
``select_related()`` is documented in the "QuerySet methods that return new
QuerySets" section above.
``select_related()`` is documented in the `QuerySet methods that return new QuerySets`_ section above.
Backward
~~~~~~~~

View File

@ -5,7 +5,7 @@ Third-party distributions of Django
Several third-party distributors are now providing versions of Django integrated
with their package-management systems. These can make installation and upgrading
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.
Typically, these packages are based on the latest stable release of Django, so

View File

@ -767,7 +767,7 @@ a command that can be executed as an action when you run ``manage.py``::
views.py
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
called ``Command`` that extends ``django.core.management.base.BaseCommand``.

View File

@ -353,7 +353,7 @@ How do I install mod_python on Windows?
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
.. _`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
.. _`guide to getting mod_python working`: http://www.dscpl.com.au/articles/modpython-001.html

View File

@ -138,7 +138,7 @@ Installing a distribution-specific package
Check the `distribution specific notes`_ to see if your
platform/distribution provides official Django packages/installers.
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -384,7 +384,7 @@ The admin represents this as an ``<input type="text">`` (a single-line input).
``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).
@ -784,9 +784,17 @@ you can use the name of the model, rather than the model object itself::
class Manufacturer(models.Model):
# ...
Note, however, that you can only use strings to refer to models in the same
models.py file -- you cannot use a string to reference a model in a different
application, or to reference a model that has been imported from elsewhere.
Note, however, that this only refers to models in the same models.py file -- you
cannot use a string to reference a model defined in another application or
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
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.
``symmetrical`` Only used in the definition of ManyToManyFields on self.
Consider the following model:
Consider the following model::
class Person(models.Model):
friends = models.ManyToManyField("self")
@ -1872,7 +1880,7 @@ more simply as::
If you define a ``__unicode__()`` method on your model and not a ``__str__()``
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
``__unicode__()`` and let Django take care of the conversion to string objects
when required.

View File

@ -320,3 +320,41 @@ parameter when declaring the form field::
...
... class Meta:
... 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.

View File

@ -576,7 +576,7 @@ Three things to note about 404 views:
in the 404.
* 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``).
* If ``DEBUG`` is set to ``True`` (in your settings module), then your 404

View File

@ -88,7 +88,7 @@ something like::
for deserialized_object in serializers.deserialize("xml", data):
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
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.

View File

@ -30,9 +30,9 @@ Optional arguments
``context_instance``
The context instance to render the template with. By default, the template
will be rendered with a ``Context`` instance (filled with values from
``dictionary``). If you need to use `context processors`_, you will want to
render the template with a ``RequestContext`` instance instead. Your code
might look something like this::
``dictionary``). If you need to use `context processors`_, render the
template with a ``RequestContext`` instance instead. Your code might look
something like this::
return render_to_response('my_template.html',
my_data_dictionary,

View File

@ -1406,6 +1406,8 @@ Joins a list with a string, like Python's ``str.join(list)``.
last
~~~~
**New in Django development version.**
Returns the last item in a list.
length

View File

@ -395,6 +395,8 @@ See the `internationalization docs`_ for more.
django.core.context_processors.media
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version**
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
``RequestContext`` will contain a variable ``MEDIA_URL``, providing the
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::
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))
If we had neglected to pass in the current ``context.autoescape`` value to our

View File

@ -190,6 +190,28 @@ The remaining arguments should be tuples in this format::
...where ``optional dictionary`` and ``optional name`` are optional. (See
`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
---

View File

@ -61,13 +61,13 @@ _django_completion()
||
# python manage.py, /some/path/python manage.py (if manage.py exists)
( ${COMP_CWORD} -eq 2 &&
( $( basename ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
( $( basename ${COMP_WORDS[1]} ) == manage.py) &&
( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
( $( basename -- ${COMP_WORDS[1]} ) == manage.py) &&
( -r ${COMP_WORDS[1]} ) )
||
( ${COMP_CWORD} -eq 2 &&
( $( basename ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
( $( basename ${COMP_WORDS[1]} ) == django-admin.py) &&
( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
( $( basename -- ${COMP_WORDS[1]} ) == django-admin.py) &&
( -r ${COMP_WORDS[1]} ) ) ]] ; then
case ${cur} in
@ -149,7 +149,7 @@ unset pythons
if command -v whereis &>/dev/null; then
python_interpreters=$(whereis python | cut -d " " -f 2-)
for python in $python_interpreters; do
pythons="${pythons} $(basename $python)"
pythons="${pythons} $(basename -- $python)"
done
pythons=$(echo $pythons | tr " " "\n" | sort -u | tr "\n" " ")
else

View File

@ -27,19 +27,16 @@ for scheme in INSTALL_SCHEMES.values():
# an easy way to do this.
packages, data_files = [], []
root_dir = os.path.dirname(__file__)
django_dir = os.path.join(root_dir, 'django')
pieces = fullsplit(root_dir)
if pieces[-1] == '':
len_root_dir = len(pieces) - 1
else:
len_root_dir = len(pieces)
if root_dir != '':
os.chdir(root_dir)
django_dir = 'django'
for dirpath, dirnames, filenames in os.walk(django_dir):
# Ignore dirnames that start with '.'
for i, dirname in enumerate(dirnames):
if dirname.startswith('.'): del dirnames[i]
if '__init__.py' in filenames:
packages.append('.'.join(fullsplit(dirpath)[len_root_dir:]))
packages.append('.'.join(fullsplit(dirpath)))
elif filenames:
data_files.append([dirpath, [os.path.join(dirpath, f) for f in filenames]])

View File

@ -5,6 +5,11 @@
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
class Article(models.Model):
@ -389,4 +394,10 @@ year, including Jan. 1 and Dec. 31.
>>> a.save()
>>> Article.objects.get(pk=a.id).headline
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
"""

View File

@ -155,29 +155,52 @@ familiar with the mechanics.
... class Meta:
... model = Category
>>> class BadForm(CategoryForm):
>>> class OddForm(CategoryForm):
... class Meta:
... model = Article
Traceback (most recent call last):
...
ImproperlyConfigured: BadForm defines a different model than its parent.
OddForm is now an Article-related thing, because BadForm.Meta overrides
CategoryForm.Meta.
>>> OddForm.base_fields.keys()
['headline', 'slug', 'pub_date', 'writer', 'article', 'status', 'categories']
>>> class ArticleForm(ModelForm):
... class Meta:
... model = Article
First class with a Meta class wins.
>>> class BadForm(ArticleForm, CategoryForm):
... pass
Traceback (most recent call last):
...
ImproperlyConfigured: BadForm's base classes define more than one model.
>>> OddForm.base_fields.keys()
['headline', 'slug', 'pub_date', 'writer', 'article', 'status', 'categories']
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:
... 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 #######################################################

View File

@ -1,18 +1,22 @@
"""
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 *
class Parent(Model):
name = CharField(max_length=100, core=True)
# Use a simple string for forward declarations.
bestchild = ForeignKey("Child", null=True, related_name="favoured_by")
class Child(Model):
name = CharField(max_length=100)
parent = ForeignKey(Parent)
# You can also explicitally specify the related app.
parent = ForeignKey("mutually_referential.Parent")
__test__ = {'API_TESTS':"""
# Create a Parent

View File

@ -2,8 +2,8 @@
6. Specifying ordering
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
results of ``get_list()`` and other similar functions.
should be a list or tuple of field names. This tells Django how to order
queryset results.
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.

View File

@ -77,6 +77,8 @@ MultiValueDictKeyError: "Key 'lastname' not found in <MultiValueDict: {'position
'not one'
>>> d.keys() == d.copy().keys()
True
>>> d2 = d.copy()
>>> d2['four'] = 'four'
>>> print repr(d)
{'one': 'not one', 'two': 'two', 'three': 'three'}
>>> d.pop('one', 'missing')
@ -99,6 +101,12 @@ Init from sequence of tuples
>>> print repr(d)
{1: 'one', 0: 'zero', 2: 'two'}
>>> d.clear()
>>> d
{}
>>> d.keyOrder
[]
### DotExpandedDict ############################################################
>>> d = DotExpandedDict({'person.1.firstname': ['Simon'], 'person.1.lastname': ['Willison'], 'person.2.firstname': ['Adrian'], 'person.2.lastname': ['Holovaty']})

View File

@ -56,4 +56,30 @@ datetime.date(1938, 6, 4)
datetime.time(5, 30)
>>> d3.consumed_at
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)
[]
"""}

View File

@ -0,0 +1,2 @@
# A models.py so that tests run.

View 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__')

View File

@ -0,0 +1,9 @@
[
{
"pk": "1",
"model": "fixtures_regress.absolute",
"fields": {
"name": "Load Absolute Path Test"
}
}
]

View File

@ -1,6 +1,7 @@
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
import os
class Animal(models.Model):
name = models.CharField(max_length=150)
@ -28,6 +29,16 @@ class Stuff(models.Model):
name = None
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':"""
>>> from django.core import management
@ -49,4 +60,15 @@ __test__ = {'API_TESTS':"""
>>> Stuff.objects.all()
[<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
"""}

View File

@ -1,3 +1,5 @@
import sys
tests = """
>>> from django.utils.translation.trans_real import parse_accept_lang_header
>>> p = parse_accept_lang_header
@ -83,7 +85,14 @@ source tree.
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-ar,de'}
>>> g(r)
'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
of the Spanish language, a safe assumption. When the user sets it
as the preferred language, the main 'es' translation should be selected
@ -91,7 +100,9 @@ instead.
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-us'}
>>> g(r)
'es'
"""
tests += """
This tests the following scenario: there isn't a main language (zh)
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

View File

@ -39,6 +39,7 @@ class Base(models.Model):
class Article(models.Model):
name = models.CharField(max_length=50)
text = models.TextField()
submitted_from = models.IPAddressField(blank=True, null=True)
def __str__(self):
return "Article %s" % self.name
@ -98,4 +99,11 @@ __test__ = {'API_TESTS': ur"""
>>> Article.objects.get(text__contains='quick brown fox')
<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>]
"""}