1
0
mirror of https://github.com/django/django.git synced 2025-07-05 02:09:13 +00:00

[per-object-permissions] Update to trunk

git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@3630 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Christopher Long 2006-08-20 22:49:48 +00:00
parent 455842e07e
commit 49c1c2fdd3
15 changed files with 142 additions and 22 deletions

View File

@ -68,6 +68,7 @@ answer newbie questions, and generally made Django that much better:
deric@monowerks.com deric@monowerks.com
dne@mayonnaise.net dne@mayonnaise.net
Jeremy Dunck <http://dunck.us/> Jeremy Dunck <http://dunck.us/>
Andy Dustman <farcepest@gmail.com>
Clint Ecker Clint Ecker
gandalf@owca.info gandalf@owca.info
Baishampayan Ghose Baishampayan Ghose

View File

@ -11,7 +11,7 @@ def compile_messages():
elif os.path.isdir('locale'): elif os.path.isdir('locale'):
basedir = os.path.abspath('locale') basedir = os.path.abspath('locale')
else: else:
print "this script should be run from the django svn tree or your project or app tree" print "This script should be run from the Django SVN tree or your project or app tree."
sys.exit(1) sys.exit(1)
for dirpath, dirnames, filenames in os.walk(basedir): for dirpath, dirnames, filenames in os.walk(basedir):
@ -19,7 +19,14 @@ def compile_messages():
if f.endswith('.po'): if f.endswith('.po'):
sys.stderr.write('processing file %s in %s\n' % (f, dirpath)) sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
pf = os.path.splitext(os.path.join(dirpath, f))[0] pf = os.path.splitext(os.path.join(dirpath, f))[0]
cmd = 'msgfmt -o "%s.mo" "%s.po"' % (pf, pf) # Store the names of the .mo and .po files in an environment
# variable, rather than doing a string replacement into the
# command, so that we can take advantage of shell quoting, to
# quote any malicious characters/escaping.
# See http://cyberelk.net/tim/articles/cmdline/ar01s02.html
os.environ['djangocompilemo'] = pf + '.mo'
os.environ['djangocompilepo'] = pf + '.po'
cmd = 'msgfmt -o "$djangocompilemo" "$djangocompilepo"'
os.system(cmd) os.system(cmd)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -27,6 +27,10 @@ LANGUAGE_CODE = 'en-us'
SITE_ID = 1 SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
# Absolute path to the directory that holds media. # Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/" # Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = '' MEDIA_ROOT = ''

View File

@ -6,6 +6,7 @@
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %} {% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %}
{% block extrastyle %}{% endblock %} {% block extrastyle %}{% endblock %}
{% block extrahead %}{% endblock %} {% block extrahead %}{% endblock %}
{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
</head> </head>
{% load i18n %} {% load i18n %}

View File

@ -226,7 +226,7 @@ def model_detail(request, app_label, model_name):
return render_to_response('admin_doc/model_detail.html', { return render_to_response('admin_doc/model_detail.html', {
'name': '%s.%s' % (opts.app_label, opts.object_name), 'name': '%s.%s' % (opts.app_label, opts.object_name),
'summary': "Fields on %s objects" % opts.object_name, 'summary': _("Fields on %s objects") % opts.object_name,
'description': model.__doc__, 'description': model.__doc__,
'fields': fields, 'fields': fields,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))

View File

@ -272,7 +272,9 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
post_url_continue += "?_popup=1" post_url_continue += "?_popup=1"
return HttpResponseRedirect(post_url_continue % pk_value) return HttpResponseRedirect(post_url_continue % pk_value)
if request.POST.has_key("_popup"): if request.POST.has_key("_popup"):
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %r, "%s");</script>' % \ if type(pk_value) is str: # Quote if string, so JavaScript doesn't think it's a variable.
pk_value = '"%s"' % pk_value.replace('"', '\\"')
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
(pk_value, str(new_object).replace('"', '\\"'))) (pk_value, str(new_object).replace('"', '\\"')))
elif request.POST.has_key("_addanother"): elif request.POST.has_key("_addanother"):
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name)) request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
@ -734,9 +736,19 @@ class ChangeList(object):
qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field) qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field)
# Apply keyword searches. # Apply keyword searches.
def construct_search(field_name):
if field_name.startswith('^'):
return "%s__istartswith" % field_name[1:]
elif field_name.startswith('='):
return "%s__iexact" % field_name[1:]
elif field_name.startswith('@'):
return "%s__search" % field_name[1:]
else:
return "%s__icontains" % field_name
if self.lookup_opts.admin.search_fields and self.query: if self.lookup_opts.admin.search_fields and self.query:
for bit in self.query.split(): for bit in self.query.split():
or_queries = [models.Q(**{'%s__icontains' % field_name: bit}) for field_name in self.lookup_opts.admin.search_fields] or_queries = [models.Q(**{construct_search(field_name): bit}) for field_name in self.lookup_opts.admin.search_fields]
other_qs = QuerySet(self.model) other_qs = QuerySet(self.model)
other_qs = other_qs.filter(reduce(operator.or_, or_queries)) other_qs = other_qs.filter(reduce(operator.or_, or_queries))
qs = qs & other_qs qs = qs & other_qs

