Source code for pagetools.menus.admin

from django import forms
from django.conf import settings
from django.contrib import admin
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.http.response import HttpResponseRedirect
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _

from pagetools.admin import TinyMCEMixin
from pagetools.utils import get_adminadd_url, get_classname

from .apps import MenusConfig
from .models import AutoPopulated, Link, Menu, MenuCache, MenuEntry, ViewLink














[docs]class EntrieableForm(forms.ModelForm): """Adds a field: menus to the form. Preselect all menus which contain an entry for the obj """ menus = forms.Field() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.existing_menuentries = [] self.sel_menus = None menus = [(m.id, "%s" % m) for m in Menu.objects.root_nodes()] try: entry = kwargs["instance"] content_type = ContentType.objects.get_for_model(entry) containing_menus = MenuEntry.objects.filter(content_type=content_type, object_id=entry.id) menuroot_ids = {menu.get_root().id for menu in containing_menus} except (KeyError, AttributeError): menuroot_ids = set() self.fields["menus"] = forms.MultipleChoiceField( label=_("Menus"), choices=menus, required=False, initial=list(menuroot_ids), widget=forms.CheckboxSelectMultiple, )
[docs] def clean(self): cleaned_data = super().clean() if self.instance and "menus" in self.changed_data: obj = self.instance cmp_data = self.cleaned_data.copy() fmenu_ids = [int(m) for m in cmp_data.pop("menus", [])] self.sel_menus = Menu.objects.filter(id__in=fmenu_ids) existing_menuentries_for_obj = MenuEntry.objects.filter( content_type=ContentType.objects.get_for_model(obj.__class__), object_id=obj.pk, ) for entry in existing_menuentries_for_obj: entry.clean() self.existing_menuentries.append(entry) return cleaned_data
[docs] class Media(TinyMCEMixin.Media): js = TinyMCEMixin.Media.js + [settings.STATIC_URL + "pagetools/admin/js/pre_sel_menu.js"]
[docs]class EntrieableAdmin(admin.ModelAdmin): form = EntrieableForm is_menu_entrieable = True
[docs] def get_fields(self, request, obj=None): """ See :func:`pagetools.menus.admin.entrieable_admin_get_fields` """ superfunc = super(self.__class__, self).get_fields if not getattr(superfunc, "for_entrieable", False): fields = superfunc(request, obj) else: fields = admin.ModelAdmin.get_fields(self, request, obj) if "menus" not in fields: fields = fields + type(fields)(("menus",)) return fields
get_fields.for_entrieable = True # type: ignore
[docs] def get_fieldsets(self, request, obj=None): superfunc = super(self.__class__, self).get_fieldsets if not getattr(superfunc, "for_entrieable", False): self.fieldsets = superfunc(request, obj) else: self.fieldsets = super().get_fieldsets(request, obj) added = False for fieldset in self.fieldsets: if "menus" in fieldset[1]["fields"]: added = True break if not added: self.fieldsets = self.fieldsets + type(self.fieldsets)(((_("In menus"), {"fields": ["menus"]}),)) return self.fieldsets
get_fieldsets.for_entrieable = True # type: ignore save_related.for_entrieable = True # type: ignore def _redirect(self, action, request, obj, *args, **kwargs): menus_param = request.GET.get("menus", None) if menus_param and "_save" in request.POST: return HttpResponseRedirect(reverse("admin:menus_menu_change", args=(menus_param,))) return getattr(admin.ModelAdmin, "response_%s" % action)(self, request, obj, *args, **kwargs)
[docs] def response_add(self, request, obj, *args, **kwargs): return self._redirect("add", request, obj, *args, **kwargs)
[docs] def response_change(self, request, obj, *args, **kwargs): return self._redirect("change", request, obj, *args, **kwargs)
[docs]def make_entrieable_admin(clz): """ Monkeypatch an admin class Call this with an admin class to allow the instance class to be a menu entry. """ clz.is_menu_entrieable = True clz.save_related = EntrieableAdmin.save_related clz.get_fields = EntrieableAdmin.get_fields clz.get_fieldsets = EntrieableAdmin.get_fieldsets clz.form = EntrieableForm
admin.site.register(Menu, MenuAdmin) admin.site.register(Link, EntrieableAdmin) admin.site.register(ViewLink, EntrieableAdmin) admin.site.register(MenuEntry, MenuEntryAdmin) admin.site.register(MenuCache) admin.site.register(AutoPopulated, EntrieableAdmin)