mirror of
https://github.com/django/django.git
synced 2025-07-05 10:19:20 +00:00
queryset-refactor: Merged from trunk up to [7168].
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7173 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
7c54780497
commit
2f2908d7b5
@ -1,3 +1,11 @@
|
|||||||
|
import base64
|
||||||
|
import md5
|
||||||
|
import cPickle as pickle
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django import http, template
|
from django import http, template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@ -5,8 +13,6 @@ from django.contrib.auth import authenticate, login
|
|||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
import base64, md5
|
|
||||||
import cPickle as pickle
|
|
||||||
|
|
||||||
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
||||||
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
||||||
@ -104,4 +110,4 @@ def staff_member_required(view_func):
|
|||||||
else:
|
else:
|
||||||
return _display_login_form(request, ERROR_MESSAGE)
|
return _display_login_form(request, ERROR_MESSAGE)
|
||||||
|
|
||||||
return _checklogin
|
return wraps(view_func)(_checklogin)
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
try:
|
||||||
|
from functools import wraps, update_wrapper
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps, update_wrapper # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.utils.http import urlquote
|
from django.utils.http import urlquote
|
||||||
@ -51,7 +56,7 @@ class _CheckLogin(object):
|
|||||||
self.test_func = test_func
|
self.test_func = test_func
|
||||||
self.login_url = login_url
|
self.login_url = login_url
|
||||||
self.redirect_field_name = redirect_field_name
|
self.redirect_field_name = redirect_field_name
|
||||||
self.__name__ = view_func.__name__
|
update_wrapper(self, view_func)
|
||||||
|
|
||||||
def __get__(self, obj, cls=None):
|
def __get__(self, obj, cls=None):
|
||||||
view_func = self.view_func.__get__(obj, cls)
|
view_func = self.view_func.__get__(obj, cls)
|
||||||
|
@ -109,7 +109,8 @@ class BaseHandler(object):
|
|||||||
except exceptions.PermissionDenied:
|
except exceptions.PermissionDenied:
|
||||||
return http.HttpResponseForbidden('<h1>Permission denied</h1>')
|
return http.HttpResponseForbidden('<h1>Permission denied</h1>')
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
pass # See http://code.djangoproject.com/ticket/1023
|
# Allow sys.exit() to actually exit. See tickets #1023 and #4701
|
||||||
|
raise
|
||||||
except: # Handle everything else, including SuspiciousOperation, etc.
|
except: # Handle everything else, including SuspiciousOperation, etc.
|
||||||
# Get the exception info now, in case another exception is thrown later.
|
# Get the exception info now, in case another exception is thrown later.
|
||||||
exc_info = sys.exc_info()
|
exc_info = sys.exc_info()
|
||||||
|
@ -29,7 +29,7 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||||||
|
|
||||||
def field_cast_sql(self, db_type):
|
def field_cast_sql(self, db_type):
|
||||||
if db_type == 'inet':
|
if db_type == 'inet':
|
||||||
return 'CAST(%s AS TEXT)'
|
return 'HOST(%s)'
|
||||||
return '%s'
|
return '%s'
|
||||||
|
|
||||||
def last_insert_id(self, cursor, table_name, pk_name):
|
def last_insert_id(self, cursor, table_name, pk_name):
|
||||||
|
@ -23,26 +23,64 @@ RECURSIVE_RELATIONSHIP_CONSTANT = 'self'
|
|||||||
|
|
||||||
pending_lookups = {}
|
pending_lookups = {}
|
||||||
|
|
||||||
def add_lookup(rel_cls, field):
|
def add_lazy_relation(cls, field, relation):
|
||||||
name = field.rel.to
|
"""
|
||||||
module = rel_cls.__module__
|
Adds a lookup on ``cls`` when a related field is defined using a string,
|
||||||
key = (module, name)
|
i.e.::
|
||||||
# Has the model already been loaded?
|
|
||||||
# If so, resolve the string reference right away
|
class MyModel(Model):
|
||||||
model = get_model(rel_cls._meta.app_label, field.rel.to, False)
|
fk = ForeignKey("AnotherModel")
|
||||||
|
|
||||||
|
This string can be:
|
||||||
|
|
||||||
|
* RECURSIVE_RELATIONSHIP_CONSTANT (i.e. "self") to indicate a recursive
|
||||||
|
relation.
|
||||||
|
|
||||||
|
* The name of a model (i.e "AnotherModel") to indicate another model in
|
||||||
|
the same app.
|
||||||
|
|
||||||
|
* An app-label and model name (i.e. "someapp.AnotherModel") to indicate
|
||||||
|
another model in a different app.
|
||||||
|
|
||||||
|
If the other model hasn't yet been loaded -- almost a given if you're using
|
||||||
|
lazy relationships -- then the relation won't be set up until the
|
||||||
|
class_prepared signal fires at the end of model initialization.
|
||||||
|
"""
|
||||||
|
# Check for recursive relations
|
||||||
|
if relation == RECURSIVE_RELATIONSHIP_CONSTANT:
|
||||||
|
app_label = cls._meta.app_label
|
||||||
|
model_name = cls.__name__
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Look for an "app.Model" relation
|
||||||
|
try:
|
||||||
|
app_label, model_name = relation.split(".")
|
||||||
|
except ValueError:
|
||||||
|
# If we can't split, assume a model in current app
|
||||||
|
app_label = cls._meta.app_label
|
||||||
|
model_name = relation
|
||||||
|
|
||||||
|
# Try to look up the related model, and if it's already loaded resolve the
|
||||||
|
# string right away. If get_model returns None, it means that the related
|
||||||
|
# model isn't loaded yet, so we need to pend the relation until the class
|
||||||
|
# is prepared.
|
||||||
|
model = get_model(app_label, model_name, False)
|
||||||
if model:
|
if model:
|
||||||
field.rel.to = model
|
field.rel.to = model
|
||||||
field.do_related_class(model, rel_cls)
|
field.do_related_class(model, cls)
|
||||||
else:
|
else:
|
||||||
# Mark the related field for later lookup
|
key = (app_label, model_name)
|
||||||
pending_lookups.setdefault(key, []).append((rel_cls, field))
|
value = (cls, field)
|
||||||
|
pending_lookups.setdefault(key, []).append(value)
|
||||||
|
|
||||||
def do_pending_lookups(sender):
|
def do_pending_lookups(sender):
|
||||||
other_cls = sender
|
"""
|
||||||
key = (other_cls.__module__, other_cls.__name__)
|
Handle any pending relations to the sending model. Sent from class_prepared.
|
||||||
for rel_cls, field in pending_lookups.setdefault(key, []):
|
"""
|
||||||
field.rel.to = other_cls
|
key = (sender._meta.app_label, sender.__name__)
|
||||||
field.do_related_class(other_cls, rel_cls)
|
for cls, field in pending_lookups.pop(key, []):
|
||||||
|
field.rel.to = sender
|
||||||
|
field.do_related_class(sender, cls)
|
||||||
|
|
||||||
dispatcher.connect(do_pending_lookups, signal=signals.class_prepared)
|
dispatcher.connect(do_pending_lookups, signal=signals.class_prepared)
|
||||||
|
|
||||||
@ -66,9 +104,7 @@ class RelatedField(object):
|
|||||||
sup.contribute_to_class(cls, name)
|
sup.contribute_to_class(cls, name)
|
||||||
other = self.rel.to
|
other = self.rel.to
|
||||||
if isinstance(other, basestring):
|
if isinstance(other, basestring):
|
||||||
if other == RECURSIVE_RELATIONSHIP_CONSTANT:
|
add_lazy_relation(cls, self, other)
|
||||||
self.rel.to = cls.__name__
|
|
||||||
add_lookup(cls, self)
|
|
||||||
else:
|
else:
|
||||||
self.do_related_class(other, cls)
|
self.do_related_class(other, cls)
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ class QueryDict(MultiValueDict):
|
|||||||
dict.__setitem__(result, key, value)
|
dict.__setitem__(result, key, value)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __deepcopy__(self, memo={}):
|
def __deepcopy__(self, memo):
|
||||||
import copy
|
import copy
|
||||||
result = self.__class__('', mutable=True)
|
result = self.__class__('', mutable=True)
|
||||||
memo[id(self)] = result
|
memo[id(self)] = result
|
||||||
@ -223,7 +223,7 @@ class QueryDict(MultiValueDict):
|
|||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
"Returns a mutable copy of this object."
|
"Returns a mutable copy of this object."
|
||||||
return self.__deepcopy__()
|
return self.__deepcopy__({})
|
||||||
|
|
||||||
def urlencode(self):
|
def urlencode(self):
|
||||||
output = []
|
output = []
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import random as random_module
|
import random as random_module
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.template import Variable, Library
|
from django.template import Variable, Library
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -35,7 +39,7 @@ def stringfilter(func):
|
|||||||
for attr in ('is_safe', 'needs_autoescape'):
|
for attr in ('is_safe', 'needs_autoescape'):
|
||||||
if hasattr(func, attr):
|
if hasattr(func, attr):
|
||||||
setattr(_dec, attr, getattr(func, attr))
|
setattr(_dec, attr, getattr(func, attr))
|
||||||
return _dec
|
return wraps(func)(_dec)
|
||||||
|
|
||||||
###################
|
###################
|
||||||
# STRINGS #
|
# STRINGS #
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
"Functions that help with dynamically creating decorators for views."
|
"Functions that help with dynamically creating decorators for views."
|
||||||
|
|
||||||
import types
|
import types
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
def decorator_from_middleware(middleware_class):
|
def decorator_from_middleware(middleware_class):
|
||||||
"""
|
"""
|
||||||
@ -53,5 +57,5 @@ def decorator_from_middleware(middleware_class):
|
|||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
return response
|
return response
|
||||||
return _wrapped_view
|
return wraps(view_func)(_wrapped_view)
|
||||||
return _decorator_from_middleware
|
return _decorator_from_middleware
|
||||||
|
@ -1,8 +1,120 @@
|
|||||||
|
# License for code in this file that was taken from Python 2.5.
|
||||||
|
|
||||||
|
# PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||||
|
# --------------------------------------------
|
||||||
|
#
|
||||||
|
# 1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||||
|
# ("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||||
|
# otherwise using this software ("Python") in source or binary form and
|
||||||
|
# its associated documentation.
|
||||||
|
#
|
||||||
|
# 2. Subject to the terms and conditions of this License Agreement, PSF
|
||||||
|
# hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
||||||
|
# license to reproduce, analyze, test, perform and/or display publicly,
|
||||||
|
# prepare derivative works, distribute, and otherwise use Python
|
||||||
|
# alone or in any derivative version, provided, however, that PSF's
|
||||||
|
# License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
|
||||||
|
# 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation;
|
||||||
|
# All Rights Reserved" are retained in Python alone or in any derivative
|
||||||
|
# version prepared by Licensee.
|
||||||
|
#
|
||||||
|
# 3. In the event Licensee prepares a derivative work that is based on
|
||||||
|
# or incorporates Python or any part thereof, and wants to make
|
||||||
|
# the derivative work available to others as provided herein, then
|
||||||
|
# Licensee hereby agrees to include in any such work a brief summary of
|
||||||
|
# the changes made to Python.
|
||||||
|
#
|
||||||
|
# 4. PSF is making Python available to Licensee on an "AS IS"
|
||||||
|
# basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||||
|
# IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||||
|
# DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||||
|
# FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||||
|
# INFRINGE ANY THIRD PARTY RIGHTS.
|
||||||
|
#
|
||||||
|
# 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||||
|
# FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||||
|
# A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||||
|
# OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||||
|
#
|
||||||
|
# 6. This License Agreement will automatically terminate upon a material
|
||||||
|
# breach of its terms and conditions.
|
||||||
|
#
|
||||||
|
# 7. Nothing in this License Agreement shall be deemed to create any
|
||||||
|
# relationship of agency, partnership, or joint venture between PSF and
|
||||||
|
# Licensee. This License Agreement does not grant permission to use PSF
|
||||||
|
# trademarks or trade name in a trademark sense to endorse or promote
|
||||||
|
# products or services of Licensee, or any third party.
|
||||||
|
#
|
||||||
|
# 8. By copying, installing or otherwise using Python, Licensee
|
||||||
|
# agrees to be bound by the terms and conditions of this License
|
||||||
|
# Agreement.
|
||||||
|
|
||||||
|
|
||||||
def curry(_curried_func, *args, **kwargs):
|
def curry(_curried_func, *args, **kwargs):
|
||||||
def _curried(*moreargs, **morekwargs):
|
def _curried(*moreargs, **morekwargs):
|
||||||
return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
|
return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
|
||||||
return _curried
|
return _curried
|
||||||
|
|
||||||
|
### Begin from Python 2.5 functools.py ########################################
|
||||||
|
|
||||||
|
# Summary of changes made to the Python 2.5 code below:
|
||||||
|
# * swapped ``partial`` for ``curry`` to maintain backwards-compatibility
|
||||||
|
# in Django.
|
||||||
|
# * Wrapped the ``setattr`` call in ``update_wrapper`` with a try-except
|
||||||
|
# block to make it compatible with Python 2.3, which doesn't allow
|
||||||
|
# assigning to ``__name__``.
|
||||||
|
|
||||||
|
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation.
|
||||||
|
# All Rights Reserved.
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# update_wrapper() and wraps() are tools to help write
|
||||||
|
# wrapper functions that can handle naive introspection
|
||||||
|
|
||||||
|
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
|
||||||
|
WRAPPER_UPDATES = ('__dict__',)
|
||||||
|
def update_wrapper(wrapper,
|
||||||
|
wrapped,
|
||||||
|
assigned = WRAPPER_ASSIGNMENTS,
|
||||||
|
updated = WRAPPER_UPDATES):
|
||||||
|
"""Update a wrapper function to look like the wrapped function
|
||||||
|
|
||||||
|
wrapper is the function to be updated
|
||||||
|
wrapped is the original function
|
||||||
|
assigned is a tuple naming the attributes assigned directly
|
||||||
|
from the wrapped function to the wrapper function (defaults to
|
||||||
|
functools.WRAPPER_ASSIGNMENTS)
|
||||||
|
updated is a tuple naming the attributes off the wrapper that
|
||||||
|
are updated with the corresponding attribute from the wrapped
|
||||||
|
function (defaults to functools.WRAPPER_UPDATES)
|
||||||
|
"""
|
||||||
|
for attr in assigned:
|
||||||
|
try:
|
||||||
|
setattr(wrapper, attr, getattr(wrapped, attr))
|
||||||
|
except TypeError: # Python 2.3 doesn't allow assigning to __name__.
|
||||||
|
pass
|
||||||
|
for attr in updated:
|
||||||
|
getattr(wrapper, attr).update(getattr(wrapped, attr))
|
||||||
|
# Return the wrapper so this can be used as a decorator via curry()
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
def wraps(wrapped,
|
||||||
|
assigned = WRAPPER_ASSIGNMENTS,
|
||||||
|
updated = WRAPPER_UPDATES):
|
||||||
|
"""Decorator factory to apply update_wrapper() to a wrapper function
|
||||||
|
|
||||||
|
Returns a decorator that invokes update_wrapper() with the decorated
|
||||||
|
function as the wrapper argument and the arguments to wraps() as the
|
||||||
|
remaining arguments. Default arguments are as for update_wrapper().
|
||||||
|
This is a convenience function to simplify applying curry() to
|
||||||
|
update_wrapper().
|
||||||
|
"""
|
||||||
|
return curry(update_wrapper, wrapped=wrapped,
|
||||||
|
assigned=assigned, updated=updated)
|
||||||
|
|
||||||
|
### End from Python 2.5 functools.py ##########################################
|
||||||
|
|
||||||
def memoize(func, cache, num_args):
|
def memoize(func, cache, num_args):
|
||||||
"""
|
"""
|
||||||
Wrap a function so that results for any argument tuple are stored in
|
Wrap a function so that results for any argument tuple are stored in
|
||||||
@ -18,7 +130,7 @@ def memoize(func, cache, num_args):
|
|||||||
result = func(*args)
|
result = func(*args)
|
||||||
cache[mem_args] = result
|
cache[mem_args] = result
|
||||||
return result
|
return result
|
||||||
return wrapper
|
return wraps(func)(wrapper)
|
||||||
|
|
||||||
class Promise(object):
|
class Promise(object):
|
||||||
"""
|
"""
|
||||||
@ -110,7 +222,7 @@ def lazy(func, *resultclasses):
|
|||||||
# Creates the proxy object, instead of the actual value.
|
# Creates the proxy object, instead of the actual value.
|
||||||
return __proxy__(args, kw)
|
return __proxy__(args, kw)
|
||||||
|
|
||||||
return __wrapper__
|
return wraps(func)(__wrapper__)
|
||||||
|
|
||||||
def allow_lazy(func, *resultclasses):
|
def allow_lazy(func, *resultclasses):
|
||||||
"""
|
"""
|
||||||
@ -126,4 +238,4 @@ def allow_lazy(func, *resultclasses):
|
|||||||
else:
|
else:
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
return lazy(func, *resultclasses)(*args, **kwargs)
|
return lazy(func, *resultclasses)(*args, **kwargs)
|
||||||
return wrapper
|
return wraps(func)(wrapper)
|
||||||
|
@ -11,6 +11,11 @@ Additionally, all headers from the response's Vary header will be taken into
|
|||||||
account on caching -- just like the middleware does.
|
account on caching -- just like the middleware does.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.utils.decorators import decorator_from_middleware
|
from django.utils.decorators import decorator_from_middleware
|
||||||
from django.utils.cache import patch_cache_control, add_never_cache_headers
|
from django.utils.cache import patch_cache_control, add_never_cache_headers
|
||||||
from django.middleware.cache import CacheMiddleware
|
from django.middleware.cache import CacheMiddleware
|
||||||
@ -26,7 +31,7 @@ def cache_control(**kwargs):
|
|||||||
patch_cache_control(response, **kwargs)
|
patch_cache_control(response, **kwargs)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
return _cache_controlled
|
return wraps(viewfunc)(_cache_controlled)
|
||||||
|
|
||||||
return _cache_controller
|
return _cache_controller
|
||||||
|
|
||||||
@ -39,4 +44,4 @@ def never_cache(view_func):
|
|||||||
response = view_func(request, *args, **kwargs)
|
response = view_func(request, *args, **kwargs)
|
||||||
add_never_cache_headers(response)
|
add_never_cache_headers(response)
|
||||||
return response
|
return response
|
||||||
return _wrapped_view_func
|
return wraps(view_func)(_wrapped_view_func)
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
Decorators for views based on HTTP headers.
|
Decorators for views based on HTTP headers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.utils.decorators import decorator_from_middleware
|
from django.utils.decorators import decorator_from_middleware
|
||||||
from django.middleware.http import ConditionalGetMiddleware
|
from django.middleware.http import ConditionalGetMiddleware
|
||||||
from django.http import HttpResponseNotAllowed
|
from django.http import HttpResponseNotAllowed
|
||||||
@ -24,7 +29,7 @@ def require_http_methods(request_method_list):
|
|||||||
if request.method not in request_method_list:
|
if request.method not in request_method_list:
|
||||||
return HttpResponseNotAllowed(request_method_list)
|
return HttpResponseNotAllowed(request_method_list)
|
||||||
return func(request, *args, **kwargs)
|
return func(request, *args, **kwargs)
|
||||||
return inner
|
return wraps(func)(inner)
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
require_GET = require_http_methods(["GET"])
|
require_GET = require_http_methods(["GET"])
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
try:
|
||||||
|
from functools import wraps
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
|
||||||
|
|
||||||
from django.utils.cache import patch_vary_headers
|
from django.utils.cache import patch_vary_headers
|
||||||
|
|
||||||
def vary_on_headers(*headers):
|
def vary_on_headers(*headers):
|
||||||
@ -16,7 +21,7 @@ def vary_on_headers(*headers):
|
|||||||
response = func(*args, **kwargs)
|
response = func(*args, **kwargs)
|
||||||
patch_vary_headers(response, headers)
|
patch_vary_headers(response, headers)
|
||||||
return response
|
return response
|
||||||
return inner_func
|
return wraps(func)(inner_func)
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
def vary_on_cookie(func):
|
def vary_on_cookie(func):
|
||||||
@ -32,4 +37,4 @@ def vary_on_cookie(func):
|
|||||||
response = func(*args, **kwargs)
|
response = func(*args, **kwargs)
|
||||||
patch_vary_headers(response, ('Cookie',))
|
patch_vary_headers(response, ('Cookie',))
|
||||||
return response
|
return response
|
||||||
return inner_func
|
return wraps(func)(inner_func)
|
||||||
|
@ -784,9 +784,17 @@ you can use the name of the model, rather than the model object itself::
|
|||||||
class Manufacturer(models.Model):
|
class Manufacturer(models.Model):
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
Note, however, that you can only use strings to refer to models in the same
|
Note, however, that this only refers to models in the same models.py file -- you
|
||||||
models.py file -- you cannot use a string to reference a model in a different
|
cannot use a string to reference a model defined in another application or
|
||||||
application, or to reference a model that has been imported from elsewhere.
|
imported from elsewhere.
|
||||||
|
|
||||||
|
**New in Django development version:** to refer to models defined in another
|
||||||
|
application, you must instead explicitially specify the application label. That
|
||||||
|
is, if the ``Manufacturer`` model above is defined in another application called
|
||||||
|
``production``, you'd need to use::
|
||||||
|
|
||||||
|
class Car(models.Model):
|
||||||
|
manufacturer = models.ForeignKey('production.Manufacturer')
|
||||||
|
|
||||||
Behind the scenes, Django appends ``"_id"`` to the field name to create its
|
Behind the scenes, Django appends ``"_id"`` to the field name to create its
|
||||||
database column name. In the above example, the database table for the ``Car``
|
database column name. In the above example, the database table for the ``Car``
|
||||||
|
@ -61,13 +61,13 @@ _django_completion()
|
|||||||
||
|
||
|
||||||
# python manage.py, /some/path/python manage.py (if manage.py exists)
|
# python manage.py, /some/path/python manage.py (if manage.py exists)
|
||||||
( ${COMP_CWORD} -eq 2 &&
|
( ${COMP_CWORD} -eq 2 &&
|
||||||
( $( basename ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
|
( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
|
||||||
( $( basename ${COMP_WORDS[1]} ) == manage.py) &&
|
( $( basename -- ${COMP_WORDS[1]} ) == manage.py) &&
|
||||||
( -r ${COMP_WORDS[1]} ) )
|
( -r ${COMP_WORDS[1]} ) )
|
||||||
||
|
||
|
||||||
( ${COMP_CWORD} -eq 2 &&
|
( ${COMP_CWORD} -eq 2 &&
|
||||||
( $( basename ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
|
( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
|
||||||
( $( basename ${COMP_WORDS[1]} ) == django-admin.py) &&
|
( $( basename -- ${COMP_WORDS[1]} ) == django-admin.py) &&
|
||||||
( -r ${COMP_WORDS[1]} ) ) ]] ; then
|
( -r ${COMP_WORDS[1]} ) ) ]] ; then
|
||||||
|
|
||||||
case ${cur} in
|
case ${cur} in
|
||||||
@ -149,7 +149,7 @@ unset pythons
|
|||||||
if command -v whereis &>/dev/null; then
|
if command -v whereis &>/dev/null; then
|
||||||
python_interpreters=$(whereis python | cut -d " " -f 2-)
|
python_interpreters=$(whereis python | cut -d " " -f 2-)
|
||||||
for python in $python_interpreters; do
|
for python in $python_interpreters; do
|
||||||
pythons="${pythons} $(basename $python)"
|
pythons="${pythons} $(basename -- $python)"
|
||||||
done
|
done
|
||||||
pythons=$(echo $pythons | tr " " "\n" | sort -u | tr "\n" " ")
|
pythons=$(echo $pythons | tr " " "\n" | sort -u | tr "\n" " ")
|
||||||
else
|
else
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
"""
|
"""
|
||||||
24. Mutually referential many-to-one relationships
|
24. Mutually referential many-to-one relationships
|
||||||
|
|
||||||
To define a many-to-one relationship, use ``ForeignKey()`` .
|
Strings can be used instead of model literals to set up "lazy" relations.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.db.models import *
|
from django.db.models import *
|
||||||
|
|
||||||
class Parent(Model):
|
class Parent(Model):
|
||||||
name = CharField(max_length=100, core=True)
|
name = CharField(max_length=100, core=True)
|
||||||
|
|
||||||
|
# Use a simple string for forward declarations.
|
||||||
bestchild = ForeignKey("Child", null=True, related_name="favoured_by")
|
bestchild = ForeignKey("Child", null=True, related_name="favoured_by")
|
||||||
|
|
||||||
class Child(Model):
|
class Child(Model):
|
||||||
name = CharField(max_length=100)
|
name = CharField(max_length=100)
|
||||||
parent = ForeignKey(Parent)
|
|
||||||
|
# You can also explicitally specify the related app.
|
||||||
|
parent = ForeignKey("mutually_referential.Parent")
|
||||||
|
|
||||||
__test__ = {'API_TESTS':"""
|
__test__ = {'API_TESTS':"""
|
||||||
# Create a Parent
|
# Create a Parent
|
||||||
|
0
tests/regressiontests/decorators/__init__.py
Normal file
0
tests/regressiontests/decorators/__init__.py
Normal file
2
tests/regressiontests/decorators/models.py
Normal file
2
tests/regressiontests/decorators/models.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# A models.py so that tests run.
|
||||||
|
|
56
tests/regressiontests/decorators/tests.py
Normal file
56
tests/regressiontests/decorators/tests.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from sys import version_info
|
||||||
|
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.utils.functional import allow_lazy, lazy, memoize
|
||||||
|
from django.views.decorators.http import require_http_methods, require_GET, require_POST
|
||||||
|
from django.views.decorators.vary import vary_on_headers, vary_on_cookie
|
||||||
|
from django.views.decorators.cache import cache_page, never_cache, cache_control
|
||||||
|
from django.contrib.auth.decorators import login_required, permission_required, user_passes_test
|
||||||
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
|
|
||||||
|
def fully_decorated(request):
|
||||||
|
"""Expected __doc__"""
|
||||||
|
return HttpResponse('<html><body>dummy</body></html>')
|
||||||
|
fully_decorated.anything = "Expected __dict__"
|
||||||
|
|
||||||
|
# django.views.decorators.http
|
||||||
|
fully_decorated = require_http_methods(["GET"])(fully_decorated)
|
||||||
|
fully_decorated = require_GET(fully_decorated)
|
||||||
|
fully_decorated = require_POST(fully_decorated)
|
||||||
|
|
||||||
|
# django.views.decorators.vary
|
||||||
|
fully_decorated = vary_on_headers('Accept-language')(fully_decorated)
|
||||||
|
fully_decorated = vary_on_cookie(fully_decorated)
|
||||||
|
|
||||||
|
# django.views.decorators.cache
|
||||||
|
fully_decorated = cache_page(60*15)(fully_decorated)
|
||||||
|
fully_decorated = cache_control(private=True)(fully_decorated)
|
||||||
|
fully_decorated = never_cache(fully_decorated)
|
||||||
|
|
||||||
|
# django.contrib.auth.decorators
|
||||||
|
fully_decorated = user_passes_test(lambda u:True)(fully_decorated)
|
||||||
|
fully_decorated = login_required(fully_decorated)
|
||||||
|
fully_decorated = permission_required('change_world')(fully_decorated)
|
||||||
|
|
||||||
|
# django.contrib.admin.views.decorators
|
||||||
|
fully_decorated = staff_member_required(fully_decorated)
|
||||||
|
|
||||||
|
# django.utils.functional
|
||||||
|
fully_decorated = memoize(fully_decorated, {}, 1)
|
||||||
|
fully_decorated = allow_lazy(fully_decorated)
|
||||||
|
fully_decorated = lazy(fully_decorated)
|
||||||
|
|
||||||
|
class DecoratorsTest(TestCase):
|
||||||
|
|
||||||
|
def test_attributes(self):
|
||||||
|
"""
|
||||||
|
Tests that django decorators set certain attributes of the wrapped
|
||||||
|
function.
|
||||||
|
"""
|
||||||
|
# Only check __name__ on Python 2.4 or later since __name__ can't be
|
||||||
|
# assigned to in earlier Python versions.
|
||||||
|
if version_info[0] >= 2 and version_info[1] >= 4:
|
||||||
|
self.assertEquals(fully_decorated.__name__, 'fully_decorated')
|
||||||
|
self.assertEquals(fully_decorated.__doc__, 'Expected __doc__')
|
||||||
|
self.assertEquals(fully_decorated.__dict__['anything'], 'Expected __dict__')
|
Loading…
x
Reference in New Issue
Block a user