Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

BACKWARDS-INCOMPATIBLE CHANGE -- Moved flatpages and redirects to sta…

…ndalone 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
  • Loading branch information...
commit 1b035c35d9bb288589d813393e635bc9546c914b 1 parent a11a1d5
@adrianholovaty adrianholovaty authored
View
3  django/conf/global_settings.py
@@ -135,9 +135,6 @@
# is an admin.
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.
IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf')
IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')
View
0  django/contrib/flatpages/__init__.py
No changes.
View
15 django/contrib/flatpages/middleware.py
@@ -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
View
1  django/contrib/flatpages/models/__init__.py
@@ -0,0 +1 @@
+__all__ = ['flatpages']
View
33 django/contrib/flatpages/models/flatpages.py
@@ -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
View
2  django/conf/urls/flatfiles.py → django/contrib/flatpages/urls.py
@@ -1,5 +1,5 @@
from django.conf.urls.defaults import *
urlpatterns = patterns('django.views',
- (r'^(?P<url>.*)$', 'core.flatfiles.flat_file'),
+ (r'^(?P<url>.*)$', 'django.contrib.flatpages.views.flatpage'),
)
View
22 django/views/core/flatfiles.py → django/contrib/flatpages/views.py
@@ -1,28 +1,28 @@
from django.core import template_loader
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.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,
- or `flatfiles/default` if template_name is not defined.
+ or `flatpages/default` if template_name is not defined.
Context:
- flatfile
- `flatfiles.flatfiles` object
+ flatpage
+ `flatpages.flatpages` object
"""
if not url.startswith('/'):
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
# 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
return redirect_to_login(request.path)
if f.template_name:
@@ -30,6 +30,6 @@ def flat_file(request, url):
else:
t = template_loader.get_template(DEFAULT_TEMPLATE)
c = DjangoContext(request, {
- 'flatfile': f,
+ 'flatpage': f,
})
return HttpResponse(t.render(c))
View
0  django/contrib/redirects/__init__.py
No changes.
View
27 django/contrib/redirects/middleware.py
@@ -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
View
1  django/contrib/redirects/models/__init__.py
@@ -0,0 +1 @@
+__all__ = ['redirects']
View
23 django/contrib/redirects/models/redirects.py
@@ -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)
View
11 django/middleware/common.py
@@ -1,8 +1,6 @@
from django.conf import settings
-from django.core import exceptions
from django.utils import httpwrappers
from django.core.mail import mail_managers
-from django.views.core.flatfiles import flat_file
import md5, os
class CommonMiddleware:
@@ -17,9 +15,6 @@ class CommonMiddleware:
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
the entire page content and Not Modified responses will be returned
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):
@@ -55,12 +50,6 @@ def process_request(self, request):
def process_response(self, request, response):
"Check for a flat page (for 404s) and calculate the Etag, if needed."
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 the referrer was from an internal link or a non-search-engine site,
# send a note to the managers.
View
52 django/models/core.py
@@ -1,6 +1,6 @@
import base64, md5, random, sys
import cPickle as pickle
-from django.core import meta, validators
+from django.core import meta
from django.utils.translation import gettext_lazy as _
class Site(meta.Model):
@@ -63,56 +63,6 @@ def get_object_for_this_type(self, **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):
session_key = meta.CharField(_('session key'), maxlength=40, primary_key=True)
session_data = meta.TextField(_('session data'))
View
39 django/views/defaults.py
@@ -4,7 +4,7 @@
from django.utils import httpwrappers
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.
try:
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()
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
+
+ # 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
+
+ # Next, look for a many-to-one relationship to sites
elif hasattr(obj, 'get_site'):
try:
object_domain = obj.get_site().domain
@@ -55,34 +55,15 @@ def page_not_found(request):
Templates: `404`
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')
- c = Context()
- return httpwrappers.HttpResponseNotFound(t.render(c))
+ return httpwrappers.HttpResponseNotFound(t.render(Context()))
def server_error(request):
"""
- 500 Error handler
+ 500 error handler.
Templates: `500`
Context: None
"""
t = loader.get_template('500')
- c = Context()
- return httpwrappers.HttpResponseServerError(t.render(c))
+ return httpwrappers.HttpResponseServerError(t.render(Context()))
View
114 docs/flatpages.txt
@@ -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>
View
3  docs/legacy_databases.txt
@@ -69,10 +69,7 @@ following names:
* ``sites``
* ``packages``
* ``content_types``
- * ``redirects``
- * ``flatfiles``
* ``core_sessions``
- * ``flatfiles_sites``
* ``auth_permissions``
* ``auth_groups``
* ``auth_users``
View
4 docs/middleware.txt
@@ -72,10 +72,6 @@ Adds a few conveniences for perfectionists:
MD5-hashing the page content, and it'll take care of sending
``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
-------------------------------------
View
2  docs/model-api.txt
@@ -831,7 +831,7 @@ object, which takes the following parameters. All are optional.
"click to expand" link. Fieldsets with the ``wide`` style will be
given extra horizontal space.
- For example (taken from the ``core.flatfiles`` model)::
+ For example (taken from the ``django.contrib.flatpages`` model)::
fields = (
(None, {
View
72 docs/redirects.txt
@@ -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/
View
8 docs/settings.txt
@@ -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``
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/
.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
.. _session docs: http://www.djangoproject.com/documentation/sessions/
View
1  docs/url_dispatch.txt
@@ -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'^comments/', include('django.contrib.comments.urls.comments')),
(r'^rss/', include('django.conf.urls.rss')),
- (r'', include('django.conf.urls.flatfiles')),
)
Note that an included URLconf receives any captured parameters from parent
Please sign in to comment.
Something went wrong with that request. Please try again.