<commit_before>"""
The upgraded CMS online admin area.

This is an enhanced version of the Django admin area, providing a more
user-friendly appearance and providing additional functionality over the
standard implementation.
"""

from __future__ import with_statement

from django.contrib import admin
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.conf.urls import patterns, url
from django.contrib.contenttypes.models import ContentType
from django.db import transaction
from django.db.models import F
from django.http import Http404, HttpResponseRedirect, HttpResponse, HttpResponseForbidden
from django.shortcuts import render, redirect, get_object_or_404
from django import forms
from django.utils import simplejson as json

from cms import debug, externals
from cms.admin import PageBaseAdmin
from cms.apps.pages.models import Page, get_registered_content, PageSearchAdapter


# Used to track references to and from the JS sitemap.
PAGE_FROM_KEY = "from"
PAGE_FROM_SITEMAP_VALUE = "sitemap"


# The GET parameter used to indicate content type.
PAGE_TYPE_PARAMETER = "type"
    
    
class PageAdmin(PageBaseAdmin):

    """Admin settings for Page models."""

    fieldsets = (
        (None, {
            "fields": ("title", "url_title", "parent",),
        },),
        ("Publication", {
            "fields": ("publication_date", "expiry_date", "is_online",),
            "classes": ("collapse",),
        }),
        ("Navigation", {
            "fields": ("short_title", "in_navigation",),
            "classes": ("collapse",),
        }),
        PageBaseAdmin.SEO_FIELDS,
    )
    
    search_adapter_cls = PageSearchAdapter
    
    def _register_page_inline(self, model):
        """Registeres the given page inline with reversion."""
        if externals.reversion:
            self._autoregister(model, follow=["page"])
            adapter = self.revision_manager.get_adapter(Page)
            adapter.follow = tuple(adapter.follow) + (model._meta.get_field("page").related.get_accessor_name(),)
    
    def __init__(self, *args, **kwargs):
        """Initialzies the PageAdmin."""
        super(PageAdmin, self).__init__(*args, **kwargs)
        # Patch the admin class's index template.
        self.admin_site.index_template = "admin/pages/dashboard.html"
        # Prepare to register some content inlines.
        self.content_inlines = []
        # Register all page inlines.
        for content_cls in get_registered_content():
            self._register_page_inline(content_cls)
    
    def register_content_inline(self, content_cls, inline_admin):
        """Registers an inline model with the page admin."""
        self.content_inlines.append((content_cls, inline_admin))
        self._register_page_inline(inline_admin.model)
    
    def get_inline_instances(self, request):
        """Returns all the inline instances for this PageAdmin."""
        inline_instances = super(PageAdmin, self).get_inline_instances(request)
        # Add on the relevant content inlines.
        obj = getattr(request, "_admin_change_obj", None)  # HACK: Retrieve the page from the change view.
        content_cls = self.get_page_content_cls(request, obj)
        for cls, inline in self.content_inlines:
            if cls == content_cls:
                inline_instances.append(inline(self.model, self.admin_site))
        # All done!
        return inline_instances
                
    # Reversion
    
    def get_revision_instances(self, request, object):
        """Returns all the instances to be used in this object's revision."""
        instances = super(PageAdmin, self).get_revision_instances(request, object)
        # Add the content object.
        instances.append(object.content)
        # Add all the content inlines.
        for _, inline in self.content_inlines:
            instances.extend(inline.model._default_manager.filter(page=object))
        return instances
    
    def get_revision_form_data(self, request, obj, version):
        """
        Returns a dictionary of data to set in the admin form in order to revert
        to the given revision.
        """
        data = super(PageAdmin, self).get_revision_form_data(request, obj, version)
        content_version = version.revision.version_set.all().get(
            content_type = obj.content_type_id,
            object_id_int = obj.pk,
        )
        data.update(content_version.field_dict)
        return data

    # Plugable content types.

    def get_page_content_cls(self, request, obj=None):
        """Retrieves the page content type slug."""
        if PAGE_TYPE_PARAMETER in request.GET:
            return ContentType.objects.get_for_id(request.GET[PAGE_TYPE_PARAMETER]).model_class()
        if obj and obj.content_type:
            return obj.content_type.model_class()
        raise Http404, "You must specify a page content type."

    def get_fieldsets(self, request, obj=None):
        """Generates the custom content fieldsets."""
        content_cls = self.get_page_content_cls(request, obj)
        content_fields = [field.name for field in content_cls._meta.fields if field.name != "page"]
        fieldsets = super(PageAdmin, self).get_fieldsets(request, obj)
        if content_fields:
            content_fieldsets = content_cls.fieldsets or (
                ("Page content", {
                    "fields": content_fields,
                }),
            )
            fieldsets = tuple(fieldsets[0:1]) + content_fieldsets + tuple(fieldsets[1:])
        return fieldsets

    def get_all_children(self, page):
        """Returns all the children for a page."""
        children = []
        def do_get_all_children(page):
            for child in page.children:
                children.append(child)
                do_get_all_children(child)
        do_get_all_children(page)
        return children

    def get_breadcrumbs(self, page):
        """Returns all breadcrumbs for a page."""
        breadcrumbs = []
        while page:
            breadcrumbs.append(page)
            page = page.parent
        breadcrumbs.reverse()
        return breadcrumbs

    def get_form(self, request, obj=None, **kwargs):
        """Adds the template area fields to the form."""
        content_cls = self.get_page_content_cls(request, obj)
        form_attrs = {}
        for field in content_cls._meta.fields:
            if field.name == "page":
                continue
            form_field = self.formfield_for_dbfield(field, request=request)<commit_msg>Added support for ManyToMany fields as well as applying filter_horizontal to them.<commit_after>"""
The upgraded CMS online admin area.

This is an enhanced version of the Django admin area, providing a more
user-friendly appearance and providing additional functionality over the
standard implementation.
"""

