BACKWARDS-INCOMPATIBLE CHANGE -- Moved flatpages and redirects to standalone apps in django.contrib that are NOT installed by default. See http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges for full migration information.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@1166 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
a11a1d5e16
commit
1b035c35d9
|
@ -135,9 +135,6 @@ ALLOWED_INCLUDE_ROOTS = ()
|
||||||
# is an admin.
|
# is an admin.
|
||||||
ADMIN_FOR = ()
|
ADMIN_FOR = ()
|
||||||
|
|
||||||
# Whether to check the flat-pages table as a last resort for all 404 errors.
|
|
||||||
USE_FLAT_PAGES = True
|
|
||||||
|
|
||||||
# 404s that may be ignored.
|
# 404s that may be ignored.
|
||||||
IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf')
|
IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf')
|
||||||
IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')
|
IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
from django.contrib.flatpages.views import flatpage
|
||||||
|
from django.conf.settings import DEBUG
|
||||||
|
|
||||||
|
class FlatpageFallbackMiddleware:
|
||||||
|
def process_response(self, request, response):
|
||||||
|
if response.status_code != 404:
|
||||||
|
return response # No need to check for a flatpage for non-404 responses.
|
||||||
|
try:
|
||||||
|
return flatpage(request, request.path)
|
||||||
|
# Return the original response if any errors happened. Because this
|
||||||
|
# is a middleware, we can't assume the errors will be caught elsewhere.
|
||||||
|
except:
|
||||||
|
if DEBUG:
|
||||||
|
raise
|
||||||
|
return response
|
|
@ -0,0 +1 @@
|
||||||
|
__all__ = ['flatpages']
|
|
@ -0,0 +1,33 @@
|
||||||
|
from django.core import meta, validators
|
||||||
|
from django.models.core import Site
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
class FlatPage(meta.Model):
|
||||||
|
url = meta.CharField(_('URL'), maxlength=100, validator_list=[validators.isAlphaNumericURL],
|
||||||
|
help_text=_("Example: '/about/contact/'. Make sure to have leading and trailing slashes."))
|
||||||
|
title = meta.CharField(_('title'), maxlength=200)
|
||||||
|
content = meta.TextField(_('content'))
|
||||||
|
enable_comments = meta.BooleanField(_('enable comments'))
|
||||||
|
template_name = meta.CharField(_('template name'), maxlength=70, blank=True,
|
||||||
|
help_text=_("Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'."))
|
||||||
|
registration_required = meta.BooleanField(_('registration required'), help_text=_("If this is checked, only logged-in users will be able to view the page."))
|
||||||
|
sites = meta.ManyToManyField(Site)
|
||||||
|
class META:
|
||||||
|
db_table = 'django_flatpages'
|
||||||
|
verbose_name = _('flat page')
|
||||||
|
verbose_name_plural = _('flat pages')
|
||||||
|
ordering = ('url',)
|
||||||
|
admin = meta.Admin(
|
||||||
|
fields = (
|
||||||
|
(None, {'fields': ('url', 'title', 'content', 'sites')}),
|
||||||
|
('Advanced options', {'classes': 'collapse', 'fields': ('enable_comments', 'registration_required', 'template_name')}),
|
||||||
|
),
|
||||||
|
list_filter = ('sites',),
|
||||||
|
search_fields = ('url', 'title'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "%s -- %s" % (self.url, self.title)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return self.url
|
|
@ -1,5 +1,5 @@
|
||||||
from django.conf.urls.defaults import *
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
urlpatterns = patterns('django.views',
|
urlpatterns = patterns('django.views',
|
||||||
(r'^(?P<url>.*)$', 'core.flatfiles.flat_file'),
|
(r'^(?P<url>.*)$', 'django.contrib.flatpages.views.flatpage'),
|
||||||
)
|
)
|
|
@ -1,28 +1,28 @@
|
||||||
from django.core import template_loader
|
from django.core import template_loader
|
||||||
from django.core.extensions import get_object_or_404, DjangoContext
|
from django.core.extensions import get_object_or_404, DjangoContext
|
||||||
from django.models.core import flatfiles
|
from django.models.flatpages import flatpages
|
||||||
from django.utils.httpwrappers import HttpResponse
|
from django.utils.httpwrappers import HttpResponse
|
||||||
from django.conf.settings import SITE_ID
|
from django.conf.settings import SITE_ID
|
||||||
|
|
||||||
DEFAULT_TEMPLATE = 'flatfiles/default'
|
DEFAULT_TEMPLATE = 'flatpages/default'
|
||||||
|
|
||||||
def flat_file(request, url):
|
def flatpage(request, url):
|
||||||
"""
|
"""
|
||||||
Flat file view
|
Flat page view.
|
||||||
|
|
||||||
Models: `core.flatfiles`
|
Models: `flatpages.flatpages`
|
||||||
Templates: Uses the template defined by the ``template_name`` field,
|
Templates: Uses the template defined by the ``template_name`` field,
|
||||||
or `flatfiles/default` if template_name is not defined.
|
or `flatpages/default` if template_name is not defined.
|
||||||
Context:
|
Context:
|
||||||
flatfile
|
flatpage
|
||||||
`flatfiles.flatfiles` object
|
`flatpages.flatpages` object
|
||||||
"""
|
"""
|
||||||
if not url.startswith('/'):
|
if not url.startswith('/'):
|
||||||
url = "/" + url
|
url = "/" + url
|
||||||
f = get_object_or_404(flatfiles, url__exact=url, sites__id__exact=SITE_ID)
|
f = get_object_or_404(flatpages, url__exact=url, sites__id__exact=SITE_ID)
|
||||||
# If registration is required for accessing this page, and the user isn't
|
# If registration is required for accessing this page, and the user isn't
|
||||||
# logged in, redirect to the login page.
|
# logged in, redirect to the login page.
|
||||||
if request.user.is_anonymous() and f.registration_required:
|
if f.registration_required and request.user.is_anonymous():
|
||||||
from django.views.auth.login import redirect_to_login
|
from django.views.auth.login import redirect_to_login
|
||||||
return redirect_to_login(request.path)
|
return redirect_to_login(request.path)
|
||||||
if f.template_name:
|
if f.template_name:
|
||||||
|
@ -30,6 +30,6 @@ def flat_file(request, url):
|
||||||
else:
|
else:
|
||||||
t = template_loader.get_template(DEFAULT_TEMPLATE)
|
t = template_loader.get_template(DEFAULT_TEMPLATE)
|
||||||
c = DjangoContext(request, {
|
c = DjangoContext(request, {
|
||||||
'flatfile': f,
|
'flatpage': f,
|
||||||
})
|
})
|
||||||
return HttpResponse(t.render(c))
|
return HttpResponse(t.render(c))
|
|
@ -0,0 +1,27 @@
|
||||||
|
from django.models.redirects import redirects
|
||||||
|
from django.utils import httpwrappers
|
||||||
|
from django.conf.settings import APPEND_SLASH, SITE_ID
|
||||||
|
|
||||||
|
class RedirectFallbackMiddleware:
|
||||||
|
def process_response(self, request, response):
|
||||||
|
if response.status_code != 404:
|
||||||
|
return response # No need to check for a redirect for non-404 responses.
|
||||||
|
path = request.get_full_path()
|
||||||
|
try:
|
||||||
|
r = redirects.get_object(site__id__exact=SITE_ID, old_path__exact=path)
|
||||||
|
except redirects.RedirectDoesNotExist:
|
||||||
|
r = None
|
||||||
|
if r is None and APPEND_SLASH:
|
||||||
|
# Try removing the trailing slash.
|
||||||
|
try:
|
||||||
|
r = redirects.get_object(site__id__exact=SITE_ID,
|
||||||
|
old_path__exact=path[:path.rfind('/')]+path[path.rfind('/')+1:])
|
||||||
|
except redirects.RedirectDoesNotExist:
|
||||||
|
pass
|
||||||
|
if r is not None:
|
||||||
|
if r == '':
|
||||||
|
return httpwrappers.HttpResponseGone()
|
||||||
|
return httpwrappers.HttpResponseRedirect(r.new_path)
|
||||||
|
|
||||||
|
# No redirect was found. Return the response.
|
||||||
|
return response
|
|
@ -0,0 +1 @@
|
||||||
|
__all__ = ['redirects']
|
|
@ -0,0 +1,23 @@
|
||||||
|
from django.core import meta
|
||||||
|
from django.models.core import Site
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
class Redirect(meta.Model):
|
||||||
|
site = meta.ForeignKey(Site, radio_admin=meta.VERTICAL)
|
||||||
|
old_path = meta.CharField(_('redirect from'), maxlength=200, db_index=True,
|
||||||
|
help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'."))
|
||||||
|
new_path = meta.CharField(_('redirect to'), maxlength=200, blank=True,
|
||||||
|
help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'."))
|
||||||
|
class META:
|
||||||
|
verbose_name = _('redirect')
|
||||||
|
verbose_name_plural = _('redirects')
|
||||||
|
db_table = 'django_redirects'
|
||||||
|
unique_together=(('site', 'old_path'),)
|
||||||
|
ordering = ('old_path',)
|
||||||
|
admin = meta.Admin(
|
||||||
|
list_filter = ('site',),
|
||||||
|
search_fields = ('old_path', 'new_path'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "%s ---> %s" % (self.old_path, self.new_path)
|
|
@ -1,8 +1,6 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core import exceptions
|
|
||||||
from django.utils import httpwrappers
|
from django.utils import httpwrappers
|
||||||
from django.core.mail import mail_managers
|
from django.core.mail import mail_managers
|
||||||
from django.views.core.flatfiles import flat_file
|
|
||||||
import md5, os
|
import md5, os
|
||||||
|
|
||||||
class CommonMiddleware:
|
class CommonMiddleware:
|
||||||
|
@ -17,9 +15,6 @@ class CommonMiddleware:
|
||||||
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
|
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
|
||||||
the entire page content and Not Modified responses will be returned
|
the entire page content and Not Modified responses will be returned
|
||||||
appropriately.
|
appropriately.
|
||||||
|
|
||||||
- Flat files: For 404 responses, a flat file matching the given path
|
|
||||||
will be looked up and used if found.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
|
@ -55,12 +50,6 @@ class CommonMiddleware:
|
||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
"Check for a flat page (for 404s) and calculate the Etag, if needed."
|
"Check for a flat page (for 404s) and calculate the Etag, if needed."
|
||||||
if response.status_code == 404:
|
if response.status_code == 404:
|
||||||
if settings.USE_FLAT_PAGES:
|
|
||||||
try:
|
|
||||||
return flat_file(request, request.path)
|
|
||||||
except exceptions.Http404:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if settings.SEND_BROKEN_LINK_EMAILS:
|
if settings.SEND_BROKEN_LINK_EMAILS:
|
||||||
# If the referrer was from an internal link or a non-search-engine site,
|
# If the referrer was from an internal link or a non-search-engine site,
|
||||||
# send a note to the managers.
|
# send a note to the managers.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import base64, md5, random, sys
|
import base64, md5, random, sys
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
from django.core import meta, validators
|
from django.core import meta
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
class Site(meta.Model):
|
class Site(meta.Model):
|
||||||
|
@ -63,56 +63,6 @@ class ContentType(meta.Model):
|
||||||
"""
|
"""
|
||||||
return self.get_model_module().get_object(**kwargs)
|
return self.get_model_module().get_object(**kwargs)
|
||||||
|
|
||||||
class Redirect(meta.Model):
|
|
||||||
site = meta.ForeignKey(Site, radio_admin=meta.VERTICAL)
|
|
||||||
old_path = meta.CharField(_('redirect from'), maxlength=200, db_index=True,
|
|
||||||
help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'."))
|
|
||||||
new_path = meta.CharField(_('redirect to'), maxlength=200, blank=True,
|
|
||||||
help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'."))
|
|
||||||
class META:
|
|
||||||
verbose_name = _('redirect')
|
|
||||||
verbose_name_plural = _('redirects')
|
|
||||||
db_table = 'redirects'
|
|
||||||
unique_together=(('site', 'old_path'),)
|
|
||||||
ordering = ('old_path',)
|
|
||||||
admin = meta.Admin(
|
|
||||||
list_filter = ('site',),
|
|
||||||
search_fields = ('old_path', 'new_path'),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "%s ---> %s" % (self.old_path, self.new_path)
|
|
||||||
|
|
||||||
class FlatFile(meta.Model):
|
|
||||||
url = meta.CharField(_('URL'), maxlength=100, validator_list=[validators.isAlphaNumericURL],
|
|
||||||
help_text=_("Example: '/about/contact/'. Make sure to have leading and trailing slashes."))
|
|
||||||
title = meta.CharField(_('title'), maxlength=200)
|
|
||||||
content = meta.TextField(_('content'))
|
|
||||||
enable_comments = meta.BooleanField(_('enable comments'))
|
|
||||||
template_name = meta.CharField(_('template name'), maxlength=70, blank=True,
|
|
||||||
help_text=_("Example: 'flatfiles/contact_page'. If this isn't provided, the system will use 'flatfiles/default'."))
|
|
||||||
registration_required = meta.BooleanField(_('registration required'), help_text=_("If this is checked, only logged-in users will be able to view the page."))
|
|
||||||
sites = meta.ManyToManyField(Site)
|
|
||||||
class META:
|
|
||||||
db_table = 'flatfiles'
|
|
||||||
verbose_name = _('flat page')
|
|
||||||
verbose_name_plural = _('flat pages')
|
|
||||||
ordering = ('url',)
|
|
||||||
admin = meta.Admin(
|
|
||||||
fields = (
|
|
||||||
(None, {'fields': ('url', 'title', 'content', 'sites')}),
|
|
||||||
('Advanced options', {'classes': 'collapse', 'fields': ('enable_comments', 'registration_required', 'template_name')}),
|
|
||||||
),
|
|
||||||
list_filter = ('sites',),
|
|
||||||
search_fields = ('url', 'title'),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "%s -- %s" % (self.url, self.title)
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return self.url
|
|
||||||
|
|
||||||
class Session(meta.Model):
|
class Session(meta.Model):
|
||||||
session_key = meta.CharField(_('session key'), maxlength=40, primary_key=True)
|
session_key = meta.CharField(_('session key'), maxlength=40, primary_key=True)
|
||||||
session_data = meta.TextField(_('session data'))
|
session_data = meta.TextField(_('session data'))
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.models.core import sites, contenttypes
|
||||||
from django.utils import httpwrappers
|
from django.utils import httpwrappers
|
||||||
|
|
||||||
def shortcut(request, content_type_id, object_id):
|
def shortcut(request, content_type_id, object_id):
|
||||||
"""Redirect to an object's page based on a content-type ID and an object ID"""
|
"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.
|
# Look up the object, making sure it's got a get_absolute_url() function.
|
||||||
try:
|
try:
|
||||||
content_type = contenttypes.get_object(pk=content_type_id)
|
content_type = contenttypes.get_object(pk=content_type_id)
|
||||||
|
@ -15,23 +15,23 @@ def shortcut(request, content_type_id, object_id):
|
||||||
absurl = obj.get_absolute_url()
|
absurl = obj.get_absolute_url()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise Http404, "%s objects don't have get_absolute_url() methods" % content_type.name
|
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
|
# Try to figure out the object's domain, so we can do a cross-site redirect
|
||||||
# if necessary
|
# if necessary.
|
||||||
|
|
||||||
# If the object actually defines a domain, we're done.
|
# If the object actually defines a domain, we're done.
|
||||||
if absurl.startswith('http://'):
|
if absurl.startswith('http://'):
|
||||||
return httpwrappers.HttpResponseRedirect(absurl)
|
return httpwrappers.HttpResponseRedirect(absurl)
|
||||||
|
|
||||||
object_domain = None
|
object_domain = None
|
||||||
|
|
||||||
# Next, look for an many-to-many relationship to sites
|
# Next, look for an many-to-many relationship to sites
|
||||||
if hasattr(obj, 'get_site_list'):
|
if hasattr(obj, 'get_site_list'):
|
||||||
site_list = obj.get_site_list()
|
site_list = obj.get_site_list()
|
||||||
if site_list:
|
if site_list:
|
||||||
object_domain = site_list[0].domain
|
object_domain = site_list[0].domain
|
||||||
|
|
||||||
# Next, look for a many-to-one relationship to sites
|
# Next, look for a many-to-one relationship to sites
|
||||||
elif hasattr(obj, 'get_site'):
|
elif hasattr(obj, 'get_site'):
|
||||||
try:
|
try:
|
||||||
object_domain = obj.get_site().domain
|
object_domain = obj.get_site().domain
|
||||||
|
@ -55,34 +55,15 @@ def page_not_found(request):
|
||||||
Templates: `404`
|
Templates: `404`
|
||||||
Context: None
|
Context: None
|
||||||
"""
|
"""
|
||||||
from django.models.core import redirects
|
|
||||||
from django.conf.settings import APPEND_SLASH, SITE_ID
|
|
||||||
path = request.get_full_path()
|
|
||||||
try:
|
|
||||||
r = redirects.get_object(site__id__exact=SITE_ID, old_path__exact=path)
|
|
||||||
except redirects.RedirectDoesNotExist:
|
|
||||||
r = None
|
|
||||||
if r is None and APPEND_SLASH:
|
|
||||||
# Try removing the trailing slash.
|
|
||||||
try:
|
|
||||||
r = redirects.get_object(site__id__exact=SITE_ID, old_path__exact=path[:path.rfind('/')]+path[path.rfind('/')+1:])
|
|
||||||
except redirects.RedirectDoesNotExist:
|
|
||||||
pass
|
|
||||||
if r is not None:
|
|
||||||
if r == '':
|
|
||||||
return httpwrappers.HttpResponseGone()
|
|
||||||
return httpwrappers.HttpResponseRedirect(r.new_path)
|
|
||||||
t = loader.get_template('404')
|
t = loader.get_template('404')
|
||||||
c = Context()
|
return httpwrappers.HttpResponseNotFound(t.render(Context()))
|
||||||
return httpwrappers.HttpResponseNotFound(t.render(c))
|
|
||||||
|
|
||||||
def server_error(request):
|
def server_error(request):
|
||||||
"""
|
"""
|
||||||
500 Error handler
|
500 error handler.
|
||||||
|
|
||||||
Templates: `500`
|
Templates: `500`
|
||||||
Context: None
|
Context: None
|
||||||
"""
|
"""
|
||||||
t = loader.get_template('500')
|
t = loader.get_template('500')
|
||||||
c = Context()
|
return httpwrappers.HttpResponseServerError(t.render(Context()))
|
||||||
return httpwrappers.HttpResponseServerError(t.render(c))
|
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
=================
|
||||||
|
The flatpages app
|
||||||
|
=================
|
||||||
|
|
||||||
|
Django comes with an optional "flatpages" application. It lets you store simple
|
||||||
|
"flat" HTML content in a database and handles the management for you.
|
||||||
|
|
||||||
|
A flatpage is a simple object with a URL, title and content. Use it for
|
||||||
|
one-off, special-case pages, such as "About" or "Privacy Policy" pages, that
|
||||||
|
you want to store in a database but for which you don't want to develop a
|
||||||
|
custom Django application.
|
||||||
|
|
||||||
|
A flatpage can use a custom template or a default, systemwide flatpage
|
||||||
|
template. It can be associated with one, or multiple, sites.
|
||||||
|
|
||||||
|
Here are some examples of flatpages on Django-powered sites:
|
||||||
|
|
||||||
|
* http://www.chicagocrime.org/about/
|
||||||
|
* http://www.lawrence.com/about/contact/
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
To install the flatpages app, follow these two steps:
|
||||||
|
|
||||||
|
1. Add ``"django.contrib.flatpages"`` to your INSTALLED_APPS_ setting.
|
||||||
|
2. Add ``"django.contrib.flatpages.middleware.FlatpageFallbackMiddleware"``
|
||||||
|
to your MIDDLEWARE_CLASSES_ setting.
|
||||||
|
3. Run the command ``django-admin.py install flatpages``.
|
||||||
|
|
||||||
|
.. _INSTALLED_APPS: http://www.djangoproject.com/documentation/settings/#installed-apps
|
||||||
|
.. _MIDDLEWARE_CLASSES: http://www.djangoproject.com/documentation/settings/#middleware-classes
|
||||||
|
|
||||||
|
How it works
|
||||||
|
============
|
||||||
|
|
||||||
|
``django-admin.py install flatpages`` creates two tables in your database:
|
||||||
|
``django_flatpages`` and ``django_flatpages_sites``. ``django_flatpages`` is a
|
||||||
|
simple lookup table that essentially maps a URL to a title and bunch of text
|
||||||
|
content. ``django_flatpages_sites`` associates a flatpage with a site.
|
||||||
|
|
||||||
|
The ``FlatpageFallbackMiddleware`` does all of the work. Each time any Django
|
||||||
|
application raises a 404 error, this middleware checks the flatpages database
|
||||||
|
for the requested URL as a last resort. Specifically, it checks for a flatpage
|
||||||
|
with the given URL with a site ID that corresponds to the SITE_ID_ setting.
|
||||||
|
|
||||||
|
If it finds a match, it follows this algorithm:
|
||||||
|
|
||||||
|
* If the flatpage has a custom template, it loads that template. Otherwise,
|
||||||
|
it loads the template ``flatpages/default``.
|
||||||
|
* It passes that template a single context variable, ``flatpage``, which is
|
||||||
|
the flatpage object. It uses DjangoContext_ in rendering the template.
|
||||||
|
|
||||||
|
If it doesn't find a match, the request continues to be processed as usual.
|
||||||
|
|
||||||
|
The middleware only gets activated for 404s -- not for 500s or responses of any
|
||||||
|
other status code.
|
||||||
|
|
||||||
|
Note that the order of ``MIDDLEWARE_CLASSES`` matters. Generally, you can put
|
||||||
|
``FlatpageFallbackMiddleware`` at the end of the list, because it's a last
|
||||||
|
resort.
|
||||||
|
|
||||||
|
For more on middleware, read the `middleware docs`_.
|
||||||
|
|
||||||
|
.. _SITE_ID: http://www.djangoproject.com/documentation/settings/#site-id
|
||||||
|
.. _DjangoContext: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-djangocontext
|
||||||
|
.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
|
||||||
|
|
||||||
|
How to add, change and delete flatpages
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
Via the admin interface
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
If you've activated the automatic Django admin interface, you should see a
|
||||||
|
"Flatpages" section on the admin index page. Edit flatpages as you edit any
|
||||||
|
other object in the system.
|
||||||
|
|
||||||
|
Via the Python API
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Flatpages are represented by a standard `Django model`_, which lives in
|
||||||
|
`django/contrib/flatpages/models/flatpages.py`_. You can access flatpage
|
||||||
|
objects via the `Django database API`_.
|
||||||
|
|
||||||
|
.. _Django model: http://www.djangoproject.com/documentation/model_api/
|
||||||
|
.. _django/contrib/flatpages/models/flatpages.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/flatpages/models/flatpages.py
|
||||||
|
.. _Django database API: http://www.djangoproject.com/documentation/db_api/
|
||||||
|
|
||||||
|
Flatpage templates
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, flatpages are rendered via the template ``flatpages/default``, but
|
||||||
|
you can override that for a particular flatpage.
|
||||||
|
|
||||||
|
Creating the ``flatpages/default`` template is your responsibility; in your
|
||||||
|
template directory, just create a ``flatpages`` directory containing a file
|
||||||
|
``default.html``.
|
||||||
|
|
||||||
|
Flatpage templates are passed a single context variable, ``flatpage``, which is
|
||||||
|
the flatpage object.
|
||||||
|
|
||||||
|
Here's a sample ``flatpages/default`` template::
|
||||||
|
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{ flatpage.title }}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{{ flatpage.content }}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -69,10 +69,7 @@ following names:
|
||||||
* ``sites``
|
* ``sites``
|
||||||
* ``packages``
|
* ``packages``
|
||||||
* ``content_types``
|
* ``content_types``
|
||||||
* ``redirects``
|
|
||||||
* ``flatfiles``
|
|
||||||
* ``core_sessions``
|
* ``core_sessions``
|
||||||
* ``flatfiles_sites``
|
|
||||||
* ``auth_permissions``
|
* ``auth_permissions``
|
||||||
* ``auth_groups``
|
* ``auth_groups``
|
||||||
* ``auth_users``
|
* ``auth_users``
|
||||||
|
|
|
@ -72,10 +72,6 @@ Adds a few conveniences for perfectionists:
|
||||||
MD5-hashing the page content, and it'll take care of sending
|
MD5-hashing the page content, and it'll take care of sending
|
||||||
``Not Modified`` responses, if appropriate.
|
``Not Modified`` responses, if appropriate.
|
||||||
|
|
||||||
* Handles flat pages. Every time Django encounters a 404 -- either within
|
|
||||||
a view or as a result of no URLconfs matching -- it will check the
|
|
||||||
database of flat pages based on the current URL.
|
|
||||||
|
|
||||||
django.middleware.doc.XViewMiddleware
|
django.middleware.doc.XViewMiddleware
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -831,7 +831,7 @@ object, which takes the following parameters. All are optional.
|
||||||
"click to expand" link. Fieldsets with the ``wide`` style will be
|
"click to expand" link. Fieldsets with the ``wide`` style will be
|
||||||
given extra horizontal space.
|
given extra horizontal space.
|
||||||
|
|
||||||
For example (taken from the ``core.flatfiles`` model)::
|
For example (taken from the ``django.contrib.flatpages`` model)::
|
||||||
|
|
||||||
fields = (
|
fields = (
|
||||||
(None, {
|
(None, {
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
=================
|
||||||
|
The redirects app
|
||||||
|
=================
|
||||||
|
|
||||||
|
Django comes with an optional redirects application. It lets you store simple
|
||||||
|
redirects in a database and handles the redirecting for you.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
To install the redirects app, follow these two steps:
|
||||||
|
|
||||||
|
1. Add ``"django.contrib.redirects"`` to your INSTALLED_APPS_ setting.
|
||||||
|
2. Add ``"django.contrib.redirects.middleware.RedirectFallbackMiddleware"``
|
||||||
|
to your MIDDLEWARE_CLASSES_ setting.
|
||||||
|
3. Run the command ``django-admin.py install redirects``.
|
||||||
|
|
||||||
|
.. _INSTALLED_APPS: http://www.djangoproject.com/documentation/settings/#installed-apps
|
||||||
|
.. _MIDDLEWARE_CLASSES: http://www.djangoproject.com/documentation/settings/#middleware-classes
|
||||||
|
|
||||||
|
How it works
|
||||||
|
============
|
||||||
|
|
||||||
|
``django-admin.py install redirects`` creates a ``django_redirects`` table in
|
||||||
|
your database. This is a simple lookup table with ``site_id``, ``old_path`` and
|
||||||
|
``new_path`` fields.
|
||||||
|
|
||||||
|
The ``RedirectFallbackMiddleware`` does all of the work. Each time any Django
|
||||||
|
application raises a 404 error, this middleware checks the redirects database
|
||||||
|
for the requested URL as a last resort. Specifically, it checks for a redirect
|
||||||
|
with the given ``old_path`` with a site ID that corresponds to the SITE_ID_
|
||||||
|
setting.
|
||||||
|
|
||||||
|
* If it finds a match, and ``new_path`` is not empty, it redirects to
|
||||||
|
``new_path``.
|
||||||
|
* If it finds a match, and ``new_path`` is empty, it sends a 410 ("Gone")
|
||||||
|
HTTP header and empty (content-less) response.
|
||||||
|
* If it doesn't find a match, the request continues to be processed as
|
||||||
|
usual.
|
||||||
|
|
||||||
|
The middleware only gets activated for 404s -- not for 500s or responses of any
|
||||||
|
other status code.
|
||||||
|
|
||||||
|
Note that the order of ``MIDDLEWARE_CLASSES`` matters. Generally, you can put
|
||||||
|
``RedirectFallbackMiddleware`` at the end of the list, because it's a last
|
||||||
|
resort.
|
||||||
|
|
||||||
|
For more on middleware, read the `middleware docs`_.
|
||||||
|
|
||||||
|
.. _SITE_ID: http://www.djangoproject.com/documentation/settings/#site-id
|
||||||
|
.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
|
||||||
|
|
||||||
|
How to add, change and delete redirects
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
Via the admin interface
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
If you've activated the automatic Django admin interface, you should see a
|
||||||
|
"Redirects" section on the admin index page. Edit redirects as you edit any
|
||||||
|
other object in the system.
|
||||||
|
|
||||||
|
Via the Python API
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Redirects are represented by a standard `Django model`_, which lives in
|
||||||
|
`django/contrib/redirects/models/redirects.py`_. You can access redirect
|
||||||
|
objects via the `Django database API`_.
|
||||||
|
|
||||||
|
.. _Django model: http://www.djangoproject.com/documentation/model_api/
|
||||||
|
.. _django/contrib/redirects/models/redirects.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/redirects/models/redirects.py
|
||||||
|
.. _Django database API: http://www.djangoproject.com/documentation/db_api/
|
|
@ -562,14 +562,6 @@ A boolean that specifies whether to output the "Etag" header. This saves
|
||||||
bandwidth but slows down performance. This is only used if ``CommonMiddleware``
|
bandwidth but slows down performance. This is only used if ``CommonMiddleware``
|
||||||
is installed (see the `middleware docs`_).
|
is installed (see the `middleware docs`_).
|
||||||
|
|
||||||
USE_FLAT_PAGES
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Default: ``True``
|
|
||||||
|
|
||||||
Whether to check the flat-pages table as a last resort for all 404 errors. This
|
|
||||||
is only used if ``CommonMiddleware`` is installed (see the `middleware docs`_).
|
|
||||||
|
|
||||||
.. _cache docs: http://www.djangoproject.com/documentation/cache/
|
.. _cache docs: http://www.djangoproject.com/documentation/cache/
|
||||||
.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
|
.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
|
||||||
.. _session docs: http://www.djangoproject.com/documentation/sessions/
|
.. _session docs: http://www.djangoproject.com/documentation/sessions/
|
||||||
|
|
|
@ -56,7 +56,6 @@ module that will be used for the entire site. Here's the URLconf for the
|
||||||
(r'^documentation/', include('django_website.apps.docs.urls.docs')),
|
(r'^documentation/', include('django_website.apps.docs.urls.docs')),
|
||||||
(r'^comments/', include('django.contrib.comments.urls.comments')),
|
(r'^comments/', include('django.contrib.comments.urls.comments')),
|
||||||
(r'^rss/', include('django.conf.urls.rss')),
|
(r'^rss/', include('django.conf.urls.rss')),
|
||||||
(r'', include('django.conf.urls.flatfiles')),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Note that an included URLconf receives any captured parameters from parent
|
Note that an included URLconf receives any captured parameters from parent
|
||||||
|
|
Loading…
Reference in New Issue