浏览代码

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.
Aymeric Augustin 11 年之前
父节点
当前提交
9ffab9cee1

+ 1 - 1
django/contrib/auth/forms.py

@@ -16,7 +16,7 @@ from django.contrib.auth import authenticate, get_user_model
 from django.contrib.auth.models import User
 from django.contrib.auth.models import User
 from django.contrib.auth.hashers import UNUSABLE_PASSWORD_PREFIX, identify_hasher
 from django.contrib.auth.hashers import UNUSABLE_PASSWORD_PREFIX, identify_hasher
 from django.contrib.auth.tokens import default_token_generator
 from django.contrib.auth.tokens import default_token_generator
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 
 
 
 
 UNMASKED_DIGITS_TO_SHOW = 6
 UNMASKED_DIGITS_TO_SHOW = 6

+ 2 - 1
django/contrib/auth/tests/test_views.py

@@ -4,7 +4,8 @@ import os
 import re
 import re
 
 
 from django.conf import global_settings, settings
 from django.conf import global_settings, settings
-from django.contrib.sites.models import Site, RequestSite
+from django.contrib.sites.models import Site
+from django.contrib.sites.requests import RequestSite
 from django.contrib.admin.models import LogEntry
 from django.contrib.admin.models import LogEntry
 from django.contrib.auth.models import User
 from django.contrib.auth.models import User
 from django.core import mail
 from django.core import mail

+ 1 - 1
django/contrib/auth/views.py

@@ -15,7 +15,7 @@ from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login, logout
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm, SetPasswordForm, PasswordChangeForm
 from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm, SetPasswordForm, PasswordChangeForm
 from django.contrib.auth.tokens import default_token_generator
 from django.contrib.auth.tokens import default_token_generator
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 
 
 
 
 @sensitive_post_parameters()
 @sensitive_post_parameters()

+ 1 - 1
django/contrib/comments/feeds.py

@@ -1,5 +1,5 @@
 from django.contrib.syndication.views import Feed
 from django.contrib.syndication.views import Feed
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 from django.contrib import comments
 from django.contrib import comments
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 
 

+ 1 - 1
django/contrib/comments/moderation.py

@@ -62,7 +62,7 @@ from django.contrib.comments import signals
 from django.db.models.base import ModelBase
 from django.db.models.base import ModelBase
 from django.template import Context, loader
 from django.template import Context, loader
 from django.contrib import comments
 from django.contrib import comments
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 from django.utils import timezone
 from django.utils import timezone
 
 
 class AlreadyModerated(Exception):
 class AlreadyModerated(Exception):

+ 1 - 1
django/contrib/contenttypes/tests.py

@@ -2,7 +2,7 @@ from __future__ import unicode_literals
 
 
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.views import shortcut
 from django.contrib.contenttypes.views import shortcut
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 from django.db import models
 from django.db import models
 from django.http import HttpRequest, Http404
 from django.http import HttpRequest, Http404
 from django.test import TestCase, override_settings
 from django.test import TestCase, override_settings

+ 2 - 1
django/contrib/contenttypes/views.py

@@ -2,7 +2,8 @@ from __future__ import unicode_literals
 
 
 from django import http
 from django import http
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
-from django.contrib.sites.models import Site, get_current_site
+from django.contrib.sites.models import Site
+from django.contrib.sites.shortcuts import get_current_site
 from django.core.exceptions import ObjectDoesNotExist
 from django.core.exceptions import ObjectDoesNotExist
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 
 

+ 1 - 1
django/contrib/flatpages/templatetags/flatpages.py

@@ -1,7 +1,7 @@
 from django import template
 from django import template
 from django.conf import settings
 from django.conf import settings
 from django.contrib.flatpages.models import FlatPage
 from django.contrib.flatpages.models import FlatPage
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 
 
 
 
 register = template.Library()
 register = template.Library()

+ 1 - 1
django/contrib/flatpages/views.py

@@ -1,6 +1,6 @@
 from django.conf import settings
 from django.conf import settings
 from django.contrib.flatpages.models import FlatPage
 from django.contrib.flatpages.models import FlatPage
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 from django.http import Http404, HttpResponse, HttpResponsePermanentRedirect
 from django.http import Http404, HttpResponse, HttpResponsePermanentRedirect
 from django.shortcuts import get_object_or_404
 from django.shortcuts import get_object_or_404
 from django.template import loader, RequestContext
 from django.template import loader, RequestContext

+ 1 - 1
django/contrib/gis/sitemaps/views.py

@@ -5,7 +5,7 @@ import warnings
 from django.apps import apps
 from django.apps import apps
 from django.http import HttpResponse, Http404
 from django.http import HttpResponse, Http404
 from django.template import loader
 from django.template import loader
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 from django.core import urlresolvers
 from django.core import urlresolvers
 from django.core.paginator import EmptyPage, PageNotAnInteger
 from django.core.paginator import EmptyPage, PageNotAnInteger
 from django.contrib.gis.db.models.fields import GeometryField
 from django.contrib.gis.db.models.fields import GeometryField

