Fixed #14386, #8960, #10235, #10909, #10608, #13845, #14377 - standardize Site/RequestSite usage in various places.
Many thanks to gabrielhurley for putting most of this together. Also to bmihelac, arthurk, qingfeng, hvendelbo, petr.pulc@s-cape.cz, Hraban for reports and some initial patches. The patch also contains some whitespace/PEP8 fixes. git-svn-id: http://code.djangoproject.com/svn/django/trunk@13980 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
96c11b29bd
commit
667d832e90
|
@ -1,7 +1,7 @@
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
from django.contrib.auth.tokens import default_token_generator
|
from django.contrib.auth.tokens import default_token_generator
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import get_current_site
|
||||||
from django.template import Context, loader
|
from django.template import Context, loader
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -117,14 +117,14 @@ class PasswordResetForm(forms.Form):
|
||||||
return email
|
return email
|
||||||
|
|
||||||
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
|
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
|
||||||
use_https=False, token_generator=default_token_generator, from_email=None):
|
use_https=False, token_generator=default_token_generator, from_email=None, request=None):
|
||||||
"""
|
"""
|
||||||
Generates a one-use only link for resetting password and sends to the user
|
Generates a one-use only link for resetting password and sends to the user
|
||||||
"""
|
"""
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
for user in self.users_cache:
|
for user in self.users_cache:
|
||||||
if not domain_override:
|
if not domain_override:
|
||||||
current_site = Site.objects.get_current()
|
current_site = get_current_site(request)
|
||||||
site_name = current_site.name
|
site_name = current_site.name
|
||||||
domain = current_site.domain
|
domain = current_site.domain
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -248,6 +248,12 @@ class LogoutTest(AuthViewsTestCase):
|
||||||
self.assert_('Logged out' in response.content)
|
self.assert_('Logged out' in response.content)
|
||||||
self.confirm_logged_out()
|
self.confirm_logged_out()
|
||||||
|
|
||||||
|
def test_14377(self):
|
||||||
|
# Bug 14377
|
||||||
|
self.login()
|
||||||
|
response = self.client.get('/logout/')
|
||||||
|
self.assertTrue('site' in response.context)
|
||||||
|
|
||||||
def test_logout_with_next_page_specified(self):
|
def test_logout_with_next_page_specified(self):
|
||||||
"Logout with next_page option given redirects to specified resource"
|
"Logout with next_page option given redirects to specified resource"
|
||||||
self.login()
|
self.login()
|
||||||
|
|
|
@ -10,7 +10,7 @@ from django.contrib.auth.tokens import default_token_generator
|
||||||
from django.views.decorators.csrf import csrf_protect
|
from django.views.decorators.csrf import csrf_protect
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.shortcuts import render_to_response, get_object_or_404
|
from django.shortcuts import render_to_response, get_object_or_404
|
||||||
from django.contrib.sites.models import Site, RequestSite
|
from django.contrib.sites.models import get_current_site
|
||||||
from django.http import HttpResponseRedirect, Http404
|
from django.http import HttpResponseRedirect, Http404
|
||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
from django.utils.http import urlquote, base36_to_int
|
from django.utils.http import urlquote, base36_to_int
|
||||||
|
@ -54,10 +54,7 @@ def login(request, template_name='registration/login.html',
|
||||||
|
|
||||||
request.session.set_test_cookie()
|
request.session.set_test_cookie()
|
||||||
|
|
||||||
if Site._meta.installed:
|
current_site = get_current_site(request)
|
||||||
current_site = Site.objects.get_current()
|
|
||||||
else:
|
|
||||||
current_site = RequestSite(request)
|
|
||||||
|
|
||||||
return render_to_response(template_name, {
|
return render_to_response(template_name, {
|
||||||
'form': form,
|
'form': form,
|
||||||
|
@ -75,7 +72,10 @@ def logout(request, next_page=None, template_name='registration/logged_out.html'
|
||||||
if redirect_to:
|
if redirect_to:
|
||||||
return HttpResponseRedirect(redirect_to)
|
return HttpResponseRedirect(redirect_to)
|
||||||
else:
|
else:
|
||||||
|
current_site = get_current_site(request)
|
||||||
return render_to_response(template_name, {
|
return render_to_response(template_name, {
|
||||||
|
'site': current_site,
|
||||||
|
'site_name': current_site.name,
|
||||||
'title': _('Logged out')
|
'title': _('Logged out')
|
||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
else:
|
else:
|
||||||
|
@ -115,12 +115,10 @@ def password_reset(request, is_admin_site=False, template_name='registration/pas
|
||||||
opts['use_https'] = request.is_secure()
|
opts['use_https'] = request.is_secure()
|
||||||
opts['token_generator'] = token_generator
|
opts['token_generator'] = token_generator
|
||||||
opts['from_email'] = from_email
|
opts['from_email'] = from_email
|
||||||
|
opts['email_template_name'] = email_template_name
|
||||||
|
opts['request'] = request
|
||||||
if is_admin_site:
|
if is_admin_site:
|
||||||
opts['domain_override'] = request.META['HTTP_HOST']
|
opts['domain_override'] = request.META['HTTP_HOST']
|
||||||
else:
|
|
||||||
opts['email_template_name'] = email_template_name
|
|
||||||
if not Site._meta.installed:
|
|
||||||
opts['domain_override'] = RequestSite(request).domain
|
|
||||||
form.save(**opts)
|
form.save(**opts)
|
||||||
return HttpResponseRedirect(post_reset_redirect)
|
return HttpResponseRedirect(post_reset_redirect)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,47 +1,69 @@
|
||||||
"""
|
from django import db
|
||||||
Make sure that the content type cache (see ContentTypeManager) works correctly.
|
from django.conf import settings
|
||||||
Lookups for a particular content type -- by model or by ID -- should hit the
|
from django.contrib.contenttypes.models import ContentType
|
||||||
database only on the first lookup.
|
from django.contrib.sites.models import Site
|
||||||
|
from django.contrib.contenttypes.views import shortcut
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.http import HttpRequest
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
First, let's make sure we're dealing with a blank slate (and that DEBUG is on so
|
|
||||||
that queries get logged)::
|
|
||||||
|
|
||||||
>>> from django.conf import settings
|
class ContentTypesTests(TestCase):
|
||||||
>>> settings.DEBUG = True
|
|
||||||
|
|
||||||
>>> from django.contrib.contenttypes.models import ContentType
|
def setUp(self):
|
||||||
>>> ContentType.objects.clear_cache()
|
# First, let's make sure we're dealing with a blank slate (and that
|
||||||
|
# DEBUG is on so that queries get logged)
|
||||||
|
self.old_DEBUG = settings.DEBUG
|
||||||
|
self.old_Site_meta_installed = Site._meta.installed
|
||||||
|
settings.DEBUG = True
|
||||||
|
ContentType.objects.clear_cache()
|
||||||
|
db.reset_queries()
|
||||||
|
|
||||||
>>> from django import db
|
def tearDown(self):
|
||||||
>>> db.reset_queries()
|
settings.DEBUG = self.old_DEBUG
|
||||||
|
Site._meta.installed = self.old_Site_meta_installed
|
||||||
|
|
||||||
At this point, a lookup for a ContentType should hit the DB::
|
def test_lookup_cache(self):
|
||||||
|
"""
|
||||||
|
Make sure that the content type cache (see ContentTypeManager)
|
||||||
|
works correctly. Lookups for a particular content type -- by model or
|
||||||
|
by ID -- should hit the database only on the first lookup.
|
||||||
|
"""
|
||||||
|
|
||||||
>>> ContentType.objects.get_for_model(ContentType)
|
# At this point, a lookup for a ContentType should hit the DB
|
||||||
<ContentType: content type>
|
ContentType.objects.get_for_model(ContentType)
|
||||||
|
self.assertEqual(1, len(db.connection.queries))
|
||||||
|
|
||||||
>>> len(db.connection.queries)
|
# A second hit, though, won't hit the DB, nor will a lookup by ID
|
||||||
1
|
ct = ContentType.objects.get_for_model(ContentType)
|
||||||
|
self.assertEqual(1, len(db.connection.queries))
|
||||||
|
ContentType.objects.get_for_id(ct.id)
|
||||||
|
self.assertEqual(1, len(db.connection.queries))
|
||||||
|
|
||||||
A second hit, though, won't hit the DB, nor will a lookup by ID::
|
# Once we clear the cache, another lookup will again hit the DB
|
||||||
|
ContentType.objects.clear_cache()
|
||||||
|
ContentType.objects.get_for_model(ContentType)
|
||||||
|
len(db.connection.queries)
|
||||||
|
self.assertEqual(2, len(db.connection.queries))
|
||||||
|
|
||||||
>>> ct = ContentType.objects.get_for_model(ContentType)
|
def test_shortcut_view(self):
|
||||||
>>> len(db.connection.queries)
|
"""
|
||||||
1
|
Check that the shortcut view (used for the admin "view on site"
|
||||||
>>> ContentType.objects.get_for_id(ct.id)
|
functionality) returns a complete URL regardless of whether the sites
|
||||||
<ContentType: content type>
|
framework is installed
|
||||||
>>> len(db.connection.queries)
|
"""
|
||||||
1
|
|
||||||
|
|
||||||
Once we clear the cache, another lookup will again hit the DB::
|
request = HttpRequest()
|
||||||
|
request.META = {
|
||||||
>>> ContentType.objects.clear_cache()
|
"SERVER_NAME": "Example.com",
|
||||||
>>> ContentType.objects.get_for_model(ContentType)
|
"SERVER_PORT": "80",
|
||||||
<ContentType: content type>
|
}
|
||||||
>>> len(db.connection.queries)
|
from django.contrib.auth.models import User
|
||||||
2
|
user_ct = ContentType.objects.get_for_model(User)
|
||||||
|
obj = User.objects.create(username="john")
|
||||||
Don't forget to reset DEBUG!
|
Site._meta.installed = True
|
||||||
|
response = shortcut(request, user_ct.id, obj.id)
|
||||||
>>> settings.DEBUG = False
|
self.assertEqual("http://example.com/users/john/", response._headers.get("location")[1])
|
||||||
"""
|
Site._meta.installed = False
|
||||||
|
response = shortcut(request, user_ct.id, obj.id)
|
||||||
|
self.assertEqual("http://Example.com/users/john/", response._headers.get("location")[1])
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
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
|
from django.contrib.sites.models import Site, get_current_site
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
def shortcut(request, content_type_id, object_id):
|
def shortcut(request, content_type_id, object_id):
|
||||||
|
@ -26,35 +26,37 @@ def shortcut(request, content_type_id, object_id):
|
||||||
# Otherwise, we need to introspect the object's relationships for a
|
# Otherwise, we need to introspect the object's relationships for a
|
||||||
# relation to the Site object
|
# relation to the Site object
|
||||||
object_domain = None
|
object_domain = None
|
||||||
opts = obj._meta
|
|
||||||
|
|
||||||
# First, look for an many-to-many relationship to Site.
|
if Site._meta.installed:
|
||||||
for field in opts.many_to_many:
|
opts = obj._meta
|
||||||
if field.rel.to is Site:
|
|
||||||
try:
|
|
||||||
# Caveat: In the case of multiple related Sites, this just
|
|
||||||
# selects the *first* one, which is arbitrary.
|
|
||||||
object_domain = getattr(obj, field.name).all()[0].domain
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
if object_domain is not None:
|
|
||||||
break
|
|
||||||
|
|
||||||
# Next, look for a many-to-one relationship to Site.
|
# First, look for an many-to-many relationship to Site.
|
||||||
if object_domain is None:
|
for field in opts.many_to_many:
|
||||||
for field in obj._meta.fields:
|
if field.rel.to is Site:
|
||||||
if field.rel and field.rel.to is Site:
|
|
||||||
try:
|
try:
|
||||||
object_domain = getattr(obj, field.name).domain
|
# Caveat: In the case of multiple related Sites, this just
|
||||||
except Site.DoesNotExist:
|
# selects the *first* one, which is arbitrary.
|
||||||
|
object_domain = getattr(obj, field.name).all()[0].domain
|
||||||
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
if object_domain is not None:
|
if object_domain is not None:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Next, look for a many-to-one relationship to Site.
|
||||||
|
if object_domain is None:
|
||||||
|
for field in obj._meta.fields:
|
||||||
|
if field.rel and field.rel.to is Site:
|
||||||
|
try:
|
||||||
|
object_domain = getattr(obj, field.name).domain
|
||||||
|
except Site.DoesNotExist:
|
||||||
|
pass
|
||||||
|
if object_domain is not None:
|
||||||
|
break
|
||||||
|
|
||||||
# Fall back to the current site (if possible).
|
# Fall back to the current site (if possible).
|
||||||
if object_domain is None:
|
if object_domain is None:
|
||||||
try:
|
try:
|
||||||
object_domain = Site.objects.get_current().domain
|
object_domain = get_current_site(request).domain
|
||||||
except Site.DoesNotExist:
|
except Site.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
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 Site
|
from django.contrib.sites.models 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
|
||||||
|
@ -15,7 +15,7 @@ def index(request, sitemaps):
|
||||||
This view generates a sitemap index that uses the proper view
|
This view generates a sitemap index that uses the proper view
|
||||||
for resolving geographic section sitemap URLs.
|
for resolving geographic section sitemap URLs.
|
||||||
"""
|
"""
|
||||||
current_site = Site.objects.get_current()
|
current_site = get_current_site(request)
|
||||||
sites = []
|
sites = []
|
||||||
protocol = request.is_secure() and 'https' or 'http'
|
protocol = request.is_secure() and 'https' or 'http'
|
||||||
for section, site in sitemaps.items():
|
for section, site in sitemaps.items():
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from django.contrib.sites.models import get_current_site
|
||||||
from django.core import urlresolvers, paginator
|
from django.core import urlresolvers, paginator
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
|
@ -60,8 +61,7 @@ class Sitemap(object):
|
||||||
paginator = property(_get_paginator)
|
paginator = property(_get_paginator)
|
||||||
|
|
||||||
def get_urls(self, page=1):
|
def get_urls(self, page=1):
|
||||||
from django.contrib.sites.models import Site
|
current_site = get_current_site(self.request)
|
||||||
current_site = Site.objects.get_current()
|
|
||||||
urls = []
|
urls = []
|
||||||
for item in self.paginator.page(page).object_list:
|
for item in self.paginator.page(page).object_list:
|
||||||
loc = "http://%s%s" % (current_site.domain, self.__get('location', item))
|
loc = "http://%s%s" % (current_site.domain, self.__get('location', item))
|
||||||
|
@ -77,9 +77,11 @@ class Sitemap(object):
|
||||||
|
|
||||||
class FlatPageSitemap(Sitemap):
|
class FlatPageSitemap(Sitemap):
|
||||||
def items(self):
|
def items(self):
|
||||||
from django.contrib.sites.models import Site
|
current_site = get_current_site(self.request)
|
||||||
current_site = Site.objects.get_current()
|
if hasattr(current_site, "flatpage_set"):
|
||||||
return current_site.flatpage_set.filter(registration_required=False)
|
return current_site.flatpage_set.filter(registration_required=False)
|
||||||
|
else:
|
||||||
|
return ()
|
||||||
|
|
||||||
class GenericSitemap(Sitemap):
|
class GenericSitemap(Sitemap):
|
||||||
priority = None
|
priority = None
|
||||||
|
|
|
@ -2,6 +2,7 @@ from datetime import date
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.flatpages.models import FlatPage
|
from django.contrib.flatpages.models import FlatPage
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils.formats import localize
|
from django.utils.formats import localize
|
||||||
from django.utils.translation import activate
|
from django.utils.translation import activate
|
||||||
|
@ -12,11 +13,13 @@ class SitemapTests(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.old_USE_L10N = settings.USE_L10N
|
self.old_USE_L10N = settings.USE_L10N
|
||||||
|
self.old_Site_meta_installed = Site._meta.installed
|
||||||
# Create a user that will double as sitemap content
|
# Create a user that will double as sitemap content
|
||||||
User.objects.create_user('testuser', 'test@example.com', 's3krit')
|
User.objects.create_user('testuser', 'test@example.com', 's3krit')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
settings.USE_L10N = self.old_USE_L10N
|
settings.USE_L10N = self.old_USE_L10N
|
||||||
|
Site._meta.installed = self.old_Site_meta_installed
|
||||||
|
|
||||||
def test_simple_sitemap(self):
|
def test_simple_sitemap(self):
|
||||||
"A simple sitemap can be rendered"
|
"A simple sitemap can be rendered"
|
||||||
|
@ -75,3 +78,16 @@ class SitemapTests(TestCase):
|
||||||
# Private flatpage should not be in the sitemap
|
# Private flatpage should not be in the sitemap
|
||||||
self.assertNotContains(response, '<loc>http://example.com%s</loc>' % private.url)
|
self.assertNotContains(response, '<loc>http://example.com%s</loc>' % private.url)
|
||||||
|
|
||||||
|
def test_requestsite_sitemap(self):
|
||||||
|
# Make sure hitting the flatpages sitemap without the sites framework
|
||||||
|
# installed doesn't raise an exception
|
||||||
|
Site._meta.installed = False
|
||||||
|
response = self.client.get('/flatpages/sitemap.xml')
|
||||||
|
# Retrieve the sitemap.
|
||||||
|
response = self.client.get('/simple/sitemap.xml')
|
||||||
|
# Check for all the important bits:
|
||||||
|
self.assertEquals(response.content, """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
<url><loc>http://testserver/location/</loc><lastmod>%s</lastmod><changefreq>never</changefreq><priority>0.5</priority></url>
|
||||||
|
</urlset>
|
||||||
|
""" % date.today().strftime('%Y-%m-%d'))
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
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 Site
|
from django.contrib.sites.models import get_current_site
|
||||||
from django.core import urlresolvers
|
from django.core import urlresolvers
|
||||||
from django.utils.encoding import smart_str
|
from django.utils.encoding import smart_str
|
||||||
from django.core.paginator import EmptyPage, PageNotAnInteger
|
from django.core.paginator import EmptyPage, PageNotAnInteger
|
||||||
|
|
||||||
def index(request, sitemaps):
|
def index(request, sitemaps):
|
||||||
current_site = Site.objects.get_current()
|
current_site = get_current_site(request)
|
||||||
sites = []
|
sites = []
|
||||||
protocol = request.is_secure() and 'https' or 'http'
|
protocol = request.is_secure() and 'https' or 'http'
|
||||||
for section, site in sitemaps.items():
|
for section, site in sitemaps.items():
|
||||||
|
site.request = request
|
||||||
if callable(site):
|
if callable(site):
|
||||||
pages = site().paginator.num_pages
|
pages = site().paginator.num_pages
|
||||||
else:
|
else:
|
||||||
|
@ -32,6 +33,7 @@ def sitemap(request, sitemaps, section=None):
|
||||||
maps = sitemaps.values()
|
maps = sitemaps.values()
|
||||||
page = request.GET.get("p", 1)
|
page = request.GET.get("p", 1)
|
||||||
for site in maps:
|
for site in maps:
|
||||||
|
site.request = request
|
||||||
try:
|
try:
|
||||||
if callable(site):
|
if callable(site):
|
||||||
urls.extend(site().get_urls(page))
|
urls.extend(site().get_urls(page))
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
SITE_CACHE = {}
|
SITE_CACHE = {}
|
||||||
|
|
||||||
|
|
||||||
class SiteManager(models.Manager):
|
class SiteManager(models.Manager):
|
||||||
|
|
||||||
def get_current(self):
|
def get_current(self):
|
||||||
"""
|
"""
|
||||||
Returns the current ``Site`` based on the SITE_ID in the
|
Returns the current ``Site`` based on the SITE_ID in the
|
||||||
|
@ -28,7 +31,9 @@ class SiteManager(models.Manager):
|
||||||
global SITE_CACHE
|
global SITE_CACHE
|
||||||
SITE_CACHE = {}
|
SITE_CACHE = {}
|
||||||
|
|
||||||
|
|
||||||
class Site(models.Model):
|
class Site(models.Model):
|
||||||
|
|
||||||
domain = models.CharField(_('domain name'), max_length=100)
|
domain = models.CharField(_('domain name'), max_length=100)
|
||||||
name = models.CharField(_('display name'), max_length=50)
|
name = models.CharField(_('display name'), max_length=50)
|
||||||
objects = SiteManager()
|
objects = SiteManager()
|
||||||
|
@ -56,6 +61,7 @@ class Site(models.Model):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class RequestSite(object):
|
class RequestSite(object):
|
||||||
"""
|
"""
|
||||||
A class that shares the primary interface of Site (i.e., it has
|
A class that shares the primary interface of Site (i.e., it has
|
||||||
|
@ -75,3 +81,15 @@ class RequestSite(object):
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
raise NotImplementedError('RequestSite cannot be deleted.')
|
raise NotImplementedError('RequestSite cannot be deleted.')
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -1,29 +1,56 @@
|
||||||
"""
|
from django.conf import settings
|
||||||
>>> from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site, RequestSite, get_current_site
|
||||||
>>> from django.conf import settings
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
>>> Site(id=settings.SITE_ID, domain="example.com", name="example.com").save()
|
from django.http import HttpRequest
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
# Make sure that get_current() does not return a deleted Site object.
|
|
||||||
>>> s = Site.objects.get_current()
|
|
||||||
>>> isinstance(s, Site)
|
|
||||||
True
|
|
||||||
|
|
||||||
>>> s.delete()
|
class SitesFrameworkTests(TestCase):
|
||||||
>>> Site.objects.get_current()
|
|
||||||
Traceback (most recent call last):
|
|
||||||
...
|
|
||||||
DoesNotExist: Site matching query does not exist.
|
|
||||||
|
|
||||||
# After updating a Site object (e.g. via the admin), we shouldn't return a
|
def setUp(self):
|
||||||
# bogus value from the SITE_CACHE.
|
Site(id=settings.SITE_ID, domain="example.com", name="example.com").save()
|
||||||
>>> _ = Site.objects.create(id=settings.SITE_ID, domain="example.com", name="example.com")
|
self.old_Site_meta_installed = Site._meta.installed
|
||||||
>>> site = Site.objects.get_current()
|
Site._meta.installed = True
|
||||||
>>> site.name
|
|
||||||
u"example.com"
|
def tearDown(self):
|
||||||
>>> s2 = Site.objects.get(id=settings.SITE_ID)
|
Site._meta.installed = self.old_Site_meta_installed
|
||||||
>>> s2.name = "Example site"
|
|
||||||
>>> s2.save()
|
def test_site_manager(self):
|
||||||
>>> site = Site.objects.get_current()
|
# Make sure that get_current() does not return a deleted Site object.
|
||||||
>>> site.name
|
s = Site.objects.get_current()
|
||||||
u"Example site"
|
self.assert_(isinstance(s, Site))
|
||||||
"""
|
s.delete()
|
||||||
|
self.assertRaises(ObjectDoesNotExist, Site.objects.get_current)
|
||||||
|
|
||||||
|
def test_site_cache(self):
|
||||||
|
# After updating a Site object (e.g. via the admin), we shouldn't return a
|
||||||
|
# bogus value from the SITE_CACHE.
|
||||||
|
site = Site.objects.get_current()
|
||||||
|
self.assertEqual(u"example.com", site.name)
|
||||||
|
s2 = Site.objects.get(id=settings.SITE_ID)
|
||||||
|
s2.name = "Example site"
|
||||||
|
s2.save()
|
||||||
|
site = Site.objects.get_current()
|
||||||
|
self.assertEqual(u"Example site", site.name)
|
||||||
|
|
||||||
|
def test_get_current_site(self):
|
||||||
|
# Test that the correct Site object is returned
|
||||||
|
request = HttpRequest()
|
||||||
|
request.META = {
|
||||||
|
"SERVER_NAME": "example.com",
|
||||||
|
"SERVER_PORT": "80",
|
||||||
|
}
|
||||||
|
site = get_current_site(request)
|
||||||
|
self.assert_(isinstance(site, Site))
|
||||||
|
self.assertEqual(site.id, settings.SITE_ID)
|
||||||
|
|
||||||
|
# Test that an exception is raised if the sites framework is installed
|
||||||
|
# but there is no matching Site
|
||||||
|
site.delete()
|
||||||
|
self.assertRaises(ObjectDoesNotExist, get_current_site, request)
|
||||||
|
|
||||||
|
# A RequestSite is returned if the sites framework is not installed
|
||||||
|
Site._meta.installed = False
|
||||||
|
site = get_current_site(request)
|
||||||
|
self.assert_(isinstance(site, RequestSite))
|
||||||
|
self.assertEqual(site.name, u"example.com")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import datetime
|
import datetime
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.sites.models import Site, RequestSite
|
from django.contrib.sites.models 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, Template, TemplateDoesNotExist, RequestContext
|
from django.template import loader, Template, TemplateDoesNotExist, RequestContext
|
||||||
|
@ -91,10 +91,7 @@ class Feed(object):
|
||||||
Returns a feedgenerator.DefaultFeed object, fully populated, for
|
Returns a feedgenerator.DefaultFeed object, fully populated, for
|
||||||
this feed. Raises FeedDoesNotExist for invalid parameters.
|
this feed. Raises FeedDoesNotExist for invalid parameters.
|
||||||
"""
|
"""
|
||||||
if Site._meta.installed:
|
current_site = get_current_site(request)
|
||||||
current_site = Site.objects.get_current()
|
|
||||||
else:
|
|
||||||
current_site = RequestSite(request)
|
|
||||||
|
|
||||||
link = self.__get_dynamic_attr('link', obj)
|
link = self.__get_dynamic_attr('link', obj)
|
||||||
link = add_domain(current_site.domain, link)
|
link = add_domain(current_site.domain, link)
|
||||||
|
|
|
@ -107,7 +107,7 @@ This has the same benefits as described in the last section.
|
||||||
Hooking into the current site from views
|
Hooking into the current site from views
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
On a lower level, you can use the sites framework in your Django views to do
|
You can use the sites framework in your Django views to do
|
||||||
particular things based on the site in which the view is being called.
|
particular things based on the site in which the view is being called.
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
|
@ -148,6 +148,16 @@ the :class:`~django.contrib.sites.models.Site` model's manager has a
|
||||||
else:
|
else:
|
||||||
# Do something else.
|
# Do something else.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.3
|
||||||
|
|
||||||
|
For code which relies on getting the current domain but cannot be certain
|
||||||
|
that the sites framework will be installed for any given project, there is a
|
||||||
|
utility function :func:`~django.contrib.sites.models.get_current_site` that
|
||||||
|
takes a request object as an argument and returns either a Site instance (if
|
||||||
|
the sites framework is installed) or a RequestSite instance (if it is not).
|
||||||
|
This allows loose coupling with the sites framework and provides a usable
|
||||||
|
fallback for cases where it is not installed.
|
||||||
|
|
||||||
Getting the current domain for display
|
Getting the current domain for display
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue