1
0
mirror of https://github.com/django/django.git synced 2025-07-06 18:59:13 +00:00

queryset-refactor: Merged from trunk up to [6635].

git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6638 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-11-03 02:16:27 +00:00
parent f189280eb3
commit 44df4e390f
13 changed files with 128 additions and 72 deletions

View File

@ -1,8 +1,8 @@
import time
from django.conf import settings from django.conf import settings
from django.utils.cache import patch_vary_headers from django.utils.cache import patch_vary_headers
from email.Utils import formatdate from django.utils.http import cookie_date
import datetime
import time
TEST_COOKIE_NAME = 'testcookie' TEST_COOKIE_NAME = 'testcookie'
TEST_COOKIE_VALUE = 'worked' TEST_COOKIE_VALUE = 'worked'
@ -10,8 +10,9 @@ TEST_COOKIE_VALUE = 'worked'
class SessionMiddleware(object): class SessionMiddleware(object):
def process_request(self, request): def process_request(self, request):
engine = __import__(settings.SESSION_ENGINE, {}, {}, ['']) engine = __import__(settings.SESSION_ENGINE, {}, {}, [''])
request.session = engine.SessionStore(request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)) session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
request.session = engine.SessionStore(session_key)
def process_response(self, request, response): def process_response(self, request, response):
# If request.session was modified, or if response.session was set, save # If request.session was modified, or if response.session was set, save
@ -30,13 +31,8 @@ class SessionMiddleware(object):
expires = None expires = None
else: else:
max_age = settings.SESSION_COOKIE_AGE max_age = settings.SESSION_COOKIE_AGE
rfcdate = formatdate(time.time() + settings.SESSION_COOKIE_AGE) expires_time = time.time() + settings.SESSION_COOKIE_AGE
expires = cookie_date(expires_time)
# Fixed length date must have '-' separation in the format
# DD-MMM-YYYY for compliance with Netscape cookie standard
expires = datetime.datetime.strftime(datetime.datetime.utcnow() + \
datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE), "%a, %d-%b-%Y %H:%M:%S GMT")
# Save the seesion data and refresh the client cookie. # Save the seesion data and refresh the client cookie.
request.session.save() request.session.save()
response.set_cookie(settings.SESSION_COOKIE_NAME, response.set_cookie(settings.SESSION_COOKIE_NAME,

View File

@ -9,14 +9,14 @@ been reviewed for security issues. Don't use it for production use.
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from types import ListType, StringType from types import ListType, StringType
from email.Utils import formatdate
import mimetypes import mimetypes
import os import os
import re import re
import sys import sys
import time
import urllib import urllib
from django.utils.http import http_date
__version__ = "0.1" __version__ = "0.1"
__all__ = ['WSGIServer','WSGIRequestHandler','demo_app'] __all__ = ['WSGIServer','WSGIRequestHandler','demo_app']
@ -376,7 +376,7 @@ class ServerHandler(object):
self._write('HTTP/%s %s\r\n' % (self.http_version,self.status)) self._write('HTTP/%s %s\r\n' % (self.http_version,self.status))
if 'Date' not in self.headers: if 'Date' not in self.headers:
self._write( self._write(
'Date: %s\r\n' % (formatdate()[:26] + "GMT") 'Date: %s\r\n' % http_date()
) )
if self.server_software and 'Server' not in self.headers: if self.server_software and 'Server' not in self.headers:
self._write('Server: %s\r\n' % self.server_software) self._write('Server: %s\r\n' % self.server_software)

View File

@ -1,4 +1,4 @@
from email.Utils import formatdate from django.utils.http import http_date
class ConditionalGetMiddleware(object): class ConditionalGetMiddleware(object):
""" """
@ -11,7 +11,7 @@ class ConditionalGetMiddleware(object):
Also sets the Date and Content-Length response-headers. Also sets the Date and Content-Length response-headers.
""" """
def process_response(self, request, response): def process_response(self, request, response):
response['Date'] = formatdate()[:26] + "GMT" response['Date'] = http_date()
if not response.has_header('Content-Length'): if not response.has_header('Content-Length'):
response['Content-Length'] = str(len(response.content)) response['Content-Length'] = str(len(response.content))
@ -23,7 +23,6 @@ class ConditionalGetMiddleware(object):
response['Content-Length'] = '0' response['Content-Length'] = '0'
if response.has_header('Last-Modified'): if response.has_header('Last-Modified'):
last_mod = response['Last-Modified']
if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE', None) if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE', None)
if if_modified_since == response['Last-Modified']: if if_modified_since == response['Last-Modified']:
response.status_code = 304 response.status_code = 304

View File

@ -6,7 +6,6 @@ and database field objects.
from django.utils.translation import ugettext from django.utils.translation import ugettext
from django.utils.encoding import smart_unicode from django.utils.encoding import smart_unicode
from util import ValidationError from util import ValidationError
from forms import BaseForm, SortedDictFromList from forms import BaseForm, SortedDictFromList
from fields import Field, ChoiceField from fields import Field, ChoiceField
@ -17,7 +16,8 @@ __all__ = (
'ModelChoiceField', 'ModelMultipleChoiceField' 'ModelChoiceField', 'ModelMultipleChoiceField'
) )
def save_instance(form, instance, fields=None, fail_message='saved', commit=True): def save_instance(form, instance, fields=None, fail_message='saved',
commit=True):
""" """
Saves bound Form ``form``'s cleaned_data into model instance ``instance``. Saves bound Form ``form``'s cleaned_data into model instance ``instance``.
@ -27,15 +27,17 @@ def save_instance(form, instance, fields=None, fail_message='saved', commit=True
from django.db import models from django.db import models
opts = instance.__class__._meta opts = instance.__class__._meta
if form.errors: if form.errors:
raise ValueError("The %s could not be %s because the data didn't validate." % (opts.object_name, fail_message)) raise ValueError("The %s could not be %s because the data didn't"
" validate." % (opts.object_name, fail_message))
cleaned_data = form.cleaned_data cleaned_data = form.cleaned_data
for f in opts.fields: for f in opts.fields:
if not f.editable or isinstance(f, models.AutoField) or not f.name in cleaned_data: if not f.editable or isinstance(f, models.AutoField) \
or not f.name in cleaned_data:
continue continue
if fields and f.name not in fields: if fields and f.name not in fields:
continue continue
f.save_form_data(instance, cleaned_data[f.name]) f.save_form_data(instance, cleaned_data[f.name])
# Wrap up the saving of m2m data as a function # Wrap up the saving of m2m data as a function.
def save_m2m(): def save_m2m():
opts = instance.__class__._meta opts = instance.__class__._meta
cleaned_data = form.cleaned_data cleaned_data = form.cleaned_data
@ -45,28 +47,29 @@ def save_instance(form, instance, fields=None, fail_message='saved', commit=True
if f.name in cleaned_data: if f.name in cleaned_data:
f.save_form_data(instance, cleaned_data[f.name]) f.save_form_data(instance, cleaned_data[f.name])
if commit: if commit:
# If we are committing, save the instance and the m2m data immediately # If we are committing, save the instance and the m2m data immediately.
instance.save() instance.save()
save_m2m() save_m2m()
else: else:
# We're not committing. Add a method to the form to allow deferred # We're not committing. Add a method to the form to allow deferred
# saving of m2m data # saving of m2m data.
form.save_m2m = save_m2m form.save_m2m = save_m2m
return instance return instance
def make_model_save(model, fields, fail_message): def make_model_save(model, fields, fail_message):
"Returns the save() method for a Form." """Returns the save() method for a Form."""
def save(self, commit=True): def save(self, commit=True):
return save_instance(self, model(), fields, fail_message, commit) return save_instance(self, model(), fields, fail_message, commit)
return save return save
def make_instance_save(instance, fields, fail_message): def make_instance_save(instance, fields, fail_message):
"Returns the save() method for a Form." """Returns the save() method for a Form."""
def save(self, commit=True): def save(self, commit=True):
return save_instance(self, instance, fields, fail_message, commit) return save_instance(self, instance, fields, fail_message, commit)
return save return save
def form_for_model(model, form=BaseForm, fields=None, formfield_callback=lambda f: f.formfield()): def form_for_model(model, form=BaseForm, fields=None,
formfield_callback=lambda f: f.formfield()):
""" """
Returns a Form class for the given Django model class. Returns a Form class for the given Django model class.
@ -87,10 +90,12 @@ def form_for_model(model, form=BaseForm, fields=None, formfield_callback=lambda
if formfield: if formfield:
field_list.append((f.name, formfield)) field_list.append((f.name, formfield))
base_fields = SortedDictFromList(field_list) base_fields = SortedDictFromList(field_list)
return type(opts.object_name + 'Form', (form,), return type(opts.object_name + 'Form', (form,),
{'base_fields': base_fields, '_model': model, 'save': make_model_save(model, fields, 'created')}) {'base_fields': base_fields, '_model': model,
'save': make_model_save(model, fields, 'created')})
def form_for_instance(instance, form=BaseForm, fields=None, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)): def form_for_instance(instance, form=BaseForm, fields=None,
formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
""" """
Returns a Form class for the given Django model instance. Returns a Form class for the given Django model instance.
@ -115,16 +120,22 @@ def form_for_instance(instance, form=BaseForm, fields=None, formfield_callback=l
field_list.append((f.name, formfield)) field_list.append((f.name, formfield))
base_fields = SortedDictFromList(field_list) base_fields = SortedDictFromList(field_list)
return type(opts.object_name + 'InstanceForm', (form,), return type(opts.object_name + 'InstanceForm', (form,),
{'base_fields': base_fields, '_model': model, 'save': make_instance_save(instance, fields, 'changed')}) {'base_fields': base_fields, '_model': model,
'save': make_instance_save(instance, fields, 'changed')})
def form_for_fields(field_list): def form_for_fields(field_list):
"Returns a Form class for the given list of Django database field instances." """
fields = SortedDictFromList([(f.name, f.formfield()) for f in field_list if f.editable]) Returns a Form class for the given list of Django database field instances.
"""
fields = SortedDictFromList([(f.name, f.formfield())
for f in field_list if f.editable])
return type('FormForFields', (BaseForm,), {'base_fields': fields}) return type('FormForFields', (BaseForm,), {'base_fields': fields})
class QuerySetIterator(object): class QuerySetIterator(object):
def __init__(self, queryset, empty_label, cache_choices): def __init__(self, queryset, empty_label, cache_choices):
self.queryset, self.empty_label, self.cache_choices = queryset, empty_label, cache_choices self.queryset = queryset
self.empty_label = empty_label
self.cache_choices = cache_choices
def __iter__(self): def __iter__(self):
if self.empty_label is not None: if self.empty_label is not None:
@ -136,11 +147,13 @@ class QuerySetIterator(object):
self.queryset._result_cache = None self.queryset._result_cache = None
class ModelChoiceField(ChoiceField): class ModelChoiceField(ChoiceField):
"A ChoiceField whose choices are a model QuerySet." """A ChoiceField whose choices are a model QuerySet."""
# This class is a subclass of ChoiceField for purity, but it doesn't # This class is a subclass of ChoiceField for purity, but it doesn't
# actually use any of ChoiceField's implementation. # actually use any of ChoiceField's implementation.
def __init__(self, queryset, empty_label=u"---------", cache_choices=False, def __init__(self, queryset, empty_label=u"---------", cache_choices=False,
required=True, widget=Select, label=None, initial=None, help_text=None): required=True, widget=Select, label=None, initial=None,
help_text=None):
self.queryset = queryset self.queryset = queryset
self.empty_label = empty_label self.empty_label = empty_label
self.cache_choices = cache_choices self.cache_choices = cache_choices
@ -160,7 +173,8 @@ class ModelChoiceField(ChoiceField):
# *each* time _get_choices() is called (and, thus, each time # *each* time _get_choices() is called (and, thus, each time
# self.choices is accessed) so that we can ensure the QuerySet has not # self.choices is accessed) so that we can ensure the QuerySet has not
# been consumed. # been consumed.
return QuerySetIterator(self.queryset, self.empty_label, self.cache_choices) return QuerySetIterator(self.queryset, self.empty_label,
self.cache_choices)
def _set_choices(self, value): def _set_choices(self, value):
# This method is copied from ChoiceField._set_choices(). It's necessary # This method is copied from ChoiceField._set_choices(). It's necessary
@ -177,16 +191,20 @@ class ModelChoiceField(ChoiceField):
try: try:
value = self.queryset.model._default_manager.get(pk=value) value = self.queryset.model._default_manager.get(pk=value)
except self.queryset.model.DoesNotExist: except self.queryset.model.DoesNotExist:
raise ValidationError(ugettext(u'Select a valid choice. That choice is not one of the available choices.')) raise ValidationError(ugettext(u'Select a valid choice. That'
u' choice is not one of the'
u' available choices.'))
return value return value
class ModelMultipleChoiceField(ModelChoiceField): class ModelMultipleChoiceField(ModelChoiceField):
"A MultipleChoiceField whose choices are a model QuerySet." """A MultipleChoiceField whose choices are a model QuerySet."""
hidden_widget = MultipleHiddenInput hidden_widget = MultipleHiddenInput
def __init__(self, queryset, cache_choices=False, required=True, def __init__(self, queryset, cache_choices=False, required=True,
widget=SelectMultiple, label=None, initial=None, help_text=None): widget=SelectMultiple, label=None, initial=None,
super(ModelMultipleChoiceField, self).__init__(queryset, None, cache_choices, help_text=None):
required, widget, label, initial, help_text) super(ModelMultipleChoiceField, self).__init__(queryset, None,
cache_choices, required, widget, label, initial, help_text)
def clean(self, value): def clean(self, value):
if self.required and not value: if self.required and not value:
@ -200,7 +218,9 @@ class ModelMultipleChoiceField(ModelChoiceField):
try: try:
obj = self.queryset.model._default_manager.get(pk=val) obj = self.queryset.model._default_manager.get(pk=val)
except self.queryset.model.DoesNotExist: except self.queryset.model.DoesNotExist:
raise ValidationError(ugettext(u'Select a valid choice. %s is not one of the available choices.') % val) raise ValidationError(ugettext(u'Select a valid choice. %s is'
u' not one of the available'
u' choices.') % val)
else: else:
final_values.append(obj) final_values.append(obj)
return final_values return final_values

View File

@ -13,17 +13,18 @@ into account when building its cache key. Requests with the same path but
different header content for headers named in "Vary" need to get different different header content for headers named in "Vary" need to get different
cache keys to prevent delivery of wrong content. cache keys to prevent delivery of wrong content.
A example: i18n middleware would need to distinguish caches by the An example: i18n middleware would need to distinguish caches by the
"Accept-language" header. "Accept-language" header.
""" """
import md5 import md5
import re import re
import time import time
from email.Utils import formatdate
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.utils.encoding import smart_str, iri_to_uri from django.utils.encoding import smart_str, iri_to_uri
from django.utils.http import http_date
cc_delim_re = re.compile(r'\s*,\s*') cc_delim_re = re.compile(r'\s*,\s*')
@ -40,7 +41,7 @@ def patch_cache_control(response, **kwargs):
str() to it. str() to it.
""" """
def dictitem(s): def dictitem(s):
t = s.split('=',1) t = s.split('=', 1)
if len(t) > 1: if len(t) > 1:
return (t[0].lower(), t[1]) return (t[0].lower(), t[1])
else: else:
@ -64,7 +65,7 @@ def patch_cache_control(response, **kwargs):
if 'max-age' in cc and 'max_age' in kwargs: if 'max-age' in cc and 'max_age' in kwargs:
kwargs['max_age'] = min(cc['max-age'], kwargs['max_age']) kwargs['max_age'] = min(cc['max-age'], kwargs['max_age'])
for (k,v) in kwargs.items(): for (k, v) in kwargs.items():
cc[k.replace('_', '-')] = v cc[k.replace('_', '-')] = v
cc = ', '.join([dictvalue(el) for el in cc.items()]) cc = ', '.join([dictvalue(el) for el in cc.items()])
response['Cache-Control'] = cc response['Cache-Control'] = cc
@ -88,15 +89,14 @@ def patch_response_headers(response, cache_timeout=None):
if not response.has_header('ETag'): if not response.has_header('ETag'):
response['ETag'] = md5.new(response.content).hexdigest() response['ETag'] = md5.new(response.content).hexdigest()
if not response.has_header('Last-Modified'): if not response.has_header('Last-Modified'):
response['Last-Modified'] = formatdate()[:26] + "GMT" response['Last-Modified'] = http_date()
if not response.has_header('Expires'): if not response.has_header('Expires'):
response['Expires'] = formatdate(time.time() + cache_timeout)[:26] + "GMT" response['Expires'] = http_date(time.time() + cache_timeout)
patch_cache_control(response, max_age=cache_timeout) patch_cache_control(response, max_age=cache_timeout)
def add_never_cache_headers(response): def add_never_cache_headers(response):
""" """
Add headers to a response to indicate that Adds headers to a response to indicate that a page should never be cached.
a page should never be cached.
""" """
patch_response_headers(response, cache_timeout=-1) patch_response_headers(response, cache_timeout=-1)
@ -119,13 +119,14 @@ def patch_vary_headers(response, newheaders):
response['Vary'] = ', '.join(vary) response['Vary'] = ', '.join(vary)
def _generate_cache_key(request, headerlist, key_prefix): def _generate_cache_key(request, headerlist, key_prefix):
"Returns a cache key from the headers given in the header list." """Returns a cache key from the headers given in the header list."""
ctx = md5.new() ctx = md5.new()
for header in headerlist: for header in headerlist:
value = request.META.get(header, None) value = request.META.get(header, None)
if value is not None: if value is not None:
ctx.update(value) ctx.update(value)
return 'views.decorators.cache.cache_page.%s.%s.%s' % (key_prefix, iri_to_uri(request.path), ctx.hexdigest()) return 'views.decorators.cache.cache_page.%s.%s.%s' % (
key_prefix, iri_to_uri(request.path), ctx.hexdigest())
def get_cache_key(request, key_prefix=None): def get_cache_key(request, key_prefix=None):
""" """
@ -139,7 +140,8 @@ def get_cache_key(request, key_prefix=None):
""" """
if key_prefix is None: if key_prefix is None:
key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, iri_to_uri(request.path)) cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
key_prefix, iri_to_uri(request.path))
headerlist = cache.get(cache_key, None) headerlist = cache.get(cache_key, None)
if headerlist is not None: if headerlist is not None:
return _generate_cache_key(request, headerlist, key_prefix) return _generate_cache_key(request, headerlist, key_prefix)
@ -163,9 +165,11 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None):
key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
if cache_timeout is None: if cache_timeout is None:
cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, iri_to_uri(request.path)) cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
key_prefix, iri_to_uri(request.path))
if response.has_header('Vary'): if response.has_header('Vary'):
headerlist = ['HTTP_'+header.upper().replace('-', '_') for header in vary_delim_re.split(response['Vary'])] headerlist = ['HTTP_'+header.upper().replace('-', '_')
for header in vary_delim_re.split(response['Vary'])]
cache.set(cache_key, headerlist, cache_timeout) cache.set(cache_key, headerlist, cache_timeout)
return _generate_cache_key(request, headerlist, key_prefix) return _generate_cache_key(request, headerlist, key_prefix)
else: else:

