Moved RequestSite and get_current_site.

Following the app-loading refactor, these objects must live outside of
django.contrib.sites.models because they must be available without
importing the django.contrib.sites.models module when
django.contrib.sites isn't installed.

Refs #21680. Thanks Carl and Loic for reporting this issue.
This commit is contained in:
Aymeric Augustin 2014-01-25 21:54:25 +01:00
parent ca95f8e435
commit 9ffab9cee1
23 changed files with 137 additions and 76 deletions

View file

@ -6,8 +6,6 @@ The "sites" framework
:synopsis: Lets you operate multiple Web sites from the same database and
Django project
.. currentmodule:: django.contrib.sites.models
Django comes with an optional "sites" framework. It's a hook for associating
objects and functionality to particular Web sites, and it's a holding place for
the domain names and "verbose" names of your Django-powered sites.
@ -15,9 +13,9 @@ the domain names and "verbose" names of your Django-powered sites.
Use it if your single Django installation powers more than one site and you
need to differentiate between those sites in some way.
The whole sites framework is based on a simple model:
The sites framework is mainly based on a simple model:
.. class:: Site
.. class:: models.Site
A model for storing the ``domain`` and ``name`` attributes of a Web site.
The :setting:`SITE_ID` setting specifies the database ID of the
@ -32,7 +30,6 @@ The whole sites framework is based on a simple model:
A human-readable "verbose" name for the Web site.
How you use this is up to you, but Django uses it in a couple of ways
automatically via simple conventions.
@ -80,7 +77,7 @@ This accomplishes several things quite nicely:
The view code that displays a given story just checks to make sure the
requested story is on the current site. It looks something like this::
from django.contrib.sites.models import get_current_site
from django.contrib.sites.shortcuts import get_current_site
def article_detail(request, article_id):
try:
@ -137,7 +134,7 @@ hard-coding is best for hackish fixes that you need done quickly. The
cleaner way of accomplishing the same thing is to check the current site's
domain::
from django.contrib.sites.models import get_current_site
from django.contrib.sites.shortcuts import get_current_site
def my_view(request):
current_site = get_current_site(request)
@ -149,7 +146,8 @@ domain::
pass
This has also the advantage of checking if the sites framework is installed,
and return a :class:`RequestSite` instance if it is not.
and return a :class:`~django.contrib.sites.requests.RequestSite` instance if
it is not.
If you don't have access to the request object, you can use the
``get_current()`` method of the :class:`~django.contrib.sites.models.Site`
@ -185,7 +183,7 @@ current site's :attr:`~django.contrib.sites.models.Site.name` and
Here's an example of what the form-handling view looks like::
from django.contrib.sites.models import get_current_site
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import send_mail
def register_for_newsletter(request):
@ -296,12 +294,10 @@ clear the cache using ``Site.objects.clear_cache()``::
Site.objects.clear_cache()
current_site = Site.objects.get_current()
.. currentmodule:: django.contrib.sites.managers
The ``CurrentSiteManager``
==========================
.. class:: CurrentSiteManager
.. class:: managers.CurrentSiteManager
If :class:`~django.contrib.sites.models.Site` plays a key role in your
application, consider using the helpful
@ -426,8 +422,6 @@ Here's how Django uses the sites framework:
:class:`~django.contrib.sites.models.Site` to work out the domain for the
site that it will redirect to.
.. currentmodule:: django.contrib.sites.models
``RequestSite`` objects
=======================
@ -435,32 +429,50 @@ Here's how Django uses the sites framework:
Some :doc:`django.contrib </ref/contrib/index>` applications take advantage of
the sites framework but are architected in a way that doesn't *require* the
sites framework to be installed in your database. (Some people don't want to, or
just aren't *able* to install the extra database table that the sites framework
requires.) For those cases, the framework provides a
:class:`~django.contrib.sites.models.RequestSite` class, which can be used as a
fallback when the database-backed sites framework is not available.
sites framework to be installed in your database. (Some people don't want to,
or just aren't *able* to install the extra database table that the sites
framework requires.) For those cases, the framework provides a
:class:`django.contrib.sites.requests.RequestSite` class, which can be used as
a fallback when the database-backed sites framework is not available.
.. class:: RequestSite
.. class:: requests.RequestSite
A class that shares the primary interface of
:class:`~django.contrib.sites.models.Site` (i.e., it has
``domain`` and ``name`` attributes) but gets its data from a Django
:class:`~django.http.HttpRequest` object rather than from a database.
The ``save()`` and ``delete()`` methods raise ``NotImplementedError``.
.. method:: __init__(request)
Sets the ``name`` and ``domain`` attributes to the value of
:meth:`~django.http.HttpRequest.get_host`.
.. versionchanged:: 1.7
A :class:`~django.contrib.sites.models.RequestSite` object has a similar
interface to a normal :class:`~django.contrib.sites.models.Site` object, except
its :meth:`~django.contrib.sites.models.RequestSite.__init__()` method takes an
:class:`~django.http.HttpRequest` object. It's able to deduce the
``domain`` and ``name`` by looking at the request's domain. It has ``save()``
and ``delete()`` methods to match the interface of
This class used to be defined in ``django.contrib.sites.models``.
A :class:`~django.contrib.sites.requests.RequestSite` object has a similar
interface to a normal :class:`~django.contrib.sites.models.Site` object,
except its :meth:`~django.contrib.sites.requests.RequestSite.__init__()`
method takes an :class:`~django.http.HttpRequest` object. It's able to deduce
the ``domain`` and ``name`` by looking at the request's domain. It has
``save()`` and ``delete()`` methods to match the interface of
:class:`~django.contrib.sites.models.Site`, but the methods raise
``NotImplementedError``.
:exc:`~exceptions.NotImplementedError`..
``get_current_site`` shortcut
=============================
Finally, to avoid repetitive fallback code, the framework provides a
:func:`django.contrib.sites.shortcut.get_current_site` function.
.. function:: shortcuts.get_current_site
A function that checks if ``django.contrib.sites`` is installed and
returns either the current :class:`~django.contrib.sites.models.Site`
object or a :class:`~django.contrib.sites.requests.RequestSite` object
based on the request.
.. versionchanged:: 1.7
This function used to be defined in ``django.contrib.sites.models``.

View file

@ -131,7 +131,7 @@ into those elements.
representing the current site. This is useful for ``{{ site.domain
}}`` or ``{{ site.name }}``. If you do *not* have the Django sites
framework installed, this will be set to a
:class:`django.contrib.sites.models.RequestSite` object. See the
:class:`~django.contrib.sites.requests.RequestSite` object. See the
:ref:`RequestSite section of the sites framework documentation
<requestsite-objects>` for more.