Ticket #13559: 13559_v3.diff

File 13559_v3.diff, 13.8 KB (added by Christopher Medrela, 12 years ago)
  • django/conf/global_settings.py

    diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
    index 13f7991..40a5ca4 100644
    a b TEMPLATE_LOADERS = (  
    197197# only parameter and returns a dictionary to add to the context.
    198198TEMPLATE_CONTEXT_PROCESSORS = (
    199199    'django.contrib.auth.context_processors.auth',
     200    'django.contrib.sites.context_processors.site',
    200201    'django.core.context_processors.debug',
    201202    'django.core.context_processors.i18n',
    202203    'django.core.context_processors.media',
  • django/contrib/auth/views.py

    diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py
    index c86ef53..7d1fbc3 100644
    a b def login(request, template_name='registration/login.html',  
    6262    context = {
    6363        'form': form,
    6464        redirect_field_name: redirect_to,
    65         'site': current_site,
    6665        'site_name': current_site.name,
    6766    }
    6867    if extra_context is not None:
  • new file django/contrib/sites/context_processors.py

    diff --git a/django/contrib/sites/context_processors.py b/django/contrib/sites/context_processors.py
    new file mode 100644
    index 0000000..0922dd3
    - +  
     1from django.contrib.sites.models import Site, RequestSite
     2from django.core.exceptions import ImproperlyConfigured
     3from django.db import models
     4
     5
     6def site(request):
     7    """Sets in the present context information about the current site."""
     8
     9    # Current SiteManager already handles prevention of spurious
     10    # database calls. If the user does not have the Sites framework
     11    # installed, a RequestSite object is an appropriate fallback.
     12    try:
     13        site_app = models.get_app('sites')
     14        site_obj = Site.objects.get_current()
     15    except ImproperlyConfigured:
     16        site_obj = RequestSite(request)
     17    return {'site': site_obj}
  • new file django/contrib/sites/tests/__init__.py

    diff --git a/django/contrib/sites/tests/__init__.py b/django/contrib/sites/tests/__init__.py
    new file mode 100644
    index 0000000..580a75f
    - +  
     1from django.contrib.sites.tests.base import SitesFrameworkTests
     2from django.contrib.sites.tests.context_processors import ContextProcessorTest
  • new file django/contrib/sites/tests/base.py

    diff --git a/django/contrib/sites/tests/base.py b/django/contrib/sites/tests/base.py
    new file mode 100644
    index 0000000..da21b7b
    - +  
     1from django.conf import settings
     2
     3from django.contrib.sites.models import Site, RequestSite, get_current_site
     4from django.core.exceptions import ObjectDoesNotExist
     5from django.http import HttpRequest
     6from django.test import TestCase
     7
     8
     9class SitesFrameworkTests(TestCase):
     10
     11    def setUp(self):
     12        Site(id=settings.SITE_ID,
     13             domain="example.com",
     14             name="example.com").save()
     15        self.old_Site_meta_installed = Site._meta.installed
     16        Site._meta.installed = True
     17
     18    def tearDown(self):
     19        Site._meta.installed = self.old_Site_meta_installed
     20
     21    def test_save_another(self):
     22        # Regression for #17415.
     23        # On some backends the sequence needs reset after save with
     24        # explicit ID.  Test that there is no sequence collisions by
     25        # saving another site.
     26        Site(domain="example2.com", name="example2.com").save()
     27
     28    def test_site_manager(self):
     29        # Make sure that get_current() does not return a deleted Site object.
     30        s = Site.objects.get_current()
     31        self.assertTrue(isinstance(s, Site))
     32        s.delete()
     33        self.assertRaises(ObjectDoesNotExist, Site.objects.get_current)
     34
     35    def test_site_cache(self):
     36        # After updating a Site object (e.g. via the admin), we
     37        # shouldn't return a bogus value from the SITE_CACHE.
     38        site = Site.objects.get_current()
     39        self.assertEqual(u"example.com", site.name)
     40        s2 = Site.objects.get(id=settings.SITE_ID)
     41        s2.name = "Example site"
     42        s2.save()
     43        site = Site.objects.get_current()
     44        self.assertEqual(u"Example site", site.name)
     45
     46    def test_get_current_site(self):
     47        # Test that the correct Site object is returned
     48        request = HttpRequest()
     49        request.META = {
     50            "SERVER_NAME": "example.com",
     51            "SERVER_PORT": "80",
     52        }
     53        site = get_current_site(request)
     54        self.assertTrue(isinstance(site, Site))
     55        self.assertEqual(site.id, settings.SITE_ID)
     56
     57        # Test that an exception is raised if the sites framework is installed
     58        # but there is no matching Site
     59        site.delete()
     60        self.assertRaises(ObjectDoesNotExist, get_current_site, request)
     61
     62        # A RequestSite is returned if the sites framework is not installed
     63        Site._meta.installed = False
     64        site = get_current_site(request)
     65        self.assertTrue(isinstance(site, RequestSite))
     66        self.assertEqual(site.name, u"example.com")
  • new file django/contrib/sites/tests/context_processors.py

    diff --git a/django/contrib/sites/tests/context_processors.py b/django/contrib/sites/tests/context_processors.py
    new file mode 100644
    index 0000000..d5c5aa8
    - +  
     1#-*- coding:utf-8 -*-
     2
     3import os
     4
     5from django.conf import settings
     6from django.contrib.sites.models import Site, RequestSite
     7from django.test import TestCase
     8from django.test.client import RequestFactory
     9from django.test.utils import override_settings
     10
     11
     12template_directory = os.path.join(os.path.dirname(__file__), 'templates')
     13
     14
     15@override_settings(TEMPLATE_DIRS=(template_directory,))
     16class ContextProcessorTest(TestCase):
     17    urls = 'django.contrib.sites.tests.urls'
     18
     19    def test_context_processor(self):
     20        response = self.client.get('/context_processors/')
     21        site_obj = Site.objects.get_current()
     22        self.assertEqual(response.status_code, 200)
     23        self.assertContains(response, 'site.name: %s' % site_obj.name)
     24        self.assertContains(response, 'site.domain: %s' % site_obj.domain)
     25
     26    def test_context_processor_without_sites_framework(self):
     27        server_url = 'test.example.com'
     28        apps = list(settings.INSTALLED_APPS)
     29        apps.remove('django.contrib.sites')
     30        with self.settings(INSTALLED_APPS=apps):
     31            response = self.client.get('/context_processors/',
     32                                       SERVER_NAME=server_url)
     33        self.assertEqual(response.status_code, 200)
     34        self.assertContains(response, 'site.name: %s' % server_url)
     35        self.assertContains(response, 'site.domain: %s' % server_url)
  • new file django/contrib/sites/tests/templates/sites/context_processors_test.html

    diff --git a/django/contrib/sites/tests/templates/sites/context_processors_test.html b/django/contrib/sites/tests/templates/sites/context_processors_test.html
    new file mode 100644
    index 0000000..a2e2ee8
    - +  
     1site.name: {{ site.name }}
     2site.domain: {{ site.domain }}
  • new file django/contrib/sites/tests/urls.py

    diff --git a/django/contrib/sites/tests/urls.py b/django/contrib/sites/tests/urls.py
    new file mode 100644
    index 0000000..7d16667
    - +  
     1from django.conf.urls import patterns
     2from django.views.generic import TemplateView
     3
     4urlpatterns = patterns('',
     5    (r'^context_processors/$',
     6     TemplateView.as_view(
     7       template_name='sites/context_processors_test.html')),)
  • django/contrib/syndication/views.py

    diff --git a/django/contrib/syndication/views.py b/django/contrib/syndication/views.py
    index af767e1..6ddd8ed 100644
    a b class Feed(object):  
    139139
    140140        for item in self.__get_dynamic_attr('items', obj):
    141141            if title_tmp is not None:
    142                 title = title_tmp.render(RequestContext(request, {'obj': item, 'site': current_site}))
     142                title = title_tmp.render( \
     143                  RequestContext(request, {'obj': item}))
    143144            else:
    144145                title = self.__get_dynamic_attr('item_title', item)
    145146            if description_tmp is not None:
    146                 description = description_tmp.render(RequestContext(request, {'obj': item, 'site': current_site}))
     147                description = description_tmp.render( \
     148                  RequestContext(request, {'obj': item}))
    147149            else:
    148150                description = self.__get_dynamic_attr('item_description', item)
    149151            link = add_domain(
  • django/views/generic/__init__.py

    diff --git a/django/views/generic/__init__.py b/django/views/generic/__init__.py
    index 1a98067..2c51513 100644
    a b  
    11from django.views.generic.base import View, TemplateView, RedirectView
    2 from django.views.generic.dates import (ArchiveIndexView, YearArchiveView, MonthArchiveView,
    3                                      WeekArchiveView, DayArchiveView, TodayArchiveView,
    4                                      DateDetailView)
     2from django.views.generic.dates import (ArchiveIndexView, YearArchiveView,
     3                                        MonthArchiveView, WeekArchiveView,
     4                                        DayArchiveView, TodayArchiveView,
     5                                        DateDetailView)
    56from django.views.generic.detail import DetailView
    6 from django.views.generic.edit import FormView, CreateView, UpdateView, DeleteView
     7from django.views.generic.edit import (FormView, CreateView,
     8                                       UpdateView, DeleteView)
    79from django.views.generic.list import ListView
    810
    911
  • docs/ref/contrib/sites.txt

    diff --git a/docs/ref/contrib/sites.txt b/docs/ref/contrib/sites.txt
    index 8fc434b..d9587c7 100644
    a b fallback for cases where it is not installed.  
    174174.. function:: get_current_site(request)
    175175
    176176    Checks if contrib.sites is installed and returns either the current
    177     :class:`~django.contrib.sites.models.Site` object or a 
     177    :class:`~django.contrib.sites.models.Site` object or a
    178178    :class:`~django.contrib.sites.models.RequestSite` object based on
    179179    the request.
    180180
    On Lawrence.com, this email has the subject line "Thanks for subscribing to  
    215215lawrence.com alerts." On LJWorld.com, the email has the subject "Thanks for
    216216subscribing to LJWorld.com alerts." Same goes for the email's message body.
    217217
    218 Note that an even more flexible (but more heavyweight) way of doing this would
    219 be to use Django's template system. Assuming Lawrence.com and LJWorld.com have
    220 different template directories (:setting:`TEMPLATE_DIRS`), you could simply farm out
    221 to the template system like so::
     218The current Site object is made available in the
     219:doc:`template context </ref/templates/api>` when you use
     220:class:`~django.template.RequestContext` and when your
     221:setting:`TEMPLATE_CONTEXT_PROCESSORS` setting contains
     222``'django.contrib.sites.context_processors.site'``, which is default.
     223
     224Using template context, an even more flexible way of sending
     225email-notifications would be to use Django's template system::
    222226
    223227    from django.core.mail import send_mail
    224     from django.template import loader, Context
     228    from django.template import loader, RequestContext
    225229
    226230    def register_for_newsletter(request):
    227231        # Check form values, etc., and subscribe the user.
    228232        # ...
    229233
    230         subject = loader.get_template('alerts/subject.txt').render(Context({}))
    231         message = loader.get_template('alerts/message.txt').render(Context({}))
     234        subject_template = loader.get_template('alerts/subject.txt')
     235        subject = subject_template.render(RequestContext(request, {}))
     236        message_template = loader.get_template('alerts/message.txt')
     237        message = message_template.render(RequestContext(request, {}))
    232238        send_mail(subject, message, 'editor@ljworld.com', [user.email])
    233239
    234240        # ...
    235241
    236242In this case, you'd have to create :file:`subject.txt` and :file:`message.txt` template
    237 files for both the LJWorld.com and Lawrence.com template directories. That
     243files that include ``{{ site.name }}`` and ``{{ site.domain }}``. That
    238244gives you more flexibility, but it's also more complex.
    239245
    240246It's a good idea to exploit the :class:`~django.contrib.sites.models.Site`
    Here's how Django uses the sites framework:  
    389395  checks the current :setting:`SITE_ID` in retrieving flatpages to display.
    390396
    391397* In the :mod:`syndication framework <django.contrib.syndication>`, the
    392   templates for ``title`` and ``description`` automatically have access to a
    393   variable ``{{ site }}``, which is the
    394   :class:`~django.contrib.sites.models.Site` object representing the current
    395   site. Also, the hook for providing item URLs will use the ``domain`` from
     398  hook for providing item URLs will use the ``domain`` from
    396399  the current :class:`~django.contrib.sites.models.Site` object if you don't
    397400  specify a fully-qualified domain.
    398401
    fallback when the database-backed sites framework is not available.  
    437440
    438441        Sets the ``name`` and ``domain`` attributes to the value of
    439442        :meth:`~django.http.HttpRequest.get_host`.
    440        
     443
    441444
    442445A :class:`~django.contrib.sites.models.RequestSite` object has a similar
    443446interface to a normal :class:`~django.contrib.sites.models.Site` object, except
  • docs/ref/settings.txt

    diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
    index 627aa50..cc8f117 100644
    a b TEMPLATE_CONTEXT_PROCESSORS  
    18801880Default::
    18811881
    18821882    ("django.contrib.auth.context_processors.auth",
     1883    "django.contrib.sites.context_processors.site",
    18831884    "django.core.context_processors.debug",
    18841885    "django.core.context_processors.i18n",
    18851886    "django.core.context_processors.media",
    of items to be merged into the context.  
    18991900    The ``django.core.context_processors.tz`` context processor
    19001901    was added in this release.
    19011902
     1903.. versionadded:: 1.5
     1904    The ``django.contrib.sites.context_processors.site`` context
     1905    processor was added in this release.
     1906
    19021907.. setting:: TEMPLATE_DEBUG
    19031908
    19041909TEMPLATE_DEBUG
Back to Top