View File

@ -1,4 +1,6 @@
import urllib import urllib
from email.Utils import formatdate
from django.utils.encoding import smart_str, force_unicode from django.utils.encoding import smart_str, force_unicode
from django.utils.functional import allow_lazy from django.utils.functional import allow_lazy
@ -37,3 +39,29 @@ def urlencode(query, doseq=0):
for k, v in query], for k, v in query],
doseq) doseq)
def cookie_date(epoch_seconds=None):
"""
Formats the time to ensure compatibility with Netscape's cookie standard.
Accepts a floating point number expressed in seconds since the epoch, in
UTC - such as that outputted by time.time(). If set to None, defaults to
the current time.
Outputs a string in the format 'Wdy, DD-Mon-YYYY HH:MM:SS GMT'.
"""
rfcdate = formatdate(epoch_seconds)
return '%s-%s-%s GMT' % (rfcdate[:7], rfcdate[8:11], rfcdate[12:25])
def http_date(epoch_seconds=None):
"""
Formats the time to match the RFC1123 date format as specified by HTTP
RFC2616 section 3.3.1.
Accepts a floating point number expressed in seconds since the epoch, in
UTC - such as that outputted by time.time(). If set to None, defaults to
the current time.
Outputs a string in the format 'Wdy, DD Mon YYYY HH:MM:SS GMT'.
"""
rfcdate = formatdate(epoch_seconds)
return '%s GMT' % rfcdate[:25]