+ 1 - 1
django/contrib/redirects/middleware.py

@@ -3,7 +3,7 @@ from __future__ import unicode_literals
 from django.apps import apps
 from django.apps import apps
 from django.conf import settings
 from django.conf import settings
 from django.contrib.redirects.models import Redirect
 from django.contrib.redirects.models import Redirect
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 from django.core.exceptions import ImproperlyConfigured
 from django.core.exceptions import ImproperlyConfigured
 from django import http
 from django import http
 
 

+ 1 - 1
django/contrib/sitemaps/views.py

@@ -1,7 +1,7 @@
 from calendar import timegm
 from calendar import timegm
 from functools import wraps
 from functools import wraps
 
 
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 from django.core import urlresolvers
 from django.core import urlresolvers
 from django.core.paginator import EmptyPage, PageNotAnInteger
 from django.core.paginator import EmptyPage, PageNotAnInteger
 from django.http import Http404
 from django.http import Http404

+ 14 - 29
django/contrib/sites/models.py

@@ -1,6 +1,7 @@
 from __future__ import unicode_literals
 from __future__ import unicode_literals
 
 
 import string
 import string
+import warnings
 
 
 from django.core.exceptions import ImproperlyConfigured, ValidationError
 from django.core.exceptions import ImproperlyConfigured, ValidationError
 from django.db import models
 from django.db import models
@@ -8,6 +9,9 @@ from django.db.models.signals import pre_save, pre_delete
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 from django.utils.encoding import python_2_unicode_compatible
 from django.utils.encoding import python_2_unicode_compatible
 
 
+from .requests import RequestSite as RealRequestSite
+from .shortcuts import get_current_site as real_get_current_site
+
 
 
 SITE_CACHE = {}
 SITE_CACHE = {}
 
 
@@ -74,38 +78,19 @@ class Site(models.Model):
         return self.domain
         return self.domain
 
 
 
 
-@python_2_unicode_compatible
-class RequestSite(object):
-    """
-    A class that shares the primary interface of Site (i.e., it has
-    ``domain`` and ``name`` attributes) but gets its data from a Django
-    HttpRequest object rather than from a database.
-
-    The save() and delete() methods raise NotImplementedError.
-    """
-    def __init__(self, request):
-        self.domain = self.name = request.get_host()
-
-    def __str__(self):
-        return self.domain
-
-    def save(self, force_insert=False, force_update=False):
-        raise NotImplementedError('RequestSite cannot be saved.')
-
-    def delete(self):
-        raise NotImplementedError('RequestSite cannot be deleted.')
+class RequestSite(RealRequestSite):
+    def __init__(self, *args, **kwargs):
+        warnings.warn(
+            "Please import RequestSite from django.contrib.sites.requests.",
+            PendingDeprecationWarning, stacklevel=2)
+        super(RequestSite, self).__init__(*args, **kwargs)
 
 
 
 
 def get_current_site(request):
 def get_current_site(request):
-    """
-    Checks if contrib.sites is installed and returns either the current
-    ``Site`` object or a ``RequestSite`` object based on the request.
-    """
-    if Site._meta.installed:
-        current_site = Site.objects.get_current()
-    else:
-        current_site = RequestSite(request)
-    return current_site
+    warnings.warn(
+        "Please import get_current_site from django.contrib.sites.shortcuts.",
+        PendingDeprecationWarning, stacklevel=2)
+    return real_get_current_site(request)
 
 
 
 
 def clear_site_cache(sender, **kwargs):
 def clear_site_cache(sender, **kwargs):

+ 25 - 0
django/contrib/sites/requests.py

@@ -0,0 +1,25 @@
+from __future__ import unicode_literals
+
+from django.utils.encoding import python_2_unicode_compatible
+
+
+@python_2_unicode_compatible
+class RequestSite(object):
+    """
+    A class that shares the primary interface of Site (i.e., it has
+    ``domain`` and ``name`` attributes) but gets its data from a Django
+    HttpRequest object rather than from a database.
+
+    The save() and delete() methods raise NotImplementedError.
+    """
+    def __init__(self, request):
+        self.domain = self.name = request.get_host()
+
+    def __str__(self):
+        return self.domain
+
+    def save(self, force_insert=False, force_update=False):
+        raise NotImplementedError('RequestSite cannot be saved.')
+
+    def delete(self):
+        raise NotImplementedError('RequestSite cannot be deleted.')

+ 18 - 0
django/contrib/sites/shortcuts.py