from __future__ import with_statement

from django.contrib import admin
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.conf.urls import patterns, url
from django.contrib.contenttypes.models import ContentType
from django.db import transaction
from django.db.models import F
from django.http import Http404, HttpResponseRedirect, HttpResponse, HttpResponseForbidden
from django.shortcuts import render, redirect, get_object_or_404
from django import forms
from django.utils import simplejson as json

from cms import debug, externals
from cms.admin import PageBaseAdmin
from cms.apps.pages.models import Page, get_registered_content, PageSearchAdapter


# Used to track references to and from the JS sitemap.
PAGE_FROM_KEY = "from"
PAGE_FROM_SITEMAP_VALUE = "sitemap"


# The GET parameter used to indicate content type.
PAGE_TYPE_PARAMETER = "type"
    
    
class PageAdmin(PageBaseAdmin):

    """Admin settings for Page models."""

    fieldsets = (
        (None, {
            "fields": ("title", "url_title", "parent",),
        },),
        ("Publication", {
            "fields": ("publication_date", "expiry_date", "is_online",),
            "classes": ("collapse",),
        }),
        ("Navigation", {
            "fields": ("short_title", "in_navigation",),
            "classes": ("collapse",),
        }),
        PageBaseAdmin.SEO_FIELDS,
    )
    
    search_adapter_cls = PageSearchAdapter
    
    def _register_page_inline(self, model):
        """Registeres the given page inline with reversion."""
        if externals.reversion:
            self._autoregister(model, follow=["page"])
            adapter = self.revision_manager.get_adapter(Page)
            adapter.follow = tuple(adapter.follow) + (model._meta.get_field("page").related.get_accessor_name(),)
    
    def __init__(self, *args, **kwargs):
        """Initialzies the PageAdmin."""
        super(PageAdmin, self).__init__(*args, **kwargs)
        # Patch the admin class's index template.
        self.admin_site.index_template = "admin/pages/dashboard.html"
        # Prepare to register some content inlines.
        self.content_inlines = []
        # Register all page inlines.
        for content_cls in get_registered_content():
            self._register_page_inline(content_cls)
    
    def register_content_inline(self, content_cls, inline_admin):
        """Registers an inline model with the page admin."""
        self.content_inlines.append((content_cls, inline_admin))
        self._register_page_inline(inline_admin.model)
    
    def get_inline_instances(self, request):
        """Returns all the inline instances for this PageAdmin."""
        inline_instances = super(PageAdmin, self).get_inline_instances(request)
        # Add on the relevant content inlines.
        obj = getattr(request, "_admin_change_obj", None)  # HACK: Retrieve the page from the change view.
        content_cls = self.get_page_content_cls(request, obj)
        for cls, inline in self.content_inlines:
            if cls == content_cls:
                inline_instances.append(inline(self.model, self.admin_site))
        # All done!
        return inline_instances
                
    # Reversion
    
    def get_revision_instances(self, request, object):
        """Returns all the instances to be used in this object's revision."""
        instances = super(PageAdmin, self).get_revision_instances(request, object)
        # Add the content object.
        instances.append(object.content)
        # Add all the content inlines.
        for _, inline in self.content_inlines:
            instances.extend(inline.model._default_manager.filter(page=object))
        return instances
    
    def get_revision_form_data(self, request, obj, version):
        """
        Returns a dictionary of data to set in the admin form in order to revert
        to the given revision.
        """
        data = super(PageAdmin, self).get_revision_form_data(request, obj, version)
        content_version = version.revision.version_set.all().get(
            content_type = obj.content_type_id,
            object_id_int = obj.pk,
        )
        data.update(content_version.field_dict)
        return data

    # Plugable content types.

    def get_page_content_cls(self, request, obj=None):
        """Retrieves the page content type slug."""
        if PAGE_TYPE_PARAMETER in request.GET:
            return ContentType.objects.get_for_id(request.GET[PAGE_TYPE_PARAMETER]).model_class()
        if obj and obj.content_type:
            return obj.content_type.model_class()
        raise Http404, "You must specify a page content type."

    def get_fieldsets(self, request, obj=None):
        """Generates the custom content fieldsets."""
        content_cls = self.get_page_content_cls(request, obj)
        content_fields = [field.name for field in content_cls._meta.fields + content_cls._meta.many_to_many if field.name != "page"]
        fieldsets = super(PageAdmin, self).get_fieldsets(request, obj)
        if content_fields:
            content_fieldsets = content_cls.fieldsets or (
                ("Page content", {
                    "fields": content_fields,
                }),
            )
            fieldsets = tuple(fieldsets[0:1]) + content_fieldsets + tuple(fieldsets[1:])
        if getattr(content_cls, "filter_horizontal", ""):
            self.filter_horizontal = content_cls.filter_horizontal
        return fieldsets

    def get_all_children(self, page):
        """Returns all the children for a page."""
        children = []
        def do_get_all_children(page):
            for child in page.children:
                children.append(child)
                do_get_all_children(child)
        do_get_all_children(page)
        return children

    def get_breadcrumbs(self, page):
        """Returns all breadcrumbs for a page."""
        breadcrumbs = []
        while page:
            breadcrumbs.append(page)
            page = page.parent
        breadcrumbs.reverse()
        return breadcrumbs

    def get_form(self, request, obj=None, **kwargs):
        """Adds the template area fields to the form."""
        content_cls = self.get_page_content_cls(request, obj)
        form_attrs = {}
        for field in content_cls._meta.fields + content_cls._meta.many_to_many:
            if field.name == "page":
                continue
            form_field = self.formfield_for_dbfield(field, request=request)
{'fraction_non_alphanumeric': 0.09113374269881683, 'fraction_numerical': 0.0017972143178073986, 'mean_word_length': 2.7535132096683532, 'pattern_counts': {'":': 14, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2105398', 'n_tokens_mistral': 3658, 'n_tokens_neox': 3630, 'n_words': 993}