This middleware replaces the behavior of the APPEND_SLASH setting in the CommonMiddleware. Please set `APPEND_SLASH = False` and `SMART_APPEND_SLASH = True` if you are going to use this middleware.
In your URL patterns, omit the trailing slash for URLs you want accessible without the slash. Include the slash for those URLs you wish to be automatically redirected from an URL with the slash missing.
If a URL pattern exists both with and without a slash, they are treated as two distinct URLs and no redirection is done.
Example
urlpatterns = patterns('some_site.some_app.views',
(r'^test/no_append$','test_no_append'),
(r'^test/append/$','test_append'),
(r'^test/distinct_url$', 'view_one'),
(r'^test/distinct_url/$', 'view_two'), )
Behavior of URLs against the above patterns with SMART_APPEND_SLASH enabled:
http://some_site/test/no_append → test_no_append()
http://some_site/test/no_append/ → 404
http://some_site/test/append → http://some_site/test/append/
http://some_site/test/append/ → test_append()
http://some_site/test/distinct_url → view_one()
http://some_site/test/distinct_url/ → view_two()
This module is also available [in our SVN repository](http://trac.ambitone.com/ambidjangolib/browser/trunk/middleware/common.py).
[A comment on a recent blog entry of mine](http://www.b-list.org/weblog/2008/feb/25/managers/#c63422) asked about a setup where one model has foreign keys pointing at it from several others, and how to write a manager which could attach to any of those models and query seamlessly on the relation regardless of what it's named.
This is a simple example of how to do it: in this case, both `Movie` and `Restaurant` have foreign keys to `Review`, albeit under different names. However, they both use `ReviewedObjectManager` to provide a method for querying objects whose review assigned a certain rating; this works because an instance of `ReviewedObjectManager` "knows" what model it's attached to, and can introspect that model, using [Django's model-introspection API](http://www.b-list.org/weblog/2007/nov/04/working-models/), to find out the correct name to use for the relation, and then use that to perform the query.
Using model introspection in this fashion is something of an advanced topic, but is extremely useful for writing flexible, reusable code.
**Also**, note that the introspection cannot be done in the manager's `__init__()` method -- at that point, `self.model` is still `None` (it won't be filled in with the correct model until a bit later) -- so it's necessary to come up with some way to defer the introspection. In this case, I'm doing it in a method that's called when the relation name is first needed, and which caches the result in an attribute.
- managers
- models
- introspection
Have you ever felt the need to run multiple Django projects on the same memcached server? How about other cache backends? To scope the cache keys, you simply need to prefix. However, since a lot of Django's internals rely on `django.core.cache.cache`, you cannot easily replace it everywhere.
This will automatically upgrade the `django.core.cache.cache` object if `settings.CACHE_PREFIX` is set to a string and the Middleware contains `ScopeCacheMiddleware`.
A thread discussing the merging of this functionality into Django is available on [the dev mailing list](http://groups.google.com/group/django-developers/browse_thread/thread/d45edaafec56da2a).
However, (as of now) nowhere in the thread does anyone mention the reason why this sort of treatment is needed: Many of Django's internal caching helpers use `django.core.cache.cache`, and will then conflict if multiple sites run on the same cache stores.
Example Usage:
>>> from django.conf import settings
>>> from django.core.cache import cache
>>> from scoped_caching import prefix_cache_object
>>> settings.CACHE_PREFIX
'FOO_'
# Do this once a process (e.g. on import or Middleware)
>>> prefix_cache_object(settings.CACHE_PREFIX, cache)
>>> cache.set("pi", 3.14159)
>>> cache.get("pi")
3.14159
>>> cache.get("pi", use_global_namespace=True)
>>> cache.get("FOO_pi", use_global_namespace=True)
3.14159
>>> cache.set("FOO_e", 2.71828, use_global_namespace=True)
>>> cache.get("e")
2.71828
To Install: Simply add `ScopeCacheMiddleware` as a middleware and define `settings.CACHE_PREFIX` and enjoy!
- middleware
- cache
- namespace