Source code for mezzanine.pages.admin

from __future__ import unicode_literals

from copy import deepcopy

from django.contrib import admin
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404

from mezzanine.conf import settings
from mezzanine.core.admin import (
    ContentTypedAdmin, DisplayableAdmin, DisplayableAdminForm)
from mezzanine.pages.models import Page, RichTextPage, Link
from mezzanine.utils.urls import clean_slashes


# Add extra fields for pages to the Displayable fields.
# We only add the menu field if PAGE_MENU_TEMPLATES has values.
page_fieldsets = deepcopy(DisplayableAdmin.fieldsets)
if settings.PAGE_MENU_TEMPLATES:
    page_fieldsets[0][1]["fields"] += ("in_menus",)
page_fieldsets[0][1]["fields"] += ("login_required",)


class PageAdminForm(DisplayableAdminForm):

    def clean_slug(self):
        """
        Save the old slug to be used later in PageAdmin.save_model()
        to make the slug change propagate down the page tree, and clean
        leading and trailing slashes which are added on elsewhere.
        """
        self.instance._old_slug = self.instance.slug
        new_slug = self.cleaned_data['slug']
        if not isinstance(self.instance, Link) and new_slug != "/":
            new_slug = clean_slashes(self.cleaned_data['slug'])
        return new_slug


[docs]class PageAdmin(ContentTypedAdmin, DisplayableAdmin): """ Admin class for the ``Page`` model and all subclasses of ``Page``. Handles redirections between admin interfaces for the ``Page`` model and its subclasses. """ form = PageAdminForm fieldsets = page_fieldsets change_list_template = "admin/pages/page/change_list.html"
[docs] def check_permission(self, request, page, permission): """ Runs the custom permission check and raises an exception if False. """ if not getattr(page, "can_" + permission)(request): raise PermissionDenied
[docs] def add_view(self, request, **kwargs): """ For the ``Page`` model, redirect to the add view for the first page model, based on the ``ADD_PAGE_ORDER`` setting. """ if self.model is Page: return HttpResponseRedirect(self.get_content_models()[0].add_url) return super(PageAdmin, self).add_view(request, **kwargs)
[docs] def change_view(self, request, object_id, **kwargs): """ Enforce custom permissions for the page instance. """ page = get_object_or_404(Page, pk=object_id) content_model = page.get_content_model() kwargs.setdefault("extra_context", {}) kwargs["extra_context"].update({ "hide_delete_link": not content_model.can_delete(request), "hide_slug_field": content_model.overridden(), }) return super(PageAdmin, self).change_view(request, object_id, **kwargs)
[docs] def delete_view(self, request, object_id, **kwargs): """ Enforce custom delete permissions for the page instance. """ page = get_object_or_404(Page, pk=object_id) content_model = page.get_content_model() self.check_permission(request, content_model, "delete") return super(PageAdmin, self).delete_view(request, object_id, **kwargs)
[docs] def save_model(self, request, obj, form, change): """ Set the ID of the parent page if passed in via querystring, and make sure the new slug propagates to all descendant pages. """ if change and obj._old_slug != obj.slug: # _old_slug was set in PageAdminForm.clean_slug(). new_slug = obj.slug or obj.generate_unique_slug() obj.slug = obj._old_slug obj.set_slug(new_slug) # Force parent to be saved to trigger handling of ordering and slugs. parent = request.GET.get("parent") if parent is not None and not change: obj.parent_id = parent obj.save() super(PageAdmin, self).save_model(request, obj, form, change)
def _maintain_parent(self, request, response): """ Maintain the parent ID in the querystring for response_add and response_change. """ location = response._headers.get("location") parent = request.GET.get("parent") if parent and location and "?" not in location[1]: url = "%s?parent=%s" % (location[1], parent) return HttpResponseRedirect(url) return response
[docs] def response_add(self, request, obj): """ Enforce page permissions and maintain the parent ID in the querystring. """ response = super(PageAdmin, self).response_add(request, obj) return self._maintain_parent(request, response)
[docs] def response_change(self, request, obj): """ Enforce page permissions and maintain the parent ID in the querystring. """ response = super(PageAdmin, self).response_change(request, obj) return self._maintain_parent(request, response)
[docs] def get_content_models(self): """ Return all Page subclasses that are admin registered, ordered based on the ``ADD_PAGE_ORDER`` setting. """ models = super(PageAdmin, self).get_content_models() order = [name.lower() for name in settings.ADD_PAGE_ORDER] def sort_key(page): name = "%s.%s" % (page._meta.app_label, page._meta.object_name) unordered = len(order) try: return (order.index(name.lower()), "") except ValueError: return (unordered, page.meta_verbose_name) return sorted(models, key=sort_key)
# Drop the meta data fields, and move slug towards the stop. link_fieldsets = deepcopy(page_fieldsets[:1]) link_fieldsets[0][1]["fields"] = link_fieldsets[0][1]["fields"][:-1] link_fieldsets[0][1]["fields"].insert(1, "slug") class LinkAdmin(PageAdmin): fieldsets = link_fieldsets def formfield_for_dbfield(self, db_field, **kwargs): """ Make slug mandatory. """ if db_field.name == "slug": kwargs["required"] = True kwargs["help_text"] = None return super(LinkAdmin, self).formfield_for_dbfield(db_field, **kwargs) def save_form(self, request, form, change): """ Don't show links in the sitemap. """ obj = form.save(commit=False) if not obj.id and "in_sitemap" not in form.fields: obj.in_sitemap = False return super(LinkAdmin, self).save_form(request, form, change) admin.site.register(Page, PageAdmin) admin.site.register(RichTextPage, PageAdmin) admin.site.register(Link, LinkAdmin)