Ticket #15089: 15089_patch_a.diff

File 15089_patch_a.diff, 9.5 KB (added by legutierr, 9 years ago)

A first version of a patch, for review.

  • django/contrib/sites/managers.py

     
    1 from django.conf import settings
    21from django.db import models
    32from django.db.models.fields import FieldDoesNotExist
     3from django.contrib.sites.models import Site
    44
    55class CurrentSiteManager(models.Manager):
    66    "Use this to limit objects to those associated with the current site."
     
    3838    def get_query_set(self):
    3939        if not self.__is_validated:
    4040            self._validate_field_name()
    41         return super(CurrentSiteManager, self).get_query_set().filter(**{self.__field_name + '__id__exact': settings.SITE_ID})
     41        return super(CurrentSiteManager, self).get_query_set().filter(
     42          **{self.__field_name: Site.objects.get_current()}
     43        )
  • django/contrib/sites/middleware.py

     
     1from django.utils.cache import patch_vary_headers
     2from django.contrib.sites.models import get_current_site, Site, RequestSite, SITE_CACHE
     3
     4
     5class LazySite(object):
     6    """
     7    A lazy site object that refers to either Site instance or
     8    a case insensitive RequestSite.
     9    """
     10    def get_site(self, request):
     11        get_current_site(request)
     12        return site
     13
     14    def __get__(self, request, obj_type=None):
     15        if not hasattr(request, '_cached_site'):
     16            request._cached_site = self.get_site(request)
     17        return request._cached_site
     18
     19
     20class SitesMiddleware(object):
     21
     22    def process_request(self, request):
     23        if not hasattr(request.__class__, 'site'):
     24            request.__class__.site = LazySite()
     25        return None
     26
     27    def process_response(self, request, response):
     28        """
     29        Forces the HTTP Vary header onto requests to avoid having responses
     30        cached from incorrect urlconfs.
     31
     32        If you'd like to disable this for some reason, set `FORCE_VARY_ON_HOST`
     33        in your Django settings file to `False`.
     34        """
     35        if getattr(settings, 'SITES_VARY_ON_HOST', True):
     36            patch_vary_headers(response, ('Host',))
     37        return response
     38
  • django/contrib/sites/tests.py

     
    88class SitesFrameworkTests(TestCase):
    99
    1010    def setUp(self):
    11         Site(id=settings.SITE_ID, domain="example.com", name="example.com").save()
     11        Site(id=settings.SITE_ID, domain="staticsite.com", name="staticsite.com").save()
     12        Site(domain="dynamicsite.com", name="dynamicsite.com").save()
    1213        self.old_Site_meta_installed = Site._meta.installed
    1314        Site._meta.installed = True
    1415
     
    2627        # After updating a Site object (e.g. via the admin), we shouldn't return a
    2728        # bogus value from the SITE_CACHE.
    2829        site = Site.objects.get_current()
    29         self.assertEqual(u"example.com", site.name)
     30        self.assertEqual(u"staticsite.com", site.name)
    3031        s2 = Site.objects.get(id=settings.SITE_ID)
    3132        s2.name = "Example site"
    3233        s2.save()
     
    3738        # Test that the correct Site object is returned
    3839        request = HttpRequest()
    3940        request.META = {
    40             "SERVER_NAME": "example.com",
     41            "SERVER_NAME": "staticsite.com",
    4142            "SERVER_PORT": "80",
    4243        }
    4344        site = get_current_site(request)
     
    4950        site.delete()
    5051        self.assertRaises(ObjectDoesNotExist, get_current_site, request)
    5152
     53        request = HttpRequest()
     54        request.META = {
     55            "SERVER_NAME": "dynamicsite.com",
     56            "SERVER_PORT": "80",
     57        }
     58        site = get_current_site(request)
     59        self.assert_(isinstance(site, Site))
     60        self.assertNotEqual(site.id, settings.SITE_ID)
     61        self.assertEqual(site.domain, "dynamicsite.com")
     62
     63        # Test that an exception is raised if the sites framework is installed
     64        # but there is no matching Site
     65        site.delete()
     66        self.assertRaises(ObjectDoesNotExist, get_current_site, request)
     67
    5268        # A RequestSite is returned if the sites framework is not installed
    5369        Site._meta.installed = False
    5470        site = get_current_site(request)
    5571        self.assert_(isinstance(site, RequestSite))
    56         self.assertEqual(site.name, u"example.com")
     72        self.assertEqual(site.name, u"dynamicsite.com")
     73
  • django/contrib/sites/models.py

     
    11from django.db import models
    22from django.utils.translation import ugettext_lazy as _
     3from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
    34
    45
    56SITE_CACHE = {}
     
    78
    89class SiteManager(models.Manager):
    910
     11    def get_site_by_request(self, request):
     12        host = request.get_host().lower()
     13        if ':' in host:
     14            host, _ = host.split(':', 1)
     15        return self.get(domain__iexact=host)
     16
     17    def get_site_by_id(self, id):
     18        site = SITE_CACHE.get(id, None)
     19        if site is None:
     20            site = self.get(pk=id)
     21            SITE_CACHE[id] = site
     22        return site
     23
    1024    def get_current(self):
    1125        """
    1226        Returns the current ``Site`` based on the SITE_ID in the
    1327        project's settings. The ``Site`` object is cached the first
    1428        time it's retrieved from the database.
    1529        """
     30        from warnings import warn
     31        warn(
     32            "The SiteManager.get_current() method is deprecated in favor of the "
     33            "get_current_site() function.", DeprecationWarning
     34        )
     35
    1636        from django.conf import settings
    1737        try:
    1838            sid = settings.SITE_ID
    1939        except AttributeError:
    20             from django.core.exceptions import ImproperlyConfigured
    21             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.")
    22         try:
    23             current_site = SITE_CACHE[sid]
    24         except KeyError:
    25             current_site = self.get(pk=sid)
    26             SITE_CACHE[sid] = current_site
    27         return current_site
     40            raise ImproperlyConfigured(
     41                "You're using the Django \"sites framework\" without having set "
     42                "the SITE_ID setting. Create a site in your database and set "
     43                "the SITE_ID setting to fix this error."
     44            )
     45        return self.get_site_by_id(sid)
    2846
    2947    def clear_cache(self):
    3048        """Clears the ``Site`` object cache."""
     
    3452
    3553class Site(models.Model):
    3654
    37     domain = models.CharField(_('domain name'), max_length=100)
     55    domain = models.CharField(_('domain name'), max_length=100, unique=True)
    3856    name = models.CharField(_('display name'), max_length=50)
    3957    objects = SiteManager()
    4058
     
    7189    The save() and delete() methods raise NotImplementedError.
    7290    """
    7391    def __init__(self, request):
    74         self.domain = self.name = request.get_host()
     92        self.domain = self.name = request.get_host().lower()
    7593
    7694    def __unicode__(self):
    7795        return self.domain
     
    83101        raise NotImplementedError('RequestSite cannot be deleted.')
    84102
    85103
    86 def get_current_site(request):
     104def get_current_site(request, require_orm_object=False):
    87105    """
    88106    Checks if contrib.sites is installed and returns either the current
    89107    ``Site`` object or a ``RequestSite`` object based on the request.
    90108    """
    91     if Site._meta.installed:
    92         current_site = Site.objects.get_current()
     109    from django.conf import settings
     110    if hasattr(settings, 'SITE_CALLBACK'):
     111        if callable(settings.SITE_CALLBACK):
     112            return settings.SITE_CALLBACK(request, require_orm_object)
     113        else:
     114            raise ImproperlyConfigured(
     115                'Settings contains a SITE_CALLBACK value which is not callable.'
     116            )
     117
     118    elif not Site._meta.installed:
     119        if not require_orm_object:
     120            return RequestSite(request)
     121        else:
     122            raise ImproperlyConfigured(
     123                'The Django "sites framework" is being used somewhere in '
     124                'your project in a manner that requires it to be added '
     125                'to INSTALLED_APPS in your settings file.'
     126            )
     127
    93128    else:
    94         current_site = RequestSite(request)
    95     return current_site
     129        try:
     130            return Site.objects.get_site_by_request(request)
     131
     132        except ObjectDoesNotExist:
     133            return Site.objects.get_site_by_id(settings.SITE_ID)
     134       
     135
  • django/contrib/sites/decorators.py

     
     1from django.utils.decorators import decorator_from_middleware
     2
     3from django.contrib.sites.middleware import SitesMiddleware
     4
     5site_aware = decorator_from_middleware(SitesMiddleware)
     6site_aware.__name__ = "site_aware"
     7site_aware.__doc__ = """
     8This decorator adds a LazySite instance to the request in exactly the same
     9way as the SitesMiddleware, but it can be used on a per view basis.
     10"""
     11
Back to Top