mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
[multi-db] Merge trunk to [3501]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@3502 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
e550c1eed4
commit
7062c656c3
16
AUTHORS
16
AUTHORS
@ -16,12 +16,23 @@ before Simon departed and currently oversees things with Adrian.
|
||||
|
||||
Wilson Miner <http://www.wilsonminer.com/>, who designed Django's admin
|
||||
interface, pretty error pages, official Web site (djangoproject.com) and has
|
||||
made many other contributions.
|
||||
made many other contributions. He makes us look good.
|
||||
|
||||
Malcolm Tredinnick <http://www.pointy-stick.com/blog/>, who has made
|
||||
significant contributions to all levels of the framework, from its database
|
||||
layer to template system and documentation.
|
||||
|
||||
Georg "Hugo" Bauer <http://hugo.muensterland.org/>, who added
|
||||
internationalization support, manages i18n contributions and has made a ton
|
||||
of excellent tweaks, feature additions and bug fixes.
|
||||
|
||||
Luke Plant <http://lukeplant.me.uk/>, who has contributed many excellent
|
||||
improvements, including database-level improvements, the CSRF middleware and
|
||||
unit tests.
|
||||
|
||||
Russell Keith-Magee <freakboy@iinet.net.au>, who has contributed many excellent
|
||||
improvements, including refactoring of the Django ORM code and unit tests.
|
||||
|
||||
Robert Wittams <http://robert.wittams.com/>, who majorly refactored the Django
|
||||
admin application to allow for easier reuse and has made a ton of excellent
|
||||
tweaks, feature additions and bug fixes.
|
||||
@ -70,7 +81,6 @@ answer newbie questions, and generally made Django that much better:
|
||||
Michael Josephson <http://www.sdjournal.com/>
|
||||
jpellerin@gmail.com
|
||||
junzhang.jn@gmail.com
|
||||
Russell Keith-Magee <freakboy@iinet.net.au>
|
||||
Garth Kidd <http://www.deadlybloodyserious.com/>
|
||||
kilian <kilian.cavalotti@lip6.fr>
|
||||
Sune Kirkeby <http://ibofobi.dk/>
|
||||
@ -98,6 +108,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Sam Newman <http://www.magpiebrain.com/>
|
||||
Neal Norwitz <nnorwitz@google.com>
|
||||
oggie rob <oz.robharvey@gmail.com>
|
||||
Jay Parlar <parlar@gmail.com>
|
||||
pgross@thoughtworks.com
|
||||
phaedo <http://phaedo.cx/>
|
||||
phil@produxion.net
|
||||
@ -118,7 +129,6 @@ answer newbie questions, and generally made Django that much better:
|
||||
Tom Tobin
|
||||
Tom Insam
|
||||
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
||||
Malcolm Tredinnick
|
||||
Amit Upadhyay
|
||||
Geert Vanderkelen
|
||||
Milton Waddams
|
||||
|
17
INSTALL
17
INSTALL
@ -1,7 +1,22 @@
|
||||
Thanks for downloading Django.
|
||||
|
||||
To install it, make sure you have Python 2.3 or greater installed. Then run this command:
|
||||
To install it, make sure you have Python 2.3 or greater installed. Then run
|
||||
this command from the command prompt:
|
||||
|
||||
python setup.py install
|
||||
|
||||
Note this requires a working Internet connection if you don't already have the
|
||||
Python utility "setuptools" installed.
|
||||
|
||||
AS AN ALTERNATIVE, you can just copy the entire "django" directory to Python's
|
||||
site-packages directory, which is located wherever your Python installation
|
||||
lives. Some places you might check are:
|
||||
|
||||
/usr/lib/python2.4/site-packages (Unix, Python 2.4)
|
||||
/usr/lib/python2.3/site-packages (Unix, Python 2.3)
|
||||
C:\\PYTHON\site-packages (Windows)
|
||||
|
||||
This second solution does not require a working Internet connection; it
|
||||
bypasses "setuptools" entirely.
|
||||
|
||||
For more detailed instructions, see docs/install.txt.
|
||||
|
@ -1 +1 @@
|
||||
VERSION = (0, 95, 'post-magic-removal')
|
||||
VERSION = (0, 96, 'pre')
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -13,6 +13,8 @@ def user_passes_test(test_func, login_url=LOGIN_URL):
|
||||
if test_func(request.user):
|
||||
return view_func(request, *args, **kwargs)
|
||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
|
||||
_checklogin.__doc__ = view_func.__doc__
|
||||
_checklogin.__dict__ = view_func.__dict__
|
||||
|
||||
return _checklogin
|
||||
return _dec
|
||||
|
@ -61,7 +61,7 @@ class PasswordResetForm(forms.Manipulator):
|
||||
except User.DoesNotExist:
|
||||
raise validators.ValidationError, "That e-mail address doesn't have an associated user acount. Are you sure you've registered?"
|
||||
|
||||
def save(self, domain_override=None):
|
||||
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
|
||||
"Calculates a new password randomly and sends it to the user"
|
||||
from django.core.mail import send_mail
|
||||
new_pass = User.objects.make_random_password()
|
||||
@ -73,7 +73,7 @@ class PasswordResetForm(forms.Manipulator):
|
||||
domain = current_site.domain
|
||||
else:
|
||||
site_name = domain = domain_override
|
||||
t = loader.get_template('registration/password_reset_email.html')
|
||||
t = loader.get_template(email_template_name)
|
||||
c = {
|
||||
'new_password': new_pass,
|
||||
'email': self.user_cache.email,
|
||||
|
@ -34,9 +34,8 @@ def login(request, template_name='registration/login.html'):
|
||||
def logout(request, next_page=None, template_name='registration/logged_out.html'):
|
||||
"Logs out the user and displays 'You are logged out' message."
|
||||
from django.contrib.auth import logout
|
||||
try:
|
||||
logout(request)
|
||||
except KeyError:
|
||||
if next_page is None:
|
||||
return render_to_response(template_name, {'title': _('Logged out')}, context_instance=RequestContext(request))
|
||||
else:
|
||||
# Redirect to this page until the session has been cleared.
|
||||
@ -50,7 +49,8 @@ def redirect_to_login(next, login_url=LOGIN_URL):
|
||||
"Redirects the user to the login page, passing the given 'next' page"
|
||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next))
|
||||
|
||||
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html'):
|
||||
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
|
||||
email_template_name='registration/password_reset_email.html'):
|
||||
new_data, errors = {}, {}
|
||||
form = PasswordResetForm()
|
||||
if request.POST:
|
||||
@ -58,9 +58,9 @@ def password_reset(request, is_admin_site=False, template_name='registration/pas
|
||||
errors = form.get_validation_errors(new_data)
|
||||
if not errors:
|
||||
if is_admin_site:
|
||||
form.save(request.META['HTTP_HOST'])
|
||||
form.save(domain_override=request.META['HTTP_HOST'])
|
||||
else:
|
||||
form.save()
|
||||
form.save(email_template_name=email_template_name)
|
||||
return HttpResponseRedirect('%sdone/' % request.path)
|
||||
return render_to_response(template_name, {'form': forms.FormWrapper(form, new_data, errors)},
|
||||
context_instance=RequestContext(request))
|
||||
|
@ -78,7 +78,7 @@ def get_version():
|
||||
from django import VERSION
|
||||
v = '.'.join([str(i) for i in VERSION[:-1]])
|
||||
if VERSION[-1]:
|
||||
v += ' (%s)' % VERSION[-1]
|
||||
v += '-' + VERSION[-1]
|
||||
return v
|
||||
|
||||
def get_sql_create(app):
|
||||
|
@ -41,11 +41,11 @@ class DateTimeAwareJSONEncoder(simplejson.JSONEncoder):
|
||||
TIME_FORMAT = "%H:%M:%S"
|
||||
|
||||
def default(self, o):
|
||||
if isinstance(o, datetime.date):
|
||||
if isinstance(o, datetime.datetime):
|
||||
return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
|
||||
elif isinstance(o, datetime.date):
|
||||
return o.strftime(self.DATE_FORMAT)
|
||||
elif isinstance(o, datetime.time):
|
||||
return o.strftime(self.TIME_FORMAT)
|
||||
elif isinstance(o, datetime.datetime):
|
||||
return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
|
||||
else:
|
||||
return super(self, DateTimeAwareJSONEncoder).default(o)
|
@ -201,3 +201,19 @@ class RegexURLResolver(object):
|
||||
sub_match = self.reverse(viewname, *args, **kwargs)
|
||||
result = reverse_helper(self.regex, *args, **kwargs)
|
||||
return result + sub_match
|
||||
|
||||
def resolve(path, urlconf=None):
|
||||
if urlconf is None:
|
||||
from django.conf import settings
|
||||
urlconf = settings.ROOT_URLCONF
|
||||
resolver = RegexURLResolver(r'^/', urlconf)
|
||||
return resolver.resolve(path)
|
||||
|
||||
def reverse(viewname, urlconf=None, args=None, kwargs=None):
|
||||
args = args or []
|
||||
kwargs = kwargs or {}
|
||||
if urlconf is None:
|
||||
from django.conf import settings
|
||||
urlconf = settings.ROOT_URLCONF
|
||||
resolver = RegexURLResolver(r'^/', urlconf)
|
||||
return '/' + resolver.reverse(viewname, *args, **kwargs)
|
||||
|
@ -16,6 +16,18 @@ from django.utils.text import capfirst
|
||||
# Admin stages.
|
||||
ADD, CHANGE, BOTH = 1, 2, 3
|
||||
|
||||
# Decorator. Takes a function that returns a tuple in this format:
|
||||
# (viewname, viewargs, viewkwargs)
|
||||
# Returns a function that calls urlresolvers.reverse() on that data, to return
|
||||
# the URL for those parameters.
|
||||
def permalink(func):
|
||||
from django.core.urlresolvers import reverse
|
||||
def inner(*args, **kwargs):
|
||||
bits = func(*args, **kwargs)
|
||||
viewname = bits[0]
|
||||
return reverse(bits[0], None, *bits[1:2])
|
||||
return inner
|
||||
|
||||
class LazyDate(object):
|
||||
"""
|
||||
Use in limit_choices_to to compare the field to dates calculated at run time
|
||||
|
@ -44,7 +44,7 @@ class ModelBase(type):
|
||||
new_class._meta.app_label = model_module.__name__.split('.')[-2]
|
||||
|
||||
# Bail out early if we have already created this class.
|
||||
m = get_model(new_class._meta.app_label, name)
|
||||
m = get_model(new_class._meta.app_label, name, False)
|
||||
if m is not None:
|
||||
return m
|
||||
|
||||
@ -68,7 +68,7 @@ class ModelBase(type):
|
||||
# the first class for this model to register with the framework. There
|
||||
# should only be one class for each model, so we must always return the
|
||||
# registered version.
|
||||
return get_model(new_class._meta.app_label, name)
|
||||
return get_model(new_class._meta.app_label, name, False)
|
||||
|
||||
class Model(object):
|
||||
__metaclass__ = ModelBase
|
||||
|
@ -247,9 +247,9 @@ class Field(object):
|
||||
params['is_required'] = not self.blank and not self.primary_key and not rel
|
||||
|
||||
# BooleanFields (CheckboxFields) are a special case. They don't take
|
||||
# is_required or validator_list.
|
||||
# is_required.
|
||||
if isinstance(self, BooleanField):
|
||||
del params['validator_list'], params['is_required']
|
||||
del params['is_required']
|
||||
|
||||
# If this field is in a related context, check whether any other fields
|
||||
# in the related object have core=True. If so, add a validator --
|
||||
|
@ -83,11 +83,15 @@ def get_models(app_mod=None, creation_order=False):
|
||||
model_list.extend(get_models(app_mod))
|
||||
return model_list
|
||||
|
||||
def get_model(app_label, model_name):
|
||||
def get_model(app_label, model_name, seed_cache = True):
|
||||
"""
|
||||
Returns the model matching the given app_label and case-insensitive model_name.
|
||||
Returns the model matching the given app_label and case-insensitive
|
||||
model_name.
|
||||
|
||||
Returns None if no model is found.
|
||||
"""
|
||||
if seed_cache:
|
||||
get_apps()
|
||||
try:
|
||||
model_dict = _app_models[app_label]
|
||||
except KeyError:
|
||||
|
@ -434,10 +434,12 @@ class HiddenField(FormField):
|
||||
(self.get_id(), self.field_name, escape(data))
|
||||
|
||||
class CheckboxField(FormField):
|
||||
def __init__(self, field_name, checked_by_default=False):
|
||||
def __init__(self, field_name, checked_by_default=False, validator_list=None):
|
||||
if validator_list is None: validator_list = []
|
||||
self.field_name = field_name
|
||||
self.checked_by_default = checked_by_default
|
||||
self.is_required, self.validator_list = False, [] # because the validator looks for these
|
||||
self.is_required = False # because the validator looks for these
|
||||
self.validator_list = validator_list[:]
|
||||
|
||||
def render(self, data):
|
||||
checked_html = ''
|
||||
|
@ -358,7 +358,7 @@ class DebugParser(Parser):
|
||||
super(DebugParser, self).extend_nodelist(nodelist, node, token)
|
||||
|
||||
def unclosed_block_tag(self, parse_until):
|
||||
(command, source) = self.command_stack.pop()
|
||||
command, source = self.command_stack.pop()
|
||||
msg = "Unclosed tag '%s'. Looking for one of: %s " % (command, ', '.join(parse_until))
|
||||
raise self.source_error( source, msg)
|
||||
|
||||
|
@ -50,6 +50,8 @@ class ExtendsNode(Node):
|
||||
if self.parent_name_expr:
|
||||
error_msg += " Got this from the %r variable." % self.parent_name_expr #TODO nice repr.
|
||||
raise TemplateSyntaxError, error_msg
|
||||
if hasattr(parent, 'render'):
|
||||
return parent
|
||||
try:
|
||||
source, origin = find_template_source(parent, self.template_dirs)
|
||||
except TemplateDoesNotExist:
|
||||
@ -125,7 +127,7 @@ def do_block(parser, token):
|
||||
if block_name in parser.__loaded_blocks:
|
||||
raise TemplateSyntaxError, "'%s' tag with name '%s' appears more than once" % (bits[0], block_name)
|
||||
parser.__loaded_blocks.append(block_name)
|
||||
except AttributeError: # parser._loaded_blocks isn't a list yet
|
||||
except AttributeError: # parser.__loaded_blocks isn't a list yet
|
||||
parser.__loaded_blocks = [block_name]
|
||||
nodelist = parser.parse(('endblock',))
|
||||
parser.delete_first_token()
|
||||
@ -137,8 +139,9 @@ def do_extends(parser, token):
|
||||
|
||||
This tag may be used in two ways: ``{% extends "base" %}`` (with quotes)
|
||||
uses the literal value "base" as the name of the parent template to extend,
|
||||
or ``{% extends variable %}`` uses the value of ``variable`` as the name
|
||||
of the parent template to extend.
|
||||
or ``{% extends variable %}`` uses the value of ``variable`` as either the
|
||||
name of the parent template to extend (if it evaluates to a string,) or as
|
||||
the parent tempate itelf (if it evaluates to a Template object).
|
||||
"""
|
||||
bits = token.contents.split()
|
||||
if len(bits) != 2:
|
||||
|
@ -35,6 +35,14 @@ try:
|
||||
except ImportError:
|
||||
import dummy_thread as thread
|
||||
|
||||
# This import does nothing, but it's necessary to avoid some race conditions
|
||||
# in the threading module. See http://code.djangoproject.com/ticket/2330 .
|
||||
try:
|
||||
import threading
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
RUN_RELOADER = True
|
||||
|
||||
def reloader_thread():
|
||||
|
@ -25,3 +25,6 @@ def to_locale(language):
|
||||
return language[:p].lower()+'_'+language[p+1:].upper()
|
||||
else:
|
||||
return language.lower()
|
||||
|
||||
def get_language_from_request(request):
|
||||
return settings.LANGUAGE_CODE
|
||||
|
@ -7,7 +7,7 @@ import datetime, time
|
||||
def archive_index(request, queryset, date_field, num_latest=15,
|
||||
template_name=None, template_loader=loader,
|
||||
extra_context=None, allow_empty=False, context_processors=None,
|
||||
mimetype=None):
|
||||
mimetype=None, allow_future=False):
|
||||
"""
|
||||
Generic top-level archive of date-based objects.
|
||||
|
||||
@ -20,6 +20,7 @@ def archive_index(request, queryset, date_field, num_latest=15,
|
||||
"""
|
||||
if extra_context is None: extra_context = {}
|
||||
model = queryset.model
|
||||
if not allow_future:
|
||||
queryset = queryset.filter(**{'%s__lte' % date_field: datetime.datetime.now()})
|
||||
date_list = queryset.dates(date_field, 'year')[::-1]
|
||||
if not date_list and not allow_empty:
|
||||
@ -47,7 +48,7 @@ def archive_index(request, queryset, date_field, num_latest=15,
|
||||
def archive_year(request, year, queryset, date_field, template_name=None,
|
||||
template_loader=loader, extra_context=None, allow_empty=False,
|
||||
context_processors=None, template_object_name='object', mimetype=None,
|
||||
make_object_list=False):
|
||||
make_object_list=False, allow_future=False):
|
||||
"""
|
||||
Generic yearly archive view.
|
||||
|
||||
@ -67,8 +68,8 @@ def archive_year(request, year, queryset, date_field, template_name=None,
|
||||
|
||||
lookup_kwargs = {'%s__year' % date_field: year}
|
||||
|
||||
# Only bother to check current date if the year isn't in the past.
|
||||
if int(year) >= now.year:
|
||||
# Only bother to check current date if the year isn't in the past and future objects aren't requested.
|
||||
if int(year) >= now.year and not allow_future:
|
||||
lookup_kwargs['%s__lte' % date_field] = now
|
||||
date_list = queryset.filter(**lookup_kwargs).dates(date_field, 'month')
|
||||
if not date_list and not allow_empty:
|
||||
@ -95,7 +96,7 @@ def archive_year(request, year, queryset, date_field, template_name=None,
|
||||
def archive_month(request, year, month, queryset, date_field,
|
||||
month_format='%b', template_name=None, template_loader=loader,
|
||||
extra_context=None, allow_empty=False, context_processors=None,
|
||||
template_object_name='object', mimetype=None):
|
||||
template_object_name='object', mimetype=None, allow_future=False):
|
||||
"""
|
||||
Generic monthly archive view.
|
||||
|
||||
@ -127,19 +128,28 @@ def archive_month(request, year, month, queryset, date_field,
|
||||
last_day = first_day.replace(month=first_day.month + 1)
|
||||
lookup_kwargs = {'%s__range' % date_field: (first_day, last_day)}
|
||||
|
||||
# Only bother to check current date if the month isn't in the past.
|
||||
if last_day >= now.date():
|
||||
# Only bother to check current date if the month isn't in the past and future objects are requested.
|
||||
if last_day >= now.date() and not allow_future:
|
||||
lookup_kwargs['%s__lte' % date_field] = now
|
||||
object_list = queryset.filter(**lookup_kwargs)
|
||||
if not object_list and not allow_empty:
|
||||
raise Http404
|
||||
|
||||
# Calculate the next month, if applicable.
|
||||
if allow_future:
|
||||
next_month = last_day + datetime.timedelta(days=1)
|
||||
elif last_day < datetime.date.today():
|
||||
next_month = last_day + datetime.timedelta(days=1)
|
||||
else:
|
||||
next_month = None
|
||||
|
||||
if not template_name:
|
||||
template_name = "%s/%s_archive_month.html" % (model._meta.app_label, model._meta.object_name.lower())
|
||||
t = template_loader.get_template(template_name)
|
||||
c = RequestContext(request, {
|
||||
'%s_list' % template_object_name: object_list,
|
||||
'month': date,
|
||||
'next_month': (last_day < datetime.date.today()) and (last_day + datetime.timedelta(days=1)) or None,
|
||||
'next_month': next_month,
|
||||
'previous_month': first_day - datetime.timedelta(days=1),
|
||||
}, context_processors)
|
||||
for key, value in extra_context.items():
|
||||
@ -152,7 +162,7 @@ def archive_month(request, year, month, queryset, date_field,
|
||||
def archive_week(request, year, week, queryset, date_field,
|
||||
template_name=None, template_loader=loader,
|
||||
extra_context=None, allow_empty=True, context_processors=None,
|
||||
template_object_name='object', mimetype=None):
|
||||
template_object_name='object', mimetype=None, allow_future=False):
|
||||
"""
|
||||
Generic weekly archive view.
|
||||
|
||||
@ -177,8 +187,8 @@ def archive_week(request, year, week, queryset, date_field,
|
||||
last_day = date + datetime.timedelta(days=7)
|
||||
lookup_kwargs = {'%s__range' % date_field: (first_day, last_day)}
|
||||
|
||||
# Only bother to check current date if the week isn't in the past.
|
||||
if last_day >= now.date():
|
||||
# Only bother to check current date if the week isn't in the past and future objects aren't requested.
|
||||
if last_day >= now.date() and not allow_future:
|
||||
lookup_kwargs['%s__lte' % date_field] = now
|
||||
object_list = queryset.filter(**lookup_kwargs)
|
||||
if not object_list and not allow_empty:
|
||||
@ -201,7 +211,7 @@ def archive_day(request, year, month, day, queryset, date_field,
|
||||
month_format='%b', day_format='%d', template_name=None,
|
||||
template_loader=loader, extra_context=None, allow_empty=False,
|
||||
context_processors=None, template_object_name='object',
|
||||
mimetype=None):
|
||||
mimetype=None, allow_future=False):
|
||||
"""
|
||||
Generic daily archive view.
|
||||
|
||||
@ -229,12 +239,21 @@ def archive_day(request, year, month, day, queryset, date_field,
|
||||
'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
|
||||
}
|
||||
|
||||
# Only bother to check current date if the date isn't in the past.
|
||||
if date >= now.date():
|
||||
# Only bother to check current date if the date isn't in the past and future objects aren't requested.
|
||||
if date >= now.date() and not allow_future:
|
||||
lookup_kwargs['%s__lte' % date_field] = now
|
||||
object_list = queryset.filter(**lookup_kwargs)
|
||||
if not allow_empty and not object_list:
|
||||
raise Http404
|
||||
|
||||
# Calculate the next day, if applicable.
|
||||
if allow_future:
|
||||
next_day = date + datetime.timedelta(days=1)
|
||||
elif date < datetime.date.today():
|
||||
next_day = date + datetime.timedelta(days=1)
|
||||
else:
|
||||
next_day = None
|
||||
|
||||
if not template_name:
|
||||
template_name = "%s/%s_archive_day.html" % (model._meta.app_label, model._meta.object_name.lower())
|
||||
t = template_loader.get_template(template_name)
|
||||
@ -242,7 +261,7 @@ def archive_day(request, year, month, day, queryset, date_field,
|
||||
'%s_list' % template_object_name: object_list,
|
||||
'day': date,
|
||||
'previous_day': date - datetime.timedelta(days=1),
|
||||
'next_day': (date < datetime.date.today()) and (date + datetime.timedelta(days=1)) or None,
|
||||
'next_day': next_day,
|
||||
}, context_processors)
|
||||
for key, value in extra_context.items():
|
||||
if callable(value):
|
||||
@ -267,7 +286,7 @@ def object_detail(request, year, month, day, queryset, date_field,
|
||||
month_format='%b', day_format='%d', object_id=None, slug=None,
|
||||
slug_field=None, template_name=None, template_name_field=None,
|
||||
template_loader=loader, extra_context=None, context_processors=None,
|
||||
template_object_name='object', mimetype=None):
|
||||
template_object_name='object', mimetype=None, allow_future=False):
|
||||
"""
|
||||
Generic detail view from year/month/day/slug or year/month/day/id structure.
|
||||
|
||||
@ -289,8 +308,8 @@ def object_detail(request, year, month, day, queryset, date_field,
|
||||
'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
|
||||
}
|
||||
|
||||
# Only bother to check current date if the date isn't in the past.
|
||||
if date >= now.date():
|
||||
# Only bother to check current date if the date isn't in the past and future objects aren't requested.
|
||||
if date >= now.date() and not allow_future:
|
||||
lookup_kwargs['%s__lte' % date_field] = now
|
||||
if object_id:
|
||||
lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
|
||||
|
123
docs/api_stability.txt
Normal file
123
docs/api_stability.txt
Normal file
@ -0,0 +1,123 @@
|
||||
=============
|
||||
API stability
|
||||
=============
|
||||
|
||||
Although Django has not reached a 1.0 release, the bulk of Django's public APIs are
|
||||
stable as of the 0.95 release. This document explains which APIs will and will not
|
||||
change before the 1.0 release.
|
||||
|
||||
What "stable" means
|
||||
===================
|
||||
|
||||
In this context, stable means:
|
||||
|
||||
- All the public APIs -- everything documented in the linked documents, and
|
||||
all methods that don't begin with an underscore -- will not be moved or
|
||||
renamed without providing backwards-compatible aliases.
|
||||
|
||||
- If new features are added to these APIs -- which is quite possible --
|
||||
they will not break or change the meaning of existing methods. In other
|
||||
words, "stable" does not (necessarily) mean "complete."
|
||||
|
||||
- If, for some reason, an API declared stable must be removed or replaced, it
|
||||
will be declared deprecated but will remain in the API until at least
|
||||
version 1.1. Warnings will be issued when the deprecated method is
|
||||
called.
|
||||
|
||||
- We'll only break backwards compatibility of these APIs if a bug or
|
||||
security hole makes it completely unavoidable.
|
||||
|
||||
Stable APIs
|
||||
===========
|
||||
|
||||
These APIs are stable:
|
||||
|
||||
- `Caching`_.
|
||||
|
||||
- `Custom template tags and libraries`_ (with the possible exception for a
|
||||
small change in the way templates are registered and loaded).
|
||||
|
||||
- `Database lookup`_ (with the exception of validation; see below).
|
||||
|
||||
- `django-admin utility`_.
|
||||
|
||||
- `FastCGI integration`_.
|
||||
|
||||
- `Flatpages`_.
|
||||
|
||||
- `Generic views`_.
|
||||
|
||||
- `Internationalization`_.
|
||||
|
||||
- `Legacy database integration`_.
|
||||
|
||||
- `Model definition`_ (with the exception of generic relations; see below).
|
||||
|
||||
- `mod_python integration`_.
|
||||
|
||||
- `Redirects`_.
|
||||
|
||||
- `Request/response objects`_.
|
||||
|
||||
- `Sending email`_.
|
||||
|
||||
- `Sessions`_.
|
||||
|
||||
- `Settings`_.
|
||||
|
||||
- `Syndication`_.
|
||||
|
||||
- `Template language`_ (with the exception of some possible disambiguation
|
||||
of how tag arguments are passed to tags and filters).
|
||||
|
||||
- `Transactions`_.
|
||||
|
||||
- `URL dispatch`_.
|
||||
|
||||
You'll notice that this list comprises the bulk of Django's APIs. That's right
|
||||
-- most of the changes planned between now and Django 1.0 are either under the
|
||||
hood, feature additions, or changes to a few select bits. A good estimate is
|
||||
that 90% of Django can be considered forwards-compatible at this point.
|
||||
|
||||
That said, these APIs should *not* be considered stable, and are likely to
|
||||
change:
|
||||
|
||||
- `Forms and validation`_ will most likely be compeltely rewritten to
|
||||
deemphasize Manipulators in favor of validation-aware models.
|
||||
|
||||
- `Serialization`_ is under heavy development; changes are likely.
|
||||
|
||||
- The `authentication`_ framework is changing to be far more flexible, and
|
||||
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 dependacies on optional
|
||||
components.
|
||||
|
||||
- The comments framework, which is yet undocumented, will likely get a complete
|
||||
rewrite before Django 1.0. Even if the change isn't quite that drastic,
|
||||
there will at least be moderate changes.
|
||||
|
||||
.. _caching: http://www.djangoproject.com/documentation/cache/
|
||||
.. _custom template tags and libraries: http://www.djangoproject.com/documentation/templates_python/
|
||||
.. _database lookup: http://www.djangoproject.com/documentation/db_api/
|
||||
.. _django-admin utility: http://www.djangoproject.com/documentation/django_admin/
|
||||
.. _fastcgi integration: http://www.djangoproject.com/documentation/fastcgi/
|
||||
.. _flatpages: http://www.djangoproject.com/documentation/flatpages/
|
||||
.. _generic views: http://www.djangoproject.com/documentation/generic_views/
|
||||
.. _internationalization: http://www.djangoproject.com/documentation/i18n/
|
||||
.. _legacy database integration: http://www.djangoproject.com/documentation/legacy_databases/
|
||||
.. _model definition: http://www.djangoproject.com/documentation/model_api/
|
||||
.. _mod_python integration: http://www.djangoproject.com/documentation/modpython/
|
||||
.. _redirects: http://www.djangoproject.com/documentation/redirects/
|
||||
.. _request/response objects: http://www.djangoproject.com/documentation/request_response/
|
||||
.. _sending email: http://www.djangoproject.com/documentation/email/
|
||||
.. _sessions: http://www.djangoproject.com/documentation/sessions/
|
||||
.. _settings: http://www.djangoproject.com/documentation/settings/
|
||||
.. _syndication: http://www.djangoproject.com/documentation/syndication/
|
||||
.. _template language: http://www.djangoproject.com/documentation/templates/
|
||||
.. _transactions: http://www.djangoproject.com/documentation/transactions/
|
||||
.. _url dispatch: http://www.djangoproject.com/documentation/url_dispatch/
|
||||
.. _forms and validation: http://www.djangoproject.com/documentation/forms/
|
||||
.. _serialization: http://www.djangoproject.com/documentation/serialization/
|
||||
.. _authentication: http://www.djangoproject.com/documentation/authentication/
|
@ -168,6 +168,10 @@ Please follow these coding standards when writing code for inclusion in Django:
|
||||
|
||||
{{foo}}
|
||||
|
||||
* Please don't put your name in the code. While we appreciate all
|
||||
contributions to Django, our policy is not to publish individual
|
||||
developer names in code -- for instance, at the top of Python modules.
|
||||
|
||||
Committing code
|
||||
===============
|
||||
|
||||
@ -212,6 +216,10 @@ repository:
|
||||
first, then the "Fixed #abc." For example:
|
||||
"magic-removal: Fixed #123 -- Added whizbang feature."
|
||||
|
||||
For the curious: We're using a `Trac post-commit hook`_ for this.
|
||||
|
||||
.. _Trac post-commit hook: http://trac.edgewall.org/browser/trunk/contrib/trac-post-commit-hook
|
||||
|
||||
* If your commit references a ticket in the Django `ticket tracker`_ but
|
||||
does *not* close the ticket, include the phrase "Refs #abc", where "abc"
|
||||
is the number of the ticket your commit references. We've rigged
|
||||
|
@ -274,8 +274,8 @@ Loose coupling
|
||||
A view shouldn't care about which template system the developer uses -- or even
|
||||
whether a template system is used at all.
|
||||
|
||||
Designate between GET and POST
|
||||
------------------------------
|
||||
Differentiate between GET and POST
|
||||
----------------------------------
|
||||
|
||||
GET and POST are distinct; developers should explicitly use one or the other.
|
||||
The framework should make it easy to distinguish between GET and POST data.
|
||||
|
43
docs/faq.txt
43
docs/faq.txt
@ -156,7 +156,7 @@ logical to us.
|
||||
-----------------------------------------------------
|
||||
|
||||
We're well aware that there are other awesome Web frameworks out there, and
|
||||
we're not adverse to borrowing ideas where appropriate. However, Django was
|
||||
we're not averse to borrowing ideas where appropriate. However, Django was
|
||||
developed precisely because we were unhappy with the status quo, so please be
|
||||
aware that "because <Framework X>" does it is not going to be sufficient reason
|
||||
to add a given feature to Django.
|
||||
@ -251,6 +251,16 @@ information than the docs that come with the latest Django release.
|
||||
|
||||
.. _stored in revision control: http://code.djangoproject.com/browser/django/trunk/docs
|
||||
|
||||
Where can I find Django developers for hire?
|
||||
--------------------------------------------
|
||||
|
||||
Consult our `developers for hire page`_ for a list of Django developers who
|
||||
would be happy to help you.
|
||||
|
||||
You might also be interested in posting a job to http://www.gypsyjobs.com/ .
|
||||
|
||||
.. _developers for hire page: http://code.djangoproject.com/wiki/DevelopersForHire
|
||||
|
||||
Installation questions
|
||||
======================
|
||||
|
||||
@ -546,10 +556,15 @@ Set the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting to ``True``. See the
|
||||
How do I automatically set a field's value to the user who last edited the object in the admin?
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
At this point, you can't do this. But it's an oft-requested feature, so we're
|
||||
discussing how it can be implemented. The problem is we don't want to couple
|
||||
the model layer with the admin layer with the request layer (to get the current
|
||||
user). It's a tricky problem.
|
||||
At this point, Django doesn't have an official way to do this. But it's an oft-requested
|
||||
feature, so we're discussing how it can be implemented. The problem is we don't want to couple
|
||||
the model layer with the admin layer with the request layer (to get the current user). It's a
|
||||
tricky problem.
|
||||
|
||||
One person hacked up a `solution that doesn't require patching Django`_, but note that it's an
|
||||
unofficial solution, and there's no guarantee it won't break at some point.
|
||||
|
||||
.. _solution that doesn't require patching Django: http://lukeplant.me.uk/blog.php?id=1107301634
|
||||
|
||||
How do I limit admin access so that objects can only be edited by the users who created them?
|
||||
---------------------------------------------------------------------------------------------
|
||||
@ -614,3 +629,21 @@ To create a user, you'll have to use the Python API. See `creating users`_ for
|
||||
full info.
|
||||
|
||||
.. _creating users: http://www.djangoproject.com/documentation/authentication/#creating-users
|
||||
|
||||
Contributing code
|
||||
=================
|
||||
|
||||
I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch?
|
||||
--------------------------------------------------------------------------------------------
|
||||
|
||||
Don't worry: We're not ignoring you!
|
||||
|
||||
It's important to understand there is a difference between "a ticket is being
|
||||
ignored" and "a ticket has not been attended to yet." Django's ticket system
|
||||
contains hundreds of open tickets, of various degrees of impact on end-user
|
||||
functionality, and Django's developers have to review and prioritize.
|
||||
|
||||
Besides, if your feature request stands no chance of inclusion in Django, we
|
||||
won't ignore it -- we'll just close the ticket. So if your ticket is still
|
||||
open, it doesn't mean we're ignoring you; it just means we haven't had time to
|
||||
look at it yet.
|
||||
|
@ -405,6 +405,43 @@ Here's a simple function that might drive the above form::
|
||||
form = forms.FormWrapper(manipulator, new_data, errors)
|
||||
return render_to_response('contact_form.html', {'form': form})
|
||||
|
||||
``FileField`` and ``ImageField`` special cases
|
||||
==============================================
|
||||
|
||||
Dealing with ``FileField`` and ``ImageField`` objects is a little more
|
||||
complicated.
|
||||
|
||||
First, you'll need to make sure that your ``<form>`` element correctly defines
|
||||
the ``enctype`` as ``"multipart/form-data"``, in order to upload files::
|
||||
|
||||
<form enctype="multipart/form-data" method="post" action="/foo/">
|
||||
|
||||
Next, you'll need to treat the field in the template slightly differently. A
|
||||
``FileField`` or ``ImageField`` is represented by *two* HTML form elements.
|
||||
|
||||
For example, given this field in a model::
|
||||
|
||||
photo = model.ImageField('/path/to/upload/location')
|
||||
|
||||
You'd need to display two formfields in the template::
|
||||
|
||||
<p><label for="id_photo">Photo:</label> {{ form.photo }}{{ form.photo_file }}</p>
|
||||
|
||||
The first bit (``{{ form.photo }}``) displays the currently-selected file,
|
||||
while the second (``{{ form.photo_file }}``) actually contains the file upload
|
||||
form field. Thus, at the validation layer you need to check the ``photo_file``
|
||||
key.
|
||||
|
||||
Finally, in your view, make sure to access ``request.FILES``, rather than
|
||||
``request.POST``, for the uploaded files. This is necessary because
|
||||
``request.POST`` does not contain file-upload data.
|
||||
|
||||
For example, following the ``new_data`` convention, you might do something like
|
||||
this::
|
||||
|
||||
new_data = request.POST.copy()
|
||||
new_data.update(request.FILES)
|
||||
|
||||
Validators
|
||||
==========
|
||||
|
||||
|
@ -148,7 +148,8 @@ are views for displaying drilldown pages for date-based data.
|
||||
**Description:**
|
||||
|
||||
A top-level index page showing the "latest" objects, by date. Objects with
|
||||
a date in the *future* are not included.
|
||||
a date in the *future* are not included unless you set ``allow_future`` to
|
||||
``True``.
|
||||
|
||||
**Required arguments:**
|
||||
|
||||
@ -185,6 +186,11 @@ a date in the *future* are not included.
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
* ``allow_future``: A boolean specifying whether to include "future"
|
||||
objects on this page, where "future" means objects in which the field
|
||||
specified in ``date_field`` is greater than the current date/time. By
|
||||
default, this is ``False``.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -217,7 +223,8 @@ In addition to ``extra_context``, the template's context will be:
|
||||
**Description:**
|
||||
|
||||
A yearly archive page showing all available months in a given year. Objects
|
||||
with a date in the *future* are not displayed.
|
||||
with a date in the *future* are not displayed unless you set ``allow_future``
|
||||
to ``True``.
|
||||
|
||||
**Required arguments:**
|
||||
|
||||
@ -265,6 +272,11 @@ with a date in the *future* are not displayed.
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
* ``allow_future``: A boolean specifying whether to include "future"
|
||||
objects on this page, where "future" means objects in which the field
|
||||
specified in ``date_field`` is greater than the current date/time. By
|
||||
default, this is ``False``.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -296,7 +308,8 @@ In addition to ``extra_context``, the template's context will be:
|
||||
**Description:**
|
||||
|
||||
A monthly archive page showing all objects in a given month. Objects with a
|
||||
date in the *future* are not displayed.
|
||||
date in the *future* are not displayed unless you set ``allow_future`` to
|
||||
``True``.
|
||||
|
||||
**Required arguments:**
|
||||
|
||||
@ -346,6 +359,11 @@ date in the *future* are not displayed.
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
* ``allow_future``: A boolean specifying whether to include "future"
|
||||
objects on this page, where "future" means objects in which the field
|
||||
specified in ``date_field`` is greater than the current date/time. By
|
||||
default, this is ``False``.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -378,7 +396,7 @@ In addition to ``extra_context``, the template's context will be:
|
||||
**Description:**
|
||||
|
||||
A weekly archive page showing all objects in a given week. Objects with a date
|
||||
in the *future* are not displayed.
|
||||
in the *future* are not displayed unless you set ``allow_future`` to ``True``.
|
||||
|
||||
**Required arguments:**
|
||||
|
||||
@ -422,6 +440,11 @@ in the *future* are not displayed.
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
* ``allow_future``: A boolean specifying whether to include "future"
|
||||
objects on this page, where "future" means objects in which the field
|
||||
specified in ``date_field`` is greater than the current date/time. By
|
||||
default, this is ``False``.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -445,7 +468,8 @@ In addition to ``extra_context``, the template's context will be:
|
||||
**Description:**
|
||||
|
||||
A day archive page showing all objects in a given day. Days in the future throw
|
||||
a 404 error, regardless of whether any objects exist for future days.
|
||||
a 404 error, regardless of whether any objects exist for future days, unless
|
||||
you set ``allow_future`` to ``True``.
|
||||
|
||||
**Required arguments:**
|
||||
|
||||
@ -501,6 +525,11 @@ a 404 error, regardless of whether any objects exist for future days.
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
* ``allow_future``: A boolean specifying whether to include "future"
|
||||
objects on this page, where "future" means objects in which the field
|
||||
specified in ``date_field`` is greater than the current date/time. By
|
||||
default, this is ``False``.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -537,7 +566,9 @@ and today's date is used instead.
|
||||
|
||||
**Description:**
|
||||
|
||||
A page representing an individual object.
|
||||
A page representing an individual object. If the object has a date value in the
|
||||
future, the view will throw a 404 error by default, unless you set
|
||||
``allow_future`` to ``True``.
|
||||
|
||||
**Required arguments:**
|
||||
|
||||
@ -604,6 +635,11 @@ A page representing an individual object.
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
* ``allow_future``: A boolean specifying whether to include "future"
|
||||
objects on this page, where "future" means objects in which the field
|
||||
specified in ``date_field`` is greater than the current date/time. By
|
||||
default, this is ``False``.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
|
@ -235,7 +235,7 @@ To pluralize, specify both the singular and plural forms with the
|
||||
``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and
|
||||
``{% endblocktrans %}``. Example::
|
||||
|
||||
{% blocktrans count list|counted as counter %}
|
||||
{% blocktrans count list|count as counter %}
|
||||
There is only one {{ name }} object.
|
||||
{% plural %}
|
||||
There are {{ counter }} {{ name }} objects.
|
||||
|
@ -77,9 +77,9 @@ It's easy either way.
|
||||
Installing the official version
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1. Download Django-0.91.tar.gz from our `download page`_.
|
||||
2. ``tar xzvf Django-0.91.tar.gz``
|
||||
3. ``cd Django-0.91``
|
||||
1. Download Django-0.95.tar.gz from our `download page`_.
|
||||
2. ``tar xzvf Django-0.95.tar.gz``
|
||||
3. ``cd Django-0.95``
|
||||
4. ``sudo python setup.py install``
|
||||
|
||||
Note that the last command will automatically download and install setuptools_
|
||||
@ -89,14 +89,6 @@ connection.
|
||||
This will install Django in your Python installation's ``site-packages``
|
||||
directory.
|
||||
|
||||
.. note::
|
||||
|
||||
Due to recent backwards-incompatible changes, it is strongly recommended
|
||||
that you use the development version (below) for any new applications or
|
||||
if you are just starting to work with Django. The 0.91 release is a
|
||||
dead-end branch that is primarily of use for supporting legacy Django
|
||||
applications.
|
||||
|
||||
.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
|
||||
|
||||
Installing the development version
|
||||
|
126
docs/release_notes_0.95.txt
Normal file
126
docs/release_notes_0.95.txt
Normal file
@ -0,0 +1,126 @@
|
||||
=================================
|
||||
Django version 0.95 release notes
|
||||
=================================
|
||||
|
||||
|
||||
Welcome to the Django 0.95 release.
|
||||
|
||||
This represents a significant advance in Django development since the 0.91
|
||||
release in January 2006. The details of every change in this release would be
|
||||
too extensive to list in full, but a summary is presented below.
|
||||
|
||||
Suitability and API stability
|
||||
=============================
|
||||
|
||||
This release is intended to provide a stable reference point for developers
|
||||
wanting to work on production-level applications that use Django.
|
||||
|
||||
However, it's not the 1.0 release, and we'll be introducing further changes
|
||||
before 1.0. For a clear look at which areas of the framework will change (and
|
||||
which ones will *not* change) before 1.0, see the api-stability.txt file, which
|
||||
lives in the docs/ directory of the distribution.
|
||||
|
||||
You may have a need to use some of the features that are marked as
|
||||
"subject to API change" in that document, but that's OK with us as long as it's
|
||||
OK with you, and as long as you understand APIs may change in the future.
|
||||
|
||||
Fortunately, most of Django's core APIs won't be changing before version 1.0.
|
||||
There likely won't be as big of a change between 0.95 and 1.0 versions as there
|
||||
was between 0.91 and 0.95.
|
||||
|
||||
Changes and new features
|
||||
========================
|
||||
|
||||
The major changes in this release (for developers currently using the 0.91
|
||||
release) are a result of merging the 'magic-removal' branch of development.
|
||||
This branch removed a number of constraints in the way Django code had to be
|
||||
written that were a consequence of decisions made in the early days of Django,
|
||||
prior to its open-source release. It's now possible to write more natural,
|
||||
Pythonic code that works as expected, and there's less "black magic" happening
|
||||
behind the scenes.
|
||||
|
||||
Aside from that, another main theme of this release is a dramatic increase in
|
||||
usability. We've made countless improvements in error messages, documentation,
|
||||
etc., to improve developers' quality of life.
|
||||
|
||||
The new features and changes introduced in 0.95 include:
|
||||
|
||||
* Django now uses a more consistent and natural filtering interface for
|
||||
retrieving objects from the database.
|
||||
|
||||
* User-defined models, functions and constants now appear in the module
|
||||
namespace they were defined in. (Previously everything was magically
|
||||
transferred to the django.models.* namespace.)
|
||||
|
||||
* Some optional applications, such as the FlatPage, Sites and Redirects
|
||||
apps, have been decoupled and moved into django.contrib. If you don't
|
||||
want to use these applications, you no longer have to install their
|
||||
database tables.
|
||||
|
||||
* Django now has support for managing database transactions.
|
||||
|
||||
* We've added the ability to write custom authentication and authorization
|
||||
backends for authenticating users against alternate systems, such as
|
||||
LDAP.
|
||||
|
||||
* We've made it easier to add custom table-level functions to models,
|
||||
through a new "Manager" API.
|
||||
|
||||
* It's now possible to use Django without a database. This simply means
|
||||
that the framework no longer requires you to have a working database set
|
||||
up just to serve dynamic pages. In other words, you can just use
|
||||
URLconfs/views on their own. Previously, the framework required that a
|
||||
database be configured, regardless of whether you actually used it.
|
||||
|
||||
* It's now more explicit and natural to override save() and delete()
|
||||
methods on models, rather than needing to hook into the pre_save() and
|
||||
post_save() method hooks.
|
||||
|
||||
* Individual pieces of the framework now can be configured without
|
||||
requiring the setting of an environment variable. This permits use of,
|
||||
for example, the Django templating system inside other applications.
|
||||
|
||||
* More and more parts of the framework have been internationalized, as
|
||||
we've expanded internationalization (i18n) support. The Django
|
||||
codebase, including code and templates, has now been translated, at least
|
||||
in part, into 31 languages. From Arabic to Chinese to Hungarian to Welsh,
|
||||
it is now possible to use Django's admin site in your native language.
|
||||
|
||||
The number of changes required to port from 0.91-compatible code to the 0.95
|
||||
code base are significant in some cases. However, they are, for the most part,
|
||||
reasonably routine and only need to be done once. A list of the necessary
|
||||
changes is described in the `Removing The Magic`_ wiki page. There is also an
|
||||
easy checklist_ for reference when undertaking the porting operation.
|
||||
|
||||
.. _Removing The Magic: http://code.djangoproject.com/wiki/RemovingTheMagic
|
||||
.. _checklist: http://code.djangoproject.com/wiki/MagicRemovalCheatSheet1
|
||||
|
||||
Problem reports and getting help
|
||||
================================
|
||||
|
||||
Need help resolving a problem with Django? The documentation in the
|
||||
distribution is also available online_ at the `Django website`_. The FAQ_
|
||||
document is especially recommended, as it contains a number of issues that
|
||||
come up time and again.
|
||||
|
||||
For more personalized help, the `django-users`_ mailing list is a very active
|
||||
list, with more than 2,000 subscribers who can help you solve any sort of
|
||||
Django problem. We recommend you search the archives first, though, because
|
||||
many common questions appear with some regularity, and any particular problem
|
||||
may already have been answered.
|
||||
|
||||
Finally, for those who prefer the more immediate feedback offered by IRC,
|
||||
there's a #django channel or irc.freenode.net that is regularly populated by
|
||||
Django users and developers from around the world. Friendly people are usually
|
||||
available at any hour of the day -- to help, or just to chat.
|
||||
|
||||
.. _online: http://www.djangoproject.com/documentation/
|
||||
.. _Django website: http://www.djangoproject.com/
|
||||
.. _FAQ: http://www.djangoproject.com/documentation/faq/
|
||||
.. _django-users: http://groups.google.com/group/django-users
|
||||
|
||||
Thanks for using Django!
|
||||
|
||||
The Django Team
|
||||
July 2006
|
||||
|
@ -427,7 +427,7 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
|
||||
author's e-mail as a normal Python string.
|
||||
"""
|
||||
|
||||
def author_name(self):
|
||||
def author_email(self):
|
||||
"""
|
||||
Returns the feed's author's e-mail as a normal Python string.
|
||||
"""
|
||||
|
@ -363,10 +363,15 @@ extends
|
||||
|
||||
Signal that this template extends a parent template.
|
||||
|
||||
This tag may be used in two ways: ``{% extends "base.html" %}`` (with quotes)
|
||||
uses the literal value "base.html" as the name of the parent template to
|
||||
extend, or ``{% extends variable %}`` uses the value of ``variable`` as the
|
||||
name of the parent template to extend.
|
||||
This tag can be used in two ways:
|
||||
|
||||
* ``{% extends "base.html" %}`` (with quotes) uses the literal value
|
||||
``"base.html"`` as the name of the parent template to extend.
|
||||
|
||||
* ``{% extends variable %}`` uses the value of ``variable``. If the variable
|
||||
evaluates to a string, Django will use that string as the name of the
|
||||
parent template. If the variable evaluates to a ``Template`` object,
|
||||
Django will use that object as the parent template.
|
||||
|
||||
See `Template inheritance`_ for more information.
|
||||
|
||||
@ -493,6 +498,11 @@ If you need to combine ``and`` and ``or`` to do advanced logic, just use nested
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
Multiple uses of the same logical operator are fine, as long as you use the
|
||||
same operator. For example, this is valid::
|
||||
|
||||
{% if athlete_list or coach_list or parent_list or teacher_list %}
|
||||
|
||||
ifchanged
|
||||
~~~~~~~~~
|
||||
|
||||
|
@ -198,21 +198,6 @@ some things to keep in mind:
|
||||
How invalid variables are handled
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In Django 0.91, if a variable doesn't exist, the template system fails
|
||||
silently. The variable is replaced with an empty string::
|
||||
|
||||
>>> t = Template("My name is {{ my_name }}.")
|
||||
>>> c = Context({"foo": "bar"})
|
||||
>>> t.render(c)
|
||||
"My name is ."
|
||||
|
||||
This applies to any level of lookup::
|
||||
|
||||
>>> t = Template("My name is {{ person.fname }} {{ person.lname }}.")
|
||||
>>> c = Context({"person": {"fname": "Stan"}})
|
||||
>>> t.render(c)
|
||||
"My name is Stan ."
|
||||
|
||||
If a variable doesn't exist, the template system inserts the value of the
|
||||
``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` (the empty
|
||||
string) by default.
|
||||
@ -357,7 +342,7 @@ django.core.context_processors.request
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
|
||||
``DjangoContext`` will contain a variable ``request``, which is the current
|
||||
``RequestContext`` will contain a variable ``request``, which is the current
|
||||
`HttpRequest object`_. Note that this processor is not enabled by default;
|
||||
you'll have to activate it.
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
Managing database transactions
|
||||
==============================
|
||||
|
||||
Django gives you a few ways to control how database transactions are managed.
|
||||
Django gives you a few ways to control how database transactions are managed,
|
||||
if you're using a database that supports transactions.
|
||||
|
||||
Django's default transaction behavior
|
||||
=====================================
|
||||
@ -144,3 +145,19 @@ Thus, this is best used in situations where you want to run your own
|
||||
transaction-controlling middleware or do something really strange. In almost
|
||||
all situations, you'll be better off using the default behavior, or the
|
||||
transaction middleware, and only modify selected functions as needed.
|
||||
|
||||
Transactions in MySQL
|
||||
=====================
|
||||
|
||||
If you're using MySQL, your tables may or may not support transactions; it
|
||||
depends on your MySQL version and the table types you're using. (By
|
||||
"table types," we mean something like "InnoDB" or "MyISAM".) MySQL transaction
|
||||
peculiarities are outside the scope of this article, but the MySQL site has
|
||||
`information on MySQL transactions`_.
|
||||
|
||||
If your MySQL setup does *not* support transactions, then Django will function
|
||||
in auto-commit mode: Statements will be executed and committed as soon as
|
||||
they're called. If your MySQL setup *does* support transactions, Django will
|
||||
handle transactions as explained in this document.
|
||||
|
||||
.. _information on MySQL transactions: http://dev.mysql.com/books/mysqlpress/mysql-tutorial/ch10.html
|
||||
|
@ -81,7 +81,7 @@ the following output on the command line::
|
||||
Validating models...
|
||||
0 errors found.
|
||||
|
||||
Django version 0.95 (post-magic-removal), using settings 'mysite.settings'
|
||||
Django version 0.95, using settings 'mysite.settings'
|
||||
Development server is running at http://127.0.0.1:8000/
|
||||
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).
|
||||
|
||||
|
@ -54,7 +54,8 @@ http://127.0.0.1:8000/admin/. You should see the admin's login screen:
|
||||
Enter the admin site
|
||||
====================
|
||||
|
||||
Now, try logging in. You should see the Django admin index page:
|
||||
Now, try logging in. (You created a superuser account in the first part of this
|
||||
tutorial, remember?) You should see the Django admin index page:
|
||||
|
||||
.. image:: http://media.djangoproject.com/img/doc/tutorial/admin02t.png
|
||||
:alt: Django admin index page
|
||||
|
@ -198,7 +198,7 @@ By default, the ``object_detail`` generic view uses a template called
|
||||
``vote()``.
|
||||
|
||||
Similarly, the ``object_list`` generic view uses a template called
|
||||
``<app name>/<module name>_list.html``. Thus, rename ``poll/index.html`` to
|
||||
``<app name>/<module name>_list.html``. Thus, rename ``polls/index.html`` to
|
||||
``polls/poll_list.html``.
|
||||
|
||||
Because we have more than one entry in the URLconf that uses ``object_detail``
|
||||
@ -206,7 +206,7 @@ for the polls app, we manually specify a template name for the results view:
|
||||
``template_name='polls/results.html'``. Otherwise, both views would use the same
|
||||
template. Note that we use ``dict()`` to return an altered dictionary in place.
|
||||
|
||||
In previous versions of the tutorial, the templates have been provided with a context
|
||||
In previous parts of the tutorial, the templates have been provided with a context
|
||||
that contains the ``poll` and ``latest_poll_list`` context variables. However,
|
||||
the generic views provide the variables ``object`` and ``object_list`` as context.
|
||||
Therefore, you need to change your templates to match the new context variables.
|
||||
|
38
ez_setup.py
38
ez_setup.py
@ -14,34 +14,20 @@ the appropriate options to ``use_setuptools()``.
|
||||
This file can also be run as a script to install or upgrade setuptools.
|
||||
"""
|
||||
import sys
|
||||
DEFAULT_VERSION = "0.6a10"
|
||||
DEFAULT_VERSION = "0.6c1"
|
||||
DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3]
|
||||
|
||||
md5_data = {
|
||||
'setuptools-0.5a13-py2.3.egg': '85edcf0ef39bab66e130d3f38f578c86',
|
||||
'setuptools-0.5a13-py2.4.egg': 'ede4be600e3890e06d4ee5e0148e092a',
|
||||
'setuptools-0.6a1-py2.3.egg': 'ee819a13b924d9696b0d6ca6d1c5833d',
|
||||
'setuptools-0.6a1-py2.4.egg': '8256b5f1cd9e348ea6877b5ddd56257d',
|
||||
'setuptools-0.6a10-py2.3.egg': '162d8357f1aff2b0349c6c247ee62987',
|
||||
'setuptools-0.6a10-py2.4.egg': '803a2d8db501c1ac3b5b6fb4e907f788',
|
||||
'setuptools-0.6a10dev_r42346-py2.3.egg': 'a7899272cfceb6aa60094ae8928b8077',
|
||||
'setuptools-0.6a10dev_r42346-py2.4.egg': '5d42a64adca9aedb409f83ecf22156a5',
|
||||
'setuptools-0.6a2-py2.3.egg': 'b98da449da411267c37a738f0ab625ba',
|
||||
'setuptools-0.6a2-py2.4.egg': 'be5b88bc30aed63fdefd2683be135c3b',
|
||||
'setuptools-0.6a3-py2.3.egg': 'ee0e325de78f23aab79d33106dc2a8c8',
|
||||
'setuptools-0.6a3-py2.4.egg': 'd95453d525a456d6c23e7a5eea89a063',
|
||||
'setuptools-0.6a4-py2.3.egg': 'e958cbed4623bbf47dd1f268b99d7784',
|
||||
'setuptools-0.6a4-py2.4.egg': '7f33c3ac2ef1296f0ab4fac1de4767d8',
|
||||
'setuptools-0.6a5-py2.3.egg': '748408389c49bcd2d84f6ae0b01695b1',
|
||||
'setuptools-0.6a5-py2.4.egg': '999bacde623f4284bfb3ea77941d2627',
|
||||
'setuptools-0.6a6-py2.3.egg': '7858139f06ed0600b0d9383f36aca24c',
|
||||
'setuptools-0.6a6-py2.4.egg': 'c10d20d29acebce0dc76219dc578d058',
|
||||
'setuptools-0.6a7-py2.3.egg': 'cfc4125ddb95c07f9500adc5d6abef6f',
|
||||
'setuptools-0.6a7-py2.4.egg': 'c6d62dab4461f71aed943caea89e6f20',
|
||||
'setuptools-0.6a8-py2.3.egg': '2f18eaaa3f544f5543ead4a68f3b2e1a',
|
||||
'setuptools-0.6a8-py2.4.egg': '799018f2894f14c9f8bcb2b34e69b391',
|
||||
'setuptools-0.6a9-py2.3.egg': '8e438ad70438b07b0d8f82cae42b278f',
|
||||
'setuptools-0.6a9-py2.4.egg': '8f6e01fc12fb1cd006dc0d6c04327ec1',
|
||||
'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
|
||||
'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
|
||||
'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
|
||||
'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
|
||||
'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
|
||||
'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
|
||||
'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
|
||||
'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
|
||||
'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
|
||||
'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
|
||||
}
|
||||
|
||||
import sys, os
|
||||
@ -159,7 +145,7 @@ def main(argv, version=DEFAULT_VERSION):
|
||||
egg = download_setuptools(version, to_dir=tmpdir, delay=0)
|
||||
sys.path.insert(0,egg)
|
||||
from setuptools.command.easy_install import main
|
||||
main(list(argv)+[egg])
|
||||
return main(list(argv)+[egg]) # we're done here
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
else:
|
||||
|
32
setup.py
32
setup.py
@ -14,37 +14,7 @@ setup(
|
||||
packages = find_packages(exclude=['examples', 'examples.*']),
|
||||
package_data = {
|
||||
'': ['*.TXT'],
|
||||
'django.conf': ['locale/ar/LC_MESSAGES/*',
|
||||
'locale/bn/LC_MESSAGES/*',
|
||||
'locale/cs/LC_MESSAGES/*',
|
||||
'locale/cy/LC_MESSAGES/*',
|
||||
'locale/da/LC_MESSAGES/*',
|
||||
'locale/de/LC_MESSAGES/*',
|
||||
'locale/el/LC_MESSAGES/*',
|
||||
'locale/en/LC_MESSAGES/*',
|
||||
'locale/es/LC_MESSAGES/*',
|
||||
'locale/es_AR/LC_MESSAGES/*',
|
||||
'locale/fr/LC_MESSAGES/*',
|
||||
'locale/gl/LC_MESSAGES/*',
|
||||
'locale/hu/LC_MESSAGES/*',
|
||||
'locale/he/LC_MESSAGES/*',
|
||||
'locale/is/LC_MESSAGES/*',
|
||||
'locale/it/LC_MESSAGES/*',
|
||||
'locale/ja/LC_MESSAGES/*',
|
||||
'locale/nl/LC_MESSAGES/*',
|
||||
'locale/no/LC_MESSAGES/*',
|
||||
'locale/pl/LC_MESSAGES/*',
|
||||
'locale/pt_BR/LC_MESSAGES/*',
|
||||
'locale/ro/LC_MESSAGES/*',
|
||||
'locale/ru/LC_MESSAGES/*',
|
||||
'locale/sk/LC_MESSAGES/*',
|
||||
'locale/sl/LC_MESSAGES/*',
|
||||
'locale/sr/LC_MESSAGES/*',
|
||||
'locale/sv/LC_MESSAGES/*',
|
||||
'locale/ta/LC_MESSAGES/*',
|
||||
'locale/uk/LC_MESSAGES/*',
|
||||
'locale/zh_CN/LC_MESSAGES/*',
|
||||
'locale/zh_TW/LC_MESSAGES/*'],
|
||||
'django.conf': ['locale/*/LC_MESSAGES/*'],
|
||||
'django.contrib.admin': ['templates/admin/*.html',
|
||||
'templates/admin_doc/*.html',
|
||||
'templates/registration/*.html',
|
||||
|
@ -410,6 +410,12 @@ TEMPLATE_TESTS = {
|
||||
# Three-level inheritance with {{ block.super }} from parent and grandparent
|
||||
'inheritance23': ("{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}", {}, '1_ab3_'),
|
||||
|
||||
# Inheritance from local context without use of template loader
|
||||
'inheritance24': ("{% extends context_template %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")}, '1234'),
|
||||
|
||||
# Inheritance from local context with variable parent template
|
||||
'inheritance25': ("{% extends context_template.1 %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': [template.Template("Wrong"), template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")]}, '1234'),
|
||||
|
||||
### I18N ##################################################################
|
||||
|
||||
# {% spaceless %} tag
|
||||
|
47
tests/othertests/urlpatterns_reverse.py
Normal file
47
tests/othertests/urlpatterns_reverse.py
Normal file
@ -0,0 +1,47 @@
|
||||
"Unit tests for reverse URL lookup"
|
||||
|
||||
from django.core.urlresolvers import reverse_helper, NoReverseMatch
|
||||
import re
|
||||
|
||||
test_data = (
|
||||
('^places/(\d+)/$', 'places/3/', [3], {}),
|
||||
('^places/(\d+)/$', 'places/3/', ['3'], {}),
|
||||
('^places/(\d+)/$', NoReverseMatch, ['a'], {}),
|
||||
('^places/(\d+)/$', NoReverseMatch, [], {}),
|
||||
('^places/(?P<id>\d+)/$', 'places/3/', [], {'id': 3}),
|
||||
('^people/(?P<name>\w+)/$', 'people/adrian/', ['adrian'], {}),
|
||||
('^people/(?P<name>\w+)/$', 'people/adrian/', [], {'name': 'adrian'}),
|
||||
('^people/(?P<name>\w+)/$', NoReverseMatch, ['name with spaces'], {}),
|
||||
('^people/(?P<name>\w+)/$', NoReverseMatch, [], {'name': 'name with spaces'}),
|
||||
('^people/(?P<name>\w+)/$', NoReverseMatch, [], {}),
|
||||
('^hardcoded/$', 'hardcoded/', [], {}),
|
||||
('^hardcoded/$', 'hardcoded/', ['any arg'], {}),
|
||||
('^hardcoded/$', 'hardcoded/', [], {'kwarg': 'foo'}),
|
||||
('^people/(?P<state>\w\w)/(?P<name>\w+)/$', 'people/il/adrian/', [], {'state': 'il', 'name': 'adrian'}),
|
||||
('^people/(?P<state>\w\w)/(?P<name>\d)/$', NoReverseMatch, [], {'state': 'il', 'name': 'adrian'}),
|
||||
('^people/(?P<state>\w\w)/(?P<name>\w+)/$', NoReverseMatch, [], {'state': 'il'}),
|
||||
('^people/(?P<state>\w\w)/(?P<name>\w+)/$', NoReverseMatch, [], {'name': 'adrian'}),
|
||||
('^people/(?P<state>\w\w)/(\w+)/$', NoReverseMatch, ['il'], {'name': 'adrian'}),
|
||||
('^people/(?P<state>\w\w)/(\w+)/$', 'people/il/adrian/', ['adrian'], {'state': 'il'}),
|
||||
)
|
||||
|
||||
def run_tests(verbosity=0):
|
||||
for regex, expected, args, kwargs in test_data:
|
||||
passed = True
|
||||
try:
|
||||
got = reverse_helper(re.compile(regex), *args, **kwargs)
|
||||
except NoReverseMatch, e:
|
||||
if expected != NoReverseMatch:
|
||||
passed, got = False, str(e)
|
||||
else:
|
||||
if got != expected:
|
||||
passed, got = False, got
|
||||
if passed and verbosity:
|
||||
print "Passed: %s" % regex
|
||||
elif not passed:
|
||||
print "REVERSE LOOKUP FAILED: %s" % regex
|
||||
print " Got: %s" % got
|
||||
print " Expected: %r" % expected
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_tests(1)
|
Loading…
x
Reference in New Issue
Block a user