View File

@ -20,7 +20,7 @@ class CacheClass(BaseCache):
return val return val
def set(self, key, value, timeout=0): def set(self, key, value, timeout=0):
self._cache.set(key, value, timeout) self._cache.set(key, value, timeout or self.default_timeout)
def delete(self, key): def delete(self, key):
self._cache.delete(key) self._cache.delete(key)

View File

@ -41,6 +41,9 @@ class CacheMiddleware(object):
def process_request(self, request): def process_request(self, request):
"Checks whether the page is already cached and returns the cached version if available." "Checks whether the page is already cached and returns the cached version if available."
if self.cache_anonymous_only:
assert hasattr(request, 'user'), "The Django cache middleware with CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' before the CacheMiddleware."
if not request.method in ('GET', 'HEAD') or request.GET: if not request.method in ('GET', 'HEAD') or request.GET:
request._cache_update_cache = False request._cache_update_cache = False
return None # Don't bother checking the cache. return None # Don't bother checking the cache.

View File

@ -35,3 +35,27 @@ class ConditionalGetMiddleware(object):
response.content = '' response.content = ''
return response return response
class SetRemoteAddrFromForwardedFor(object):
"""
Middleware that sets REMOTE_ADDR based on HTTP_X_FORWARDED_FOR, if the
latter is set. This is useful if you're sitting behind a reverse proxy that
causes each request's REMOTE_ADDR to be set to 127.0.0.1.
Note that this does NOT validate HTTP_X_FORWARDED_FOR. If you're not behind
a reverse proxy that sets HTTP_X_FORWARDED_FOR automatically, do not use
this middleware. Anybody can spoof the value of HTTP_X_FORWARDED_FOR, and
because this sets REMOTE_ADDR based on HTTP_X_FORWARDED_FOR, that means
anybody can "fake" their IP address. Only use this when you can absolutely
trust the value of HTTP_X_FORWARDED_FOR.
"""
def process_request(self, request):
try:
real_ip = request.META['HTTP_X_FORWARDED_FOR']
except KeyError:
return None
else:
# HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs.
# Take just the first one.
real_ip = real_ip.split(",")[0]
request.META['REMOTE_ADDR'] = real_ip

View File

@ -233,7 +233,10 @@ The cache middleware caches every page that doesn't have GET or POST
parameters. Optionally, if the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting is parameters. Optionally, if the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting is
``True``, only anonymous requests (i.e., not those made by a logged-in user) ``True``, only anonymous requests (i.e., not those made by a logged-in user)
will be cached. This is a simple and effective way of disabling caching for any will be cached. This is a simple and effective way of disabling caching for any
user-specific pages (include Django's admin interface). user-specific pages (include Django's admin interface). Note that if you use
``CACHE_MIDDLEWARE_ANONYMOUS_ONLY``, you should make sure you've activated
``AuthenticationMiddleware`` and that ``AuthenticationMiddleware`` appears
before ``CacheMiddleware`` in your ``MIDDLEWARE_CLASSES``.
Additionally, ``CacheMiddleware`` automatically sets a few headers in each Additionally, ``CacheMiddleware`` automatically sets a few headers in each
``HttpResponse``: ``HttpResponse``:

View File