@@ -0,0 +1,18 @@
+from __future__ import unicode_literals
+
+from django.apps import apps
+
+
+def get_current_site(request):
+    """
+    Checks if contrib.sites is installed and returns either the current
+    ``Site`` object or a ``RequestSite`` object based on the request.
+    """
+    # Imports are inside the function because its point is to avoid importing
+    # the Site models when django.contrib.sites isn't installed.
+    if apps.is_installed('django.contrib.sites'):
+        from .models import Site
+        return Site.objects.get_current()
+    else:
+        from .requests import RequestSite
+        return RequestSite(request)

+ 4 - 1
django/contrib/sites/tests.py

@@ -1,11 +1,14 @@
 from __future__ import unicode_literals
 from __future__ import unicode_literals
 
 
 from django.conf import settings
 from django.conf import settings
-from django.contrib.sites.models import Site, RequestSite, get_current_site
 from django.core.exceptions import ObjectDoesNotExist, ValidationError
 from django.core.exceptions import ObjectDoesNotExist, ValidationError
 from django.http import HttpRequest
 from django.http import HttpRequest
 from django.test import TestCase, modify_settings, override_settings
 from django.test import TestCase, modify_settings, override_settings
 
 
+from .models import Site
+from .requests import RequestSite
+from .shortcuts import get_current_site
+
 
 
 @modify_settings(INSTALLED_APPS={'append': 'django.contrib.sites'})
 @modify_settings(INSTALLED_APPS={'append': 'django.contrib.sites'})
 class SitesFrameworkTests(TestCase):
 class SitesFrameworkTests(TestCase):

+ 1 - 1
django/contrib/syndication/views.py

@@ -3,7 +3,7 @@ from __future__ import unicode_literals
 from calendar import timegm
 from calendar import timegm
 
 
 from django.conf import settings
 from django.conf import settings
-from django.contrib.sites.models import get_current_site
+from django.contrib.sites.shortcuts import get_current_site
 from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
 from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
 from django.http import HttpResponse, Http404
 from django.http import HttpResponse, Http404
 from django.template import loader, TemplateDoesNotExist, RequestContext
 from django.template import loader, TemplateDoesNotExist, RequestContext

+ 1 - 1
django/views/decorators/cache.py

@@ -12,7 +12,7 @@ def cache_page(*args, **kwargs):
     The cache is keyed by the URL and some data from the headers.
     The cache is keyed by the URL and some data from the headers.
     Additionally there is the key prefix that is used to distinguish different
     Additionally there is the key prefix that is used to distinguish different
     cache areas in a multi-site setup. You could use the
     cache areas in a multi-site setup. You could use the
-    sites.get_current_site().domain, for example, as that is unique across a Django
+    get_current_site().domain, for example, as that is unique across a Django
     project.
     project.
 
 
     Additionally, all headers from the response's Vary header will be taken
     Additionally, all headers from the response's Vary header will be taken

+ 3 - 0
docs/internals/deprecation.txt

@@ -184,6 +184,9 @@ these changes.
 
 
 * ``AppCommand.handle_app()`` will no longer be supported.
 * ``AppCommand.handle_app()`` will no longer be supported.
 
 
+* ``RequestSite`` will be located in ``django.contrib.sites.requests`` and
+  ``get_current_site`` in ``django.contrib.sites.shortcuts``.
+
 * FastCGI support via the ``runfcgi`` management command will be
 * FastCGI support via the ``runfcgi`` management command will be
   removed. Please deploy your project using WSGI.
   removed. Please deploy your project using WSGI.
 
 

+ 41 - 29
docs/ref/contrib/sites.txt

@@ -6,8 +6,6 @@ The "sites" framework
    :synopsis: Lets you operate multiple Web sites from the same database and
    :synopsis: Lets you operate multiple Web sites from the same database and
               Django project
               Django project
 
 
-.. currentmodule:: django.contrib.sites.models
-
 Django comes with an optional "sites" framework. It's a hook for associating
 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
 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.
 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
 Use it if your single Django installation powers more than one site and you
 need to differentiate between those sites in some way.
 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.
     A model for storing the ``domain`` and ``name`` attributes of a Web site.
     The :setting:`SITE_ID` setting specifies the database ID of the
     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.
         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
 How you use this is up to you, but Django uses it in a couple of ways
 automatically via simple conventions.
 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
   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::
   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):
       def article_detail(request, article_id):
           try:
           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
 cleaner way of accomplishing the same thing is to check the current site's
 domain::
 domain::
 
 
-    from django.contrib.sites.models import get_current_site
+    from django.contrib.sites.shortcuts import get_current_site
 
 
     def my_view(request):
     def my_view(request):
         current_site = get_current_site(request)
         current_site = get_current_site(request)
@@ -149,7 +146,8 @@ domain::
             pass
             pass
 
 
 This has also the advantage of checking if the sites framework is installed,
 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
 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`
 ``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::
 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
     from django.core.mail import send_mail
 
 
     def register_for_newsletter(request):
     def register_for_newsletter(request):
@@ -296,12 +294,10 @@ clear the cache using ``Site.objects.clear_cache()``::
     Site.objects.clear_cache()
     Site.objects.clear_cache()
     current_site = Site.objects.get_current()
     current_site = Site.objects.get_current()
 
 
-.. currentmodule:: django.contrib.sites.managers
-
 The ``CurrentSiteManager``
 The ``CurrentSiteManager``
 ==========================
 ==========================
 
 
-.. class:: CurrentSiteManager
+.. class:: managers.CurrentSiteManager
 
 
 If :class:`~django.contrib.sites.models.Site` plays a key role in your
 If :class:`~django.contrib.sites.models.Site` plays a key role in your
 application, consider using the helpful
 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
   :class:`~django.contrib.sites.models.Site` to work out the domain for the
   site that it will redirect to.
   site that it will redirect to.
 
 
-.. currentmodule:: django.contrib.sites.models
-
 ``RequestSite`` objects
 ``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
 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
 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
     A class that shares the primary interface of
     :class:`~django.contrib.sites.models.Site` (i.e., it has
     :class:`~django.contrib.sites.models.Site` (i.e., it has
     ``domain`` and ``name`` attributes) but gets its data from a Django
     ``domain`` and ``name`` attributes) but gets its data from a Django
     :class:`~django.http.HttpRequest` object rather than from a database.
     :class:`~django.http.HttpRequest` object rather than from a database.
 
 
-    The ``save()`` and ``delete()`` methods raise ``NotImplementedError``.
-
     .. method:: __init__(request)
     .. method:: __init__(request)
 
 
         Sets the ``name`` and ``domain`` attributes to the value of
         Sets the ``name`` and ``domain`` attributes to the value of
         :meth:`~django.http.HttpRequest.get_host`.
         :meth:`~django.http.HttpRequest.get_host`.
 
 
+    .. versionchanged:: 1.7
+
+      This class used to be defined in ``django.contrib.sites.models``.
 
 
-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
+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
 :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``.

+ 1 - 1
docs/ref/contrib/syndication.txt

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

+ 13 - 0
docs/releases/1.7.txt

@@ -1009,6 +1009,19 @@ than simply ``myapp/models.py``, Django would look for :ref:`initial SQL data
 will search ``myapp/sql/`` as documented. The old location will continue to
 will search ``myapp/sql/`` as documented. The old location will continue to
 work until Django 1.9.
 work until Django 1.9.
 
 
+Reorganization of ``django.contrib.sites``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``django.contrib.sites`` provides reduced functionality when it isn't in
+:setting:`INSTALLED_APPS`. The app-loading refactor adds some constraints in
+that situation. As a consequence, two objects were moved, and the old
+locations are deprecated:
+
+* :class:`~django.contrib.sites.requests.RequestSite` now lives in
+  ``django.contrib.sites.requests``.
+* :func:`~django.contrib.sites.shortcuts.get_current_site` now lives in
+  ``django.contrib.sites.shortcuts``.
+
 ``declared_fieldsets`` attribute on ``ModelAdmin``
 ``declared_fieldsets`` attribute on ``ModelAdmin``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 

+ 2 - 2
docs/topics/auth/default.txt

@@ -648,7 +648,7 @@ patterns.
     * ``site``: The current :class:`~django.contrib.sites.models.Site`,
     * ``site``: The current :class:`~django.contrib.sites.models.Site`,
       according to the :setting:`SITE_ID` setting. If you don't have the
       according to the :setting:`SITE_ID` setting. If you don't have the
       site framework installed, this will be set to an instance of
       site framework installed, this will be set to an instance of
-      :class:`~django.contrib.sites.models.RequestSite`, which derives the
+      :class:`~django.contrib.sites.requests.RequestSite`, which derives the
       site name and domain from the current
       site name and domain from the current
       :class:`~django.http.HttpRequest`.
       :class:`~django.http.HttpRequest`.
 
 
@@ -744,7 +744,7 @@ patterns.
     * ``site``: The current :class:`~django.contrib.sites.models.Site`,
     * ``site``: The current :class:`~django.contrib.sites.models.Site`,
       according to the :setting:`SITE_ID` setting. If you don't have the
       according to the :setting:`SITE_ID` setting. If you don't have the
       site framework installed, this will be set to an instance of
       site framework installed, this will be set to an instance of
-      :class:`~django.contrib.sites.models.RequestSite`, which derives the
+      :class:`~django.contrib.sites.requests.RequestSite`, which derives the
       site name and domain from the current
       site name and domain from the current
       :class:`~django.http.HttpRequest`.
       :class:`~django.http.HttpRequest`.