View File

@ -7,13 +7,14 @@ import mimetypes
import os import os
import posixpath import posixpath
import re import re
import rfc822
import stat import stat
import urllib import urllib
from email.Utils import parsedate_tz, mktime_tz
from django.template import loader from django.template import loader
from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified
from django.template import Template, Context, TemplateDoesNotExist from django.template import Template, Context, TemplateDoesNotExist
from django.utils.http import http_date
def serve(request, path, document_root=None, show_indexes=False): def serve(request, path, document_root=None, show_indexes=False):
""" """
@ -60,7 +61,7 @@ def serve(request, path, document_root=None, show_indexes=False):
mimetype = mimetypes.guess_type(fullpath)[0] mimetype = mimetypes.guess_type(fullpath)[0]
contents = open(fullpath, 'rb').read() contents = open(fullpath, 'rb').read()
response = HttpResponse(contents, mimetype=mimetype) response = HttpResponse(contents, mimetype=mimetype)
response["Last-Modified"] = rfc822.formatdate(statobj[stat.ST_MTIME]) response["Last-Modified"] = http_date(statobj[stat.ST_MTIME])
return response return response
DEFAULT_DIRECTORY_INDEX_TEMPLATE = """ DEFAULT_DIRECTORY_INDEX_TEMPLATE = """
@ -119,8 +120,7 @@ def was_modified_since(header=None, mtime=0, size=0):
raise ValueError raise ValueError
matches = re.match(r"^([^;]+)(; length=([0-9]+))?$", header, matches = re.match(r"^([^;]+)(; length=([0-9]+))?$", header,
re.IGNORECASE) re.IGNORECASE)
header_mtime = rfc822.mktime_tz(rfc822.parsedate_tz( header_mtime = mktime_tz(parsedate_tz(matches.group(1)))
matches.group(1)))
header_len = matches.group(3) header_len = matches.group(3)
if header_len and int(header_len) != size: if header_len and int(header_len) != size:
raise ValueError raise ValueError

