1
0
mirror of https://github.com/django/django.git synced 2025-04-21 07:44:36 +00:00

i18n: merged to [1025] from trunk

git-svn-id: http://code.djangoproject.com/svn/django/branches/i18n@1027 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Georg Bauer 2005-10-31 00:13:29 +00:00
commit 63651e8a81
19 changed files with 238 additions and 51 deletions

View File

@ -19,6 +19,7 @@ ACTION_MAPPING = {
'init': management.init,
'inspectdb': management.inspectdb,
'install': management.install,
'installperms': management.installperms,
'runserver': management.runserver,
'sql': management.get_sql_create,
'sqlall': management.get_sql_all,
@ -32,7 +33,7 @@ ACTION_MAPPING = {
'validate': management.validate,
}
NO_SQL_TRANSACTION = ('adminindex', 'createcachetable', 'dbcheck', 'install', 'sqlindexes')
NO_SQL_TRANSACTION = ('adminindex', 'createcachetable', 'dbcheck', 'install', 'installperms', 'sqlindexes')
def get_usage():
"""

View File

@ -83,8 +83,8 @@ TEMPLATE_FILE_EXTENSION = '.html'
# See the comments in django/core/template/loader.py for interface
# documentation.
TEMPLATE_LOADERS = (
# 'django.core.template.loaders.app_directories.load_template_source',
'django.core.template.loaders.filesystem.load_template_source',
'django.core.template.loaders.app_directories.load_template_source',
# 'django.core.template.loaders.eggs.load_template_source',
)

View File

@ -9,7 +9,7 @@ function URLify(s, num_chars) {
s = s.replace(r, '');
s = s.replace(/[^\w\s-]/g, ''); // remove unneeded chars
s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
s = s.replace(/\s+/g, '_'); // convert spaces to underscores
s = s.replace(/\s+/g, '-'); // convert spaces to hyphens
s = s.toLowerCase(); // convert to lowercase
return s.substring(0, num_chars);// trim to first num_chars chars
}

View File

@ -288,9 +288,9 @@ DATA_TYPE_MAPPING = {
def get_readable_field_data_type(field):
# ForeignKey is a special case. Use the field type of the relation.
if field.__class__.__name__ == 'ForeignKey':
if field.get_internal_type() == 'ForeignKey':
field = field.rel.get_related_field()
return DATA_TYPE_MAPPING[field.__class__.__name__] % field.__dict__
return DATA_TYPE_MAPPING[field.get_internal_type()] % field.__dict__
def extract_views_from_urlpatterns(urlpatterns, base=''):
"""

View File

@ -556,14 +556,14 @@ def _get_template(opts, app_label, add=False, change=False, show_delete=False, f
if not seen_collapse and 'collapse' in options.get('classes', ''):
seen_collapse = True
javascript_imports.append('%sjs/admin/CollapsedFieldsets.js' % ADMIN_MEDIA_PREFIX)
try:
for field_list in options['fields']:
for field_list in options['fields']:
try:
for f in field_list:
if f.rel and isinstance(f, meta.ManyToManyField) and f.rel.filter_interface:
javascript_imports.extend(['%sjs/SelectBox.js' % ADMIN_MEDIA_PREFIX, '%sjs/SelectFilter2.js' % ADMIN_MEDIA_PREFIX])
raise StopIteration
except StopIteration:
break
except StopIteration:
break
for j in javascript_imports:
t.append('<script type="text/javascript" src="%s"></script>' % j)

View File

@ -13,7 +13,9 @@ settings.CACHE_BACKEND and use that to create and load a cache object.
The CACHE_BACKEND setting is a quasi-URI; examples are:
memcached://127.0.0.1:11211/ A memcached backend; the server is running
on localhost port 11211.
on localhost port 11211. You can use
multiple memcached servers by separating
them with semicolons.
db://tablename/ A database backend in a table named
"tablename". This table should be created
@ -134,7 +136,7 @@ else:
"Memcached cache backend."
def __init__(self, server, params):
_Cache.__init__(self, params)
self._cache = memcache.Client([server])
self._cache = memcache.Client(server.split(';'))
def get(self, key, default=None):
val = self._cache.get(key)

View File

@ -215,6 +215,7 @@ class FormField:
####################
class TextField(FormField):
input_type = "text"
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=[]):
self.field_name = field_name
self.length, self.maxlength = length, maxlength
@ -237,8 +238,8 @@ class TextField(FormField):
maxlength = 'maxlength="%s" ' % self.maxlength
if isinstance(data, unicode):
data = data.encode(DEFAULT_CHARSET)
return '<input type="text" id="%s" class="v%s%s" name="%s" size="%s" value="%s" %s/>' % \
(FORM_FIELD_ID_PREFIX + self.field_name, self.__class__.__name__, self.is_required and ' required' or '',
return '<input type="%s" id="%s" class="v%s%s" name="%s" size="%s" value="%s" %s/>' % \
(self.input_type, FORM_FIELD_ID_PREFIX + self.field_name, self.__class__.__name__, self.is_required and ' required' or '',
self.field_name, self.length, escape(data), maxlength)
def html2python(data):
@ -246,11 +247,7 @@ class TextField(FormField):
html2python = staticmethod(html2python)
class PasswordField(TextField):
def render(self, data):
# value is always blank because we never want to redisplay it
return '<input type="password" id="%s" class="v%s%s" name="%s" value="" />' % \
(FORM_FIELD_ID_PREFIX + self.field_name, self.__class__.__name__, self.is_required and ' required' or '',
self.field_name)
input_type = "password"
class LargeTextField(TextField):
def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=[], maxlength=None):

View File

@ -48,6 +48,9 @@ class BaseHandler:
from django.core.mail import mail_admins
from django.conf.settings import DEBUG, INTERNAL_IPS, ROOT_URLCONF
# Reset query list per request.
db.db.queries = []
# Apply request middleware
for middleware_method in self._request_middleware:
response = middleware_method(request)

View File

@ -345,6 +345,27 @@ The full error: %s\n""" % \
install.help_doc = "Executes ``sqlall`` for the given model module name(s) in the current database."
install.args = APP_ARGS
def installperms(mod):
"Installs any permissions for the given model, if needed."
from django.models.auth import permissions
from django.models.core import packages
num_added = 0
package = packages.get_object(pk=mod._MODELS[0]._meta.app_label)
for klass in mod._MODELS:
opts = klass._meta
for codename, name in _get_all_permissions(opts):
try:
permissions.get_object(name__exact=name, codename__exact=codename, package__label__exact=package.label)
except permissions.PermissionDoesNotExist:
p = permissions.Permission(name=name, package=package, codename=codename)
p.save()
print "Added permission '%r'." % p
num_added += 1
if not num_added:
print "No permissions were added, because all necessary permissions were already installed."
installperms.help_doc = "Installs any permissions for the given model module name(s), if needed."
installperms.args = APP_ARGS
def _start_helper(app_or_project, name, directory, other_name=''):
other = {'project': 'app', 'app': 'project'}[app_or_project]
if not _is_valid_dir_name(name):

View File

@ -24,15 +24,15 @@ def fix_ampersands(value, _):
def floatformat(text, _):
"""
Displays a floating point number as 34.2 (with one decimal place) - but
Displays a floating point number as 34.2 (with one decimal place) -- but
only if there's a point to be displayed
"""
from math import modf
if not text:
return ''
if modf(float(text))[0] < 0.1:
return text
return "%.1f" % float(text)
f = float(text)
m = f - int(f)
if m:
return '%.1f' % f
else:
return '%d' % int(f)
def linenumbers(value, _):
"Displays text with line numbers"
@ -175,7 +175,7 @@ def removetags(value, tags):
"Removes a space separated list of [X]HTML tags from the output"
tags = [re.escape(tag) for tag in tags.split()]
tags_re = '(%s)' % '|'.join(tags)
starttag_re = re.compile('<%s(>|(\s+[^>]*>))' % tags_re)
starttag_re = re.compile(r'<%s(/?>|(\s+[^>]*>))' % tags_re)
endtag_re = re.compile('</%s>' % tags_re)
value = starttag_re.sub('', value)
value = endtag_re.sub('', value)

View File

@ -37,6 +37,8 @@ def reloader_thread():
mtimes = {}
while RUN_RELOADER:
for filename in filter(lambda v: v, map(lambda m: getattr(m, "__file__", None), sys.modules.values())) + reloadFiles:
if not os.path.exists(filename):
continue # File might be in an egg, so it can't be reloaded.
if filename.endswith(".pyc"):
filename = filename[:-1]
mtime = os.stat(filename).st_mtime

View File

@ -21,6 +21,45 @@ import datetime, md5, re
from django.conf import settings
from django.core.cache import cache
cc_delim_re = re.compile(r'\s*,\s*')
def patch_cache_control(response, **kwargs):
"""
This function patches the Cache-Control header by adding all
keyword arguments to it. The transformation is as follows:
- all keyword parameter names are turned to lowercase and
all _ will be translated to -
- if the value of a parameter is True (exatly True, not just a
true value), only the parameter name is added to the header
- all other parameters are added with their value, after applying
str to it.
"""
def dictitem(s):
t = s.split('=',1)
if len(t) > 1:
return (t[0].lower().replace('-', '_'), t[1])
else:
return (t[0].lower().replace('-', '_'), True)
def dictvalue(t):
if t[1] == True:
return t[0]
else:
return t[0] + '=' + str(t[1])
if response.has_header('Cache-Control'):
print response['Cache-Control']
cc = cc_delim_re.split(response['Cache-Control'])
print cc
cc = dict([dictitem(el) for el in cc])
else:
cc = {}
for (k,v) in kwargs.items():
cc[k.replace('_', '-')] = v
cc = ', '.join([dictvalue(el) for el in cc.items()])
response['Cache-Control'] = cc
vary_delim_re = re.compile(r',\s*')
def patch_response_headers(response, cache_timeout=None):
@ -43,8 +82,7 @@ def patch_response_headers(response, cache_timeout=None):
response['Last-Modified'] = now.strftime('%a, %d %b %Y %H:%M:%S GMT')
if not response.has_header('Expires'):
response['Expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S GMT')
if not response.has_header('Cache-Control'):
response['Cache-Control'] = 'max-age=%d' % cache_timeout
patch_cache_control(response, max_age=cache_timeout)
def patch_vary_headers(response, newheaders):
"""

View File

@ -1,19 +1,22 @@
def user_passes_test(view_func, test_func):
def user_passes_test(test_func):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
from django.views.auth.login import redirect_to_login
def _checklogin(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
return redirect_to_login(request.path)
return _checklogin
def _dec(view_func):
def _checklogin(request, *args, **kwargs):
from django.views.auth.login import redirect_to_login
if test_func(request.user):
return view_func(request, *args, **kwargs)
return redirect_to_login(request.path)
return _checklogin
return _dec
def login_required(view_func):
login_required = user_passes_test(lambda u: not u.is_anonymous())
login_required.__doc__ = (
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
return user_passes_test(lambda u: not u.is_anonymous())
)

View File

@ -10,8 +10,24 @@ example, as that is unique across a Django project.
Additionally, all headers from the response's Vary header will be taken into
account on caching -- just like the middleware does.
"""
import re
from django.utils.decorators import decorator_from_middleware
from django.utils.cache import patch_cache_control
from django.middleware.cache import CacheMiddleware
cache_page = decorator_from_middleware(CacheMiddleware)
def cache_control(**kwargs):
def _cache_controller(viewfunc):
def _cache_controlled(request, *args, **kw):
response = viewfunc(request, *args, **kw)
patch_cache_control(response, **kwargs)
return response
return _cache_controlled
return _cache_controller

View File

@ -1,9 +1,35 @@
"""
Decorator for views that supports conditional get on ETag and Last-Modified
headers.
Decorators for views based on HTTP headers.
"""
from django.utils.decorators import decorator_from_middleware
from django.middleware.http import ConditionalGetMiddleware
from django.utils.httpwrappers import HttpResponseForbidden
conditional_page = decorator_from_middleware(ConditionalGetMiddleware)
def require_http_methods(request_method_list):
"""
Decorator to make a view only accept particular request methods. Usage::
@require_http_methods(["GET", "POST"])
def my_view(request):
# I can assume now that only GET or POST requests make it this far
# ...
Note that request methods ARE case sensitive.
"""
def decorator(func):
def inner(request, *args, **kwargs):
method = request.META.get("REQUEST_METHOD", None)
if method not in request_method_list:
raise HttpResponseForbidden("REQUEST_METHOD '%s' not allowed" % method)
return func(request, *args, **kwargs)
return inner
return decorator
require_GET = require_http_methods(["GET"])
require_GET.__doc__ = "Decorator to require that a view only accept the GET method."
require_POST = require_http_methods(["POST"])
require_POST.__doc__ = "Decorator to require that a view only accept the POST method."

View File

@ -1,10 +1,11 @@
from django.core.exceptions import Http404, ObjectDoesNotExist
from django.core.template import Context, loader
from django.models.core import sites
from django.models.core import sites, contenttypes
from django.utils import httpwrappers
def shortcut(request, content_type_id, object_id):
from django.models.core import contenttypes
"""Redirect to an object's page based on a content-type ID and an object ID"""
# Look up the object, making sure it's got a get_absolute_url() function.
try:
content_type = contenttypes.get_object(pk=content_type_id)
obj = content_type.get_object_for_this_type(pk=object_id)
@ -14,25 +15,37 @@ def shortcut(request, content_type_id, object_id):
absurl = obj.get_absolute_url()
except AttributeError:
raise Http404, "%s objects don't have get_absolute_url() methods" % content_type.name
# Try to figure out the object's domain so we can do a cross-site redirect
# if necessary
# If the object actually defines a domain, we're done.
if absurl.startswith('http://'):
return httpwrappers.HttpResponseRedirect(absurl)
object_domain = None
# Next, look for an many-to-many relationship to sites
if hasattr(obj, 'get_site_list'):
site_list = obj.get_site_list()
if site_list:
object_domain = site_list[0].domain
# Next, look for a many-to-one relationship to sites
elif hasattr(obj, 'get_site'):
try:
object_domain = obj.get_site().domain
except sites.SiteDoesNotExist:
pass
try:
object_domain = sites.get_current().domain
except sites.SiteDoesNotExist:
pass
if not object_domain:
return httpwrappers.HttpResponseRedirect(absurl)
return httpwrappers.HttpResponseRedirect('http://%s%s' % (object_domain, absurl))
# Then, fall back to the current site (if possible)
else:
try:
object_domain = sites.get_current().domain
except sites.SiteDoesNotExist:
# Finally, give up and use a URL without the domain name
return httpwrappers.HttpResponseRedirect(obj.get_absolute_url())
return httpwrappers.HttpResponseRedirect('http://%s%s' % (object_domain, obj.get_absolute_url()))
def page_not_found(request):
"""

View File

@ -29,7 +29,9 @@ Examples:
CACHE_BACKEND Explanation
============================== ===========================================
memcached://127.0.0.1:11211/ A memcached backend; the server is running
on localhost port 11211.
on localhost port 11211. You can use
multiple memcached servers by separating
them with semicolons.
db://tablename/ A database backend in a table named
"tablename". This table should be created
@ -270,6 +272,40 @@ and a list/tuple of header names as its second argument.
.. _`HTTP Vary headers`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44
Controlling cache: Using Vary headers
=====================================
Another problem with caching is the privacy of data, and the question where data can
be stored in a cascade of caches. A user usually faces two kinds of caches: his own
browser cache (a private cache) and his providers cache (a public cache). A public cache
is used by multiple users and controlled by someone else. This poses problems with private
(in the sense of sensitive) data - you don't want your social security number or your
banking account numbers stored in some public cache. So web applications need a way
to tell the caches what data is private and what is public.
Other aspects are the definition how long a page should be cached at max, or wether the
cache should allways check for newer versions and only deliver the cache content when
there were no changes (some caches might deliver cached content even if the server page
changed - just because the cache copy isn't yet expired).
So there are a multitude of options you can control for your pages. This is where the
Cache-Control header (more infos in `HTTP Cache-Control headers`_) comes in. The usage
is quite simple::
@cache_control(private=True, must_revalidate=True, max_age=3600)
def my_view(request):
...
This would define the view as private, to be revalidated on every access and cache
copies will only be stored for 3600 seconds at max.
The caching middleware already set's this header up with a max-age of the CACHE_MIDDLEWARE_SETTINGS
setting. And the cache_page decorator does the same. The cache_control decorator correctly merges
different values into one big header, though. But you should take into account that middlewares
might overwrite some of your headers or set their own defaults if you don't give that header yourself.
.. _`HTTP Cache-Control headers`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
Other optimizations
===================

View File

@ -621,6 +621,14 @@ the relationship should work. All are optional:
vertically).
``limit_choices_to`` See the description under ``ForeignKey`` above.
``singular`` The singular name of the field. Use to name the ``get_*``
methods: in the example above, Django gives the ``Pizza``
objects a ``get_topping_list()`` method, where ``topping``
is the default ``singular`` value derived from the lowercase
version of the class being linked to. Use the singular
parameter to change this, which is if you want one model to
have multiple ``ManyToMany`` relationships to another model.
======================= ============================================================
One-to-one relationships
@ -750,11 +758,12 @@ Here's a list of all possible ``META`` options. No options are required. Adding
``permissions``
Extra permissions to enter into the permissions table when creating this
object. Add, delete and change permissions are automatically created for
each object. This option specifies extra permissions::
each object that has ``admin`` set. This example specifies an extra
permission, ``can_deliver_pizzas``::
permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
This is a list of 2-tuples of
This is a list or tuple of 2-tuples in the format
``(permission_code, human_readable_permission_name)``.
``unique_together``

View File

@ -0,0 +1,20 @@
"""
>>> floatformat(7.7, None)
'7.7'
>>> floatformat(7.0, None)
'7'
>>> floatformat(0.7, None)
'0.7'
>>> floatformat(0.07, None)
'0.1'
>>> floatformat(0.007, None)
'0.0'
>>> floatformat(0.0, None)
'0'
"""
from django.core.template.defaultfilters import *
if __name__ == '__main__':
import doctest
doctest.testmod()