Source code for mezzanine.core.views

from __future__ import absolute_import, unicode_literals
from future.builtins import int, open, str

import os
import mimetypes

from json import dumps

from django.template.response import TemplateResponse

try:
    from urllib.parse import urljoin, urlparse
except ImportError:
    from urlparse import urljoin, urlparse

from django.apps import apps
from django.contrib import admin
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.admin.options import ModelAdmin
from django.contrib.staticfiles import finders
from django.core.exceptions import PermissionDenied
from django.urls import reverse
from django.http import (HttpResponse, HttpResponseServerError,
                         HttpResponseNotFound)
from django.shortcuts import redirect
from django.template.loader import get_template
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.csrf import requires_csrf_token

from mezzanine.conf import settings
from mezzanine.core.forms import get_edit_form
from mezzanine.core.models import Displayable, SitePermission
from mezzanine.utils.views import is_editable, paginate
from mezzanine.utils.sites import has_site_permission
from mezzanine.utils.urls import next_url


mimetypes.init()


[docs]@staff_member_required def set_site(request): """ Put the selected site ID into the session - posted to from the "Select site" drop-down in the header of the admin. The site ID is then used in favour of the current request's domain in ``mezzanine.core.managers.CurrentSiteManager``. """ site_id = int(request.GET["site_id"]) if not request.user.is_superuser: try: SitePermission.objects.get(user=request.user, sites=site_id) except SitePermission.DoesNotExist: raise PermissionDenied request.session["site_id"] = site_id admin_url = reverse("admin:index") next = next_url(request) or admin_url # Don't redirect to a change view for an object that won't exist # on the selected site - go to its list view instead. if next.startswith(admin_url): parts = next.split("/") if len(parts) > 4 and parts[4].isdigit(): next = "/".join(parts[:4]) return redirect(next)
[docs]def direct_to_template(request, template, extra_context=None, **kwargs): """ Replacement for Django's ``direct_to_template`` that uses ``TemplateResponse`` via ``mezzanine.utils.views.render``. """ context = extra_context or {} context["params"] = kwargs for (key, value) in context.items(): if callable(value): context[key] = value() return TemplateResponse(request, template, context)
[docs]@staff_member_required def edit(request): """ Process the inline editing form. """ model = apps.get_model(request.POST["app"], request.POST["model"]) obj = model.objects.get(id=request.POST["id"]) form = get_edit_form(obj, request.POST["fields"], data=request.POST, files=request.FILES) if not (is_editable(obj, request) and has_site_permission(request.user)): response = _("Permission denied") elif form.is_valid(): form.save() model_admin = ModelAdmin(model, admin.site) message = model_admin.construct_change_message(request, form, None) model_admin.log_change(request, obj, message) response = "" else: response = list(form.errors.values())[0][0] return HttpResponse(response)
[docs]@staff_member_required def static_proxy(request): """ Serves TinyMCE plugins inside the inline popups and the uploadify SWF, as these are normally static files, and will break with cross-domain JavaScript errors if ``STATIC_URL`` is an external host. URL for the file is passed in via querystring in the inline popup plugin template, and we then attempt to pull out the relative path to the file, so that we can serve it locally via Django. """ normalize = lambda u: ("//" + u.split("://")[-1]) if "://" in u else u url = normalize(request.GET["u"]) host = "//" + request.get_host() static_url = normalize(settings.STATIC_URL) for prefix in (host, static_url, "/"): if url.startswith(prefix): url = url.replace(prefix, "", 1) response = "" (content_type, encoding) = mimetypes.guess_type(url) if content_type is None: content_type = "application/octet-stream" path = finders.find(url) if path: if isinstance(path, (list, tuple)): path = path[0] if url.endswith(".htm"): # Inject <base href="{{ STATIC_URL }}"> into TinyMCE # plugins, since the path static files in these won't be # on the same domain. static_url = settings.STATIC_URL + os.path.split(url)[0] + "/" if not urlparse(static_url).scheme: static_url = urljoin(host, static_url) base_tag = "<base href='%s'>" % static_url with open(path, "r") as f: response = f.read().replace("<head>", "<head>" + base_tag) else: try: with open(path, "rb") as f: response = f.read() except IOError: return HttpResponseNotFound() return HttpResponse(response, content_type=content_type)
[docs]@requires_csrf_token def page_not_found(request, *args, **kwargs): """ Mimics Django's 404 handler but with a different template path. """ context = { "STATIC_URL": settings.STATIC_URL, "request_path": request.path, } t = get_template(kwargs.get("template_name", "errors/404.html")) return HttpResponseNotFound(t.render(context, request))
[docs]@requires_csrf_token def server_error(request, template_name="errors/500.html"): """ Mimics Django's error handler but adds ``STATIC_URL`` to the context. """ context = {"STATIC_URL": settings.STATIC_URL} t = get_template(template_name) return HttpResponseServerError(t.render(context, request))