View File

@ -291,13 +291,15 @@ minutes.
Template fragment caching Template fragment caching
========================= =========================
**New in development version**.
If you're after even more control, you can also cache template fragments using If you're after even more control, you can also cache template fragments using
the ``cache`` template tag. To give your template access to this tag, put ``{% the ``cache`` template tag. To give your template access to this tag, put
load cache %}`` near the top of your template. ``{% load cache %}`` near the top of your template.
The ``{% cache %}`` template tag caches the contents of the block for a given The ``{% cache %}`` template tag caches the contents of the block for a given
amount of time. It takes at least two arguments: the cache timeout, in amount of time. It takes at least two arguments: the cache timeout, in seconds,
seconds, and the name to give the cache fragment. For example:: and the name to give the cache fragment. For example::
{% load cache %} {% load cache %}
{% cache 500 sidebar %} {% cache 500 sidebar %}

View File

@ -275,7 +275,7 @@ The class has the following methods:
There are two ways to call ``attach()``: There are two ways to call ``attach()``:
* You can pass it a single argument that is an * You can pass it a single argument that is an
``email.MIMBase.MIMEBase`` instance. This will be inserted directly ``email.MIMEBase.MIMEBase`` instance. This will be inserted directly
into the resulting message. into the resulting message.
* Alternatively, you can pass ``attach()`` three arguments: * Alternatively, you can pass ``attach()`` three arguments:

