Source code for mezzanine.utils.sites

from __future__ import unicode_literals

import os
import sys
import threading
from contextlib import contextmanager

from django.contrib.sites.models import Site

from mezzanine.conf import settings
from mezzanine.core.request import current_request
from mezzanine.utils.conf import middlewares_or_subclasses_installed


SITE_PERMISSION_MIDDLEWARE = \
    "mezzanine.core.middleware.SitePermissionMiddleware"


[docs]def current_site_id(): """ Responsible for determining the current ``Site`` instance to use when retrieving data for any ``SiteRelated`` models. If we're inside an override_current_site_id context manager, return the overriding site ID. Otherwise, try to determine the site using the following methods in order: - ``site_id`` in session. Used in the admin so that admin users can switch sites and stay on the same domain for the admin. - The id of the Site object corresponding to the hostname in the current request. This result is cached. - ``MEZZANINE_SITE_ID`` environment variable, so management commands or anything else outside of a request can specify a site. - ``SITE_ID`` setting. If a current request exists and the current site is not overridden, the site ID is stored on the request object to speed up subsequent calls. """ if hasattr(override_current_site_id.thread_local, "site_id"): return override_current_site_id.thread_local.site_id from mezzanine.utils.cache import cache_installed, cache_get, cache_set request = current_request() site_id = getattr(request, "site_id", None) if request and not site_id: site_id = request.session.get("site_id", None) if not site_id: domain = request.get_host().lower() if cache_installed(): # Don't use Mezzanine's cache_key_prefix here, since it # uses this very function we're in right now to create a # per-site cache key. bits = (settings.CACHE_MIDDLEWARE_KEY_PREFIX, domain) cache_key = "%s.site_id.%s" % bits site_id = cache_get(cache_key) if not site_id: try: site = Site.objects.get(domain__iexact=domain) except Site.DoesNotExist: pass else: site_id = site.id if cache_installed(): cache_set(cache_key, site_id) if not site_id: site_id = os.environ.get("MEZZANINE_SITE_ID", settings.SITE_ID) if request and site_id and not getattr(settings, "TESTING", False): request.site_id = site_id return site_id
[docs]@contextmanager def override_current_site_id(site_id): """ Context manager that overrides the current site id for code executed within it. Used to access SiteRelated objects outside the current site. """ override_current_site_id.thread_local.site_id = site_id yield del override_current_site_id.thread_local.site_id
override_current_site_id.thread_local = threading.local()
[docs]def has_site_permission(user): """ Checks if a staff user has staff-level access for the current site. The actual permission lookup occurs in ``SitePermissionMiddleware`` which then marks the request with the ``has_site_permission`` flag, so that we only query the db once per request, so this function serves as the entry point for everything else to check access. We also fall back to an ``is_staff`` check if the middleware is not installed, to ease migration. """ if not middlewares_or_subclasses_installed([SITE_PERMISSION_MIDDLEWARE]): return user.is_staff and user.is_active return getattr(user, "has_site_permission", False)
[docs]def host_theme_path(): """ Returns the directory of the theme associated with the given host. """ # Set domain to None, which we'll then query for in the first # iteration of HOST_THEMES. We use the current site_id rather # than a request object here, as it may differ for admin users. domain = None for (host, theme) in settings.HOST_THEMES: if domain is None: domain = Site.objects.get(id=current_site_id()).domain if host.lower() == domain.lower(): try: __import__(theme) module = sys.modules[theme] except ImportError: pass else: return os.path.dirname(os.path.abspath(module.__file__)) return ""