diff --git a/django/contrib/sites/models.py b/django/contrib/sites/models.py
index 8590740..a7aa462 100644
a
|
b
|
|
| 1 | from django.core.exceptions import ImproperlyConfigured |
1 | 2 | from django.db import models |
2 | 3 | from django.utils.translation import ugettext_lazy as _ |
3 | 4 | from django.utils.encoding import python_2_unicode_compatible |
… |
… |
SITE_CACHE = {}
|
8 | 9 | |
9 | 10 | class SiteManager(models.Manager): |
10 | 11 | |
| 12 | def _get_site_by_id(self, sid): |
| 13 | if not sid in SITE_CACHE: |
| 14 | site = self.get(pk=sid) |
| 15 | SITE_CACHE[sid] = site |
| 16 | return SITE_CACHE[sid] |
| 17 | |
| 18 | def _get_site_by_request(self, request): |
| 19 | host = request.get_host().lower() |
| 20 | if ':' in host: |
| 21 | host = host.split(':', 1)[0] |
| 22 | if not host in SITE_CACHE: |
| 23 | site = self.get(domain__iexact=host) |
| 24 | SITE_CACHE[host] = site |
| 25 | return SITE_CACHE[host] |
| 26 | |
11 | 27 | def get_current(self): |
12 | 28 | """ |
13 | 29 | Returns the current ``Site`` based on the SITE_ID in the |
… |
… |
class SiteManager(models.Manager):
|
18 | 34 | try: |
19 | 35 | sid = settings.SITE_ID |
20 | 36 | except AttributeError: |
21 | | from django.core.exceptions import ImproperlyConfigured |
22 | 37 | raise ImproperlyConfigured("You're using the Django \"sites framework\" without having set the SITE_ID setting. Create a site in your database and set the SITE_ID setting to fix this error.") |
23 | | try: |
24 | | current_site = SITE_CACHE[sid] |
25 | | except KeyError: |
26 | | current_site = self.get(pk=sid) |
27 | | SITE_CACHE[sid] = current_site |
28 | | return current_site |
| 38 | return self._get_site_by_id(sid) |
29 | 39 | |
30 | 40 | def clear_cache(self): |
31 | 41 | """Clears the ``Site`` object cache.""" |
… |
… |
def get_current_site(request):
|
92 | 102 | ``Site`` object or a ``RequestSite`` object based on the request. |
93 | 103 | """ |
94 | 104 | if Site._meta.installed: |
95 | | current_site = Site.objects.get_current() |
| 105 | from django.conf import settings |
| 106 | if hasattr(settings, 'SITE_ID'): |
| 107 | current_site = Site.objects.get_current() |
| 108 | else: |
| 109 | current_site = Site.objects._get_site_by_request(request) |
96 | 110 | else: |
97 | 111 | current_site = RequestSite(request) |
98 | 112 | return current_site |
diff --git a/django/contrib/sites/tests.py b/django/contrib/sites/tests.py
index 1bb2495..28d8f26 100644
a
|
b
|
from django.contrib.sites.models import Site, RequestSite, get_current_site
|
5 | 5 | from django.core.exceptions import ObjectDoesNotExist |
6 | 6 | from django.http import HttpRequest |
7 | 7 | from django.test import TestCase |
| 8 | from django.test.utils import override_settings |
8 | 9 | |
9 | 10 | |
10 | 11 | class SitesFrameworkTests(TestCase): |
… |
… |
class SitesFrameworkTests(TestCase):
|
62 | 63 | site = get_current_site(request) |
63 | 64 | self.assertTrue(isinstance(site, RequestSite)) |
64 | 65 | self.assertEqual(site.name, "example.com") |
| 66 | |
| 67 | @override_settings(SITE_ID='') |
| 68 | def test_get_current_site_no_site_id(self): |
| 69 | request = HttpRequest() |
| 70 | request.META = { |
| 71 | "SERVER_NAME": "example.com", |
| 72 | "SERVER_PORT": "80", |
| 73 | } |
| 74 | del settings.SITE_ID |
| 75 | site = get_current_site(request) |
| 76 | self.assertEqual(site.name, "example.com") |
diff --git a/docs/ref/contrib/sites.txt b/docs/ref/contrib/sites.txt
index 790e003..05fe9c0 100644
a
|
b
|
The whole sites framework is based on a simple model:
|
20 | 20 | .. class:: Site |
21 | 21 | |
22 | 22 | A model for storing the ``domain`` and ``name`` attributes of a Web site. |
23 | | The :setting:`SITE_ID` setting specifies the database ID of the |
24 | | :class:`~django.contrib.sites.models.Site` object associated with that |
25 | | particular settings file. |
26 | 23 | |
27 | 24 | .. attribute:: domain |
28 | 25 | |
… |
… |
The whole sites framework is based on a simple model:
|
32 | 29 | |
33 | 30 | A human-readable "verbose" name for the Web site. |
34 | 31 | |
| 32 | The :setting:`SITE_ID` setting specifies the database ID of the |
| 33 | :class:`~django.contrib.sites.models.Site` object associated with that |
| 34 | particular settings file. It is possible to omit it, but then you cannot |
| 35 | call the :meth:`~django.contrib.sites.models.Site.get_current` method any |
| 36 | more. The :func:`get_current_site` function will then always try to get the |
| 37 | current site by comparing the :attr:`~Site.domain` with the host name from the |
| 38 | :meth:`~django.http.HttpRequest.get_host` method. |
35 | 39 | |
36 | 40 | How you use this is up to you, but Django uses it in a couple of ways |
37 | 41 | automatically via simple conventions. |
… |
… |
Caching the current ``Site`` object
|
244 | 248 | =================================== |
245 | 249 | |
246 | 250 | As the current site is stored in the database, each call to |
247 | | ``Site.objects.get_current()`` could result in a database query. But Django is a |
248 | | little cleverer than that: on the first request, the current site is cached, and |
249 | | any subsequent call returns the cached data instead of hitting the database. |
| 251 | ``Site.objects.get_current()`` or to ``sites.get_current_site()`` could result |
| 252 | in a database query. But Django is a little cleverer than that: on the first |
| 253 | request, the current site is cached, and any subsequent call returns the cached |
| 254 | data instead of hitting the database. |
250 | 255 | |
251 | 256 | If for any reason you want to force a database query, you can tell Django to |
252 | 257 | clear the cache using ``Site.objects.clear_cache()``:: |
… |
… |
model(s). It's a model :doc:`manager </topics/db/managers>` that
|
277 | 282 | automatically filters its queries to include only objects associated |
278 | 283 | with the current :class:`~django.contrib.sites.models.Site`. |
279 | 284 | |
| 285 | .. admonition:: Mandatory SITE_ID |
| 286 | |
| 287 | The ``CurrentSiteManager`` is only usable when the :setting:`SITE_ID` |
| 288 | setting is defined in your settings. |
| 289 | |
280 | 290 | Use :class:`~django.contrib.sites.managers.CurrentSiteManager` by adding it to |
281 | 291 | your model explicitly. For example:: |
282 | 292 | |