View File

@ -45,7 +45,7 @@ How to use ``FormPreview``
2. Create a ``FormPreview`` subclass that overrides the ``done()`` method:: 2. Create a ``FormPreview`` subclass that overrides the ``done()`` method::
from django.contrib.formtools import FormPreview from django.contrib.formtools.preview import FormPreview
from myapp.models import SomeModel from myapp.models import SomeModel
class SomeModelFormPreview(FormPreview): class SomeModelFormPreview(FormPreview):

View File

@ -150,7 +150,7 @@ mess things up. Use the ``PythonInterpreter`` directive to give different
<Location "/otherthing"> <Location "/otherthing">
SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
PythonInterpreter mysite_other PythonInterpreter othersite
</Location> </Location>
</VirtualHost> </VirtualHost>

View File

@ -721,7 +721,6 @@ This means, instead of instantiating a ``Client`` in each test::
...you can just refer to ``self.client``, like so:: ...you can just refer to ``self.client``, like so::
from django.test import TestCase from django.test import TestCase
from django.test.client import Client
class SimpleTest(TestCase): class SimpleTest(TestCase):
def test_details(self): def test_details(self):

View File

@ -27,6 +27,14 @@ u'Paris+%26+Orl%C3%A9ans'
>>> urlquote_plus(u'Paris & Orl\xe9ans', safe="&") >>> urlquote_plus(u'Paris & Orl\xe9ans', safe="&")
u'Paris+&+Orl%C3%A9ans' u'Paris+&+Orl%C3%A9ans'
### cookie_date, http_date ###############################################
>>> from django.utils.http import cookie_date, http_date
>>> t = 1167616461.0
>>> cookie_date(t)
'Mon, 01-Jan-2007 01:54:21 GMT'
>>> http_date(t)
'Mon, 01 Jan 2007 01:54:21 GMT'
### iri_to_uri ########################################################### ### iri_to_uri ###########################################################
>>> from django.utils.encoding import iri_to_uri >>> from django.utils.encoding import iri_to_uri
>>> iri_to_uri(u'red%09ros\xe9#red') >>> iri_to_uri(u'red%09ros\xe9#red')