@ -98,11 +98,10 @@ Lawrence, Kansas, USA.
On IRC, Simon goes by ``SimonW``. On IRC, Simon goes by ``SimonW``.
`Wilson Miner`_ `Wilson Miner`_
Wilson's design-fu makes us all look like rock stars. When not sneaking Wilson's design-fu makes us all look like rock stars. By day, he's an
into apartment complex swimming pools, he's the Commercial Development interactive designer for `Apple`. Don't ask him what he's working on, or
Director for World Online, which means he makes the money that pays all our he'll have to kill you. He lives in San Francisco.
paychecks. He lives in Lawrence, Kansas.
On IRC, Wilson goes by ``wilsonian``. On IRC, Wilson goes by ``wilsonian``.
.. _`World Online`: http://code.djangoproject.com/wiki/WorldOnline .. _`World Online`: http://code.djangoproject.com/wiki/WorldOnline
@ -113,6 +112,7 @@ Lawrence, Kansas, USA.
.. _`simon.incutio.com`: http://simon.incutio.com/ .. _`simon.incutio.com`: http://simon.incutio.com/
.. _`Jacob Kaplan-Moss`: http://www.jacobian.org/ .. _`Jacob Kaplan-Moss`: http://www.jacobian.org/
.. _`Wilson Miner`: http://www.wilsonminer.com/ .. _`Wilson Miner`: http://www.wilsonminer.com/
.. _`Apple`: http://www.apple.com/
Which sites use Django? Which sites use Django?
----------------------- -----------------------

View File

@ -48,9 +48,10 @@ bit of i18n-related overhead in certain places of the framework. If you don't
use internationalization, you should take the two seconds to set use internationalization, you should take the two seconds to set
``USE_I18N = False`` in your settings file. If ``USE_I18N`` is set to ``USE_I18N = False`` in your settings file. If ``USE_I18N`` is set to
``False``, then Django will make some optimizations so as not to load the ``False``, then Django will make some optimizations so as not to load the
internationalization machinery. internationalization machinery. See the `documentation for USE_I18N`_.
See the `documentation for USE_I18N`_. You'll probably also want to remove ``'django.core.context_processors.i18n'``
from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting.
.. _documentation for USE_I18N: http://www.djangoproject.com/documentation/settings/#use-i18n .. _documentation for USE_I18N: http://www.djangoproject.com/documentation/settings/#use-i18n

View File

@ -63,7 +63,7 @@ Adds a few conveniences for perfectionists:
last component in the path contains a period. So ``foo.com/bar`` is last component in the path contains a period. So ``foo.com/bar`` is
redirected to ``foo.com/bar/``, but ``foo.com/bar/file.txt`` is passed redirected to ``foo.com/bar/``, but ``foo.com/bar/file.txt`` is passed
through unchanged. through unchanged.
If ``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be If ``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be
redirected to the same URL with a leading "www." redirected to the same URL with a leading "www."
@ -101,6 +101,22 @@ Handles conditional GET operations. If the response has a ``ETag`` or
Also removes the content from any response to a HEAD request and sets the Also removes the content from any response to a HEAD request and sets the
``Date`` and ``Content-Length`` response-headers. ``Date`` and ``Content-Length`` response-headers.
django.middleware.http.SetRemoteAddrFromForwardedFor
----------------------------------------------------
**New in Django development version**
Sets ``request['REMOTE_ADDR']`` based on ``request.['HTTP_X_FORWARDED_FOR']``,
if the latter is set. This is useful if you're sitting behind a reverse proxy
that causes each request's ``REMOTE_ADDR`` to be set to ``127.0.0.1``.
**Important note:** This does NOT validate ``HTTP_X_FORWARDED_FOR``. If you're
not behind a reverse proxy that sets ``HTTP_X_FORWARDED_FOR`` automatically, do
not use this middleware. Anybody can spoof the value of
``HTTP_X_FORWARDED_FOR``, and because this sets ``REMOTE_ADDR`` based on
``HTTP_X_FORWARDED_FOR``, that means anybody can "fake" their IP address. Only
use this when you can absolutely trust the value of ``HTTP_X_FORWARDED_FOR``.
django.contrib.sessions.middleware.SessionMiddleware django.contrib.sessions.middleware.SessionMiddleware
---------------------------------------------------- ----------------------------------------------------

View File

@ -217,7 +217,7 @@ steps:
subdirectory of ``MEDIA_ROOT`` it should upload files. subdirectory of ``MEDIA_ROOT`` it should upload files.
3. All that will be stored in your database is a path to the file 3. All that will be stored in your database is a path to the file
(relative to ``MEDIA_ROOT``). You'll must likely want to use the (relative to ``MEDIA_ROOT``). You'll most likely want to use the
convenience ``get_<fieldname>_url`` function provided by Django. For convenience ``get_<fieldname>_url`` function provided by Django. For
example, if your ``ImageField`` is called ``mug_shot``, you can get example, if your ``ImageField`` is called ``mug_shot``, you can get
the absolute URL to your image in a template with ``{{ the absolute URL to your image in a template with ``{{
@ -230,6 +230,14 @@ For example, say your ``MEDIA_ROOT`` is set to ``'/home/media'``, and
upload a file on Jan. 15, 2007, it will be saved in the directory upload a file on Jan. 15, 2007, it will be saved in the directory
``/home/media/photos/2007/01/15``. ``/home/media/photos/2007/01/15``.
Note that whenever you deal with uploaded files, you should pay close attention
to where you're uploading them and what type of files they are, to avoid
security holes. *Validate all uploaded files* so that you're sure the files are
what you think they are. For example, if you blindly let somebody upload files,
without validation, to a directory that's within your Web server's document
root, then somebody could upload a CGI or PHP script and execute that script by
visiting its URL on your site. Don't allow that.
.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941 .. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941
``FilePathField`` ``FilePathField``
@ -678,8 +686,9 @@ 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 support for strings around model names in ``ForeignKey`` is Note, however, that you can only use strings to refer to models in the same
quite new, and it can be buggy in some cases. models.py file -- you cannot use a string to reference a model in a different
application, or to reference a model that has been imported from elsewhere.
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``
@ -801,7 +810,10 @@ here's how you'd represent that::
As with ``ForeignKey``, a relationship to self can be defined by using the As with ``ForeignKey``, a relationship to self can be defined by using the
string ``'self'`` instead of the model name, and you can refer to as-yet string ``'self'`` instead of the model name, and you can refer to as-yet
undefined models by using a string containing the model name. undefined models by using a string containing the model name. However, you
can only use strings to refer to models in the same models.py file -- you
cannot use a string to reference a model in a different application, or to
reference a model that has been imported from elsewhere.
It's suggested, but not required, that the name of a ``ManyToManyField`` It's suggested, but not required, that the name of a ``ManyToManyField``
(``toppings`` in the example above) be a plural describing the set of related (``toppings`` in the example above) be a plural describing the set of related
@ -1374,6 +1386,41 @@ user searches for ``john lennon``, Django will do the equivalent of this SQL
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%') WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%') AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
**New in Django development version:** For faster and/or more restrictive
searches, prefix the field name with an operator:
``^``
Matches the beginning of the field. For example, if ``search_fields`` is
set to ``['^first_name', '^last_name']`` and a user searches for
``john lennon``, Django will do the equivalent of this SQL ``WHERE``
clause::
WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%')
AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
This query is more efficient than the normal ``'%john%'`` query, because
the database only needs to check the beginning of a column's data, rather
than seeking through the entire column's data. Plus, if the column has an
index on it, some databases may be able to use the index for this query,
even though it's a ``LIKE`` query.
``=``
Matches exactly, case-insensitive. For example, if
``search_fields`` is set to ``['=first_name', '=last_name']`` and
a user searches for ``john lennon``, Django will do the equivalent
of this SQL ``WHERE`` clause::
WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john')
AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')
Note that the query input is split by spaces, so, following this example,
it's not currently not possible to search for all records in which
``first_name`` is exactly ``'john winston'`` (containing a space).
``@``
Performs a full-text match. This is like the default search method but uses
an index. Currently this is only available for MySQL.
Managers Managers
======== ========

View File

@ -259,9 +259,10 @@ an `HttpRequest object`_ as its first argument. For example::
The second difference is that it automatically populates the context with a few The second difference is that it automatically populates the context with a few
variables, according to your `TEMPLATE_CONTEXT_PROCESSORS setting`_. variables, according to your `TEMPLATE_CONTEXT_PROCESSORS setting`_.
The ``TEMPLATE_CONTEXT_PROCESSORS`` setting is a tuple of callables that take a The ``TEMPLATE_CONTEXT_PROCESSORS`` setting is a tuple of callables -- called
request object as their argument and return a dictionary of items to be merged **context processors** -- that take a request object as their argument and
into the context. By default, ``TEMPLATE_CONTEXT_PROCESSORS`` is set to:: return a dictionary of items to be merged into the context. By default,
``TEMPLATE_CONTEXT_PROCESSORS`` is set to::
("django.core.context_processors.auth", ("django.core.context_processors.auth",
"django.core.context_processors.debug", "django.core.context_processors.debug",