137 lines
4.2 KiB
Python
137 lines
4.2 KiB
Python
from django.apps import apps
|
|
from django.contrib.auth.models import Permission
|
|
from django.urls import reverse
|
|
from django.utils.text import capfirst
|
|
|
|
from wagtail import hooks
|
|
from wagtail.admin.admin_url_finder import (
|
|
ModelAdminURLFinder,
|
|
register_admin_url_finder,
|
|
)
|
|
from wagtail.admin.menu import MenuItem
|
|
from wagtail.permission_policies import ModelPermissionPolicy
|
|
|
|
from .permissions import user_can_edit_setting_type
|
|
|
|
|
|
class SettingMenuItem(MenuItem):
|
|
def __init__(self, model, icon="cog", classname="", **kwargs):
|
|
self.model = model
|
|
super().__init__(
|
|
label=capfirst(model._meta.verbose_name),
|
|
url=reverse(
|
|
"wagtailsettings:edit",
|
|
args=[model._meta.app_label, model._meta.model_name],
|
|
),
|
|
classname=classname,
|
|
icon_name=icon,
|
|
**kwargs,
|
|
)
|
|
|
|
def is_shown(self, request):
|
|
return user_can_edit_setting_type(request.user, self.model)
|
|
|
|
|
|
class SiteSettingAdminURLFinder(ModelAdminURLFinder):
|
|
def construct_edit_url(self, instance):
|
|
return reverse(
|
|
"wagtailsettings:edit",
|
|
args=[
|
|
self.model._meta.app_label,
|
|
self.model._meta.model_name,
|
|
instance.site_id,
|
|
],
|
|
)
|
|
|
|
|
|
class GenericSettingAdminURLFinder(ModelAdminURLFinder):
|
|
def construct_edit_url(self, instance):
|
|
return reverse(
|
|
"wagtailsettings:edit",
|
|
args=[
|
|
self.model._meta.app_label,
|
|
self.model._meta.model_name,
|
|
instance.id,
|
|
],
|
|
)
|
|
|
|
|
|
class Registry(list):
|
|
def __init__(self):
|
|
self._model_icons = {}
|
|
|
|
def register(self, model, icon="cog", **kwargs):
|
|
from .models import BaseGenericSetting, BaseSiteSetting
|
|
|
|
"""
|
|
Register a model as a setting, adding it to the wagtail admin menu
|
|
"""
|
|
if icon:
|
|
self._model_icons[model] = icon
|
|
|
|
# Don't bother registering this if it is already registered
|
|
if model in self:
|
|
return model
|
|
self.append(model)
|
|
|
|
# Register a new menu item in the settings menu
|
|
@hooks.register("register_settings_menu_item")
|
|
def menu_hook():
|
|
return SettingMenuItem(model, icon=self._model_icons.get(model), **kwargs)
|
|
|
|
@hooks.register("register_permissions")
|
|
def permissions_hook():
|
|
return Permission.objects.filter(
|
|
content_type__app_label=model._meta.app_label,
|
|
codename=f"change_{model._meta.model_name}",
|
|
)
|
|
|
|
# Register an admin URL finder
|
|
permission_policy = ModelPermissionPolicy(model)
|
|
|
|
if issubclass(model, BaseSiteSetting):
|
|
finder_class = type(
|
|
"_SiteSettingAdminURLFinder",
|
|
(SiteSettingAdminURLFinder,),
|
|
{"model": model, "permission_policy": permission_policy},
|
|
)
|
|
elif issubclass(model, BaseGenericSetting):
|
|
finder_class = type(
|
|
"_GenericSettingAdminURLFinder",
|
|
(GenericSettingAdminURLFinder,),
|
|
{"model": model, "permission_policy": permission_policy},
|
|
)
|
|
else:
|
|
raise NotImplementedError
|
|
|
|
register_admin_url_finder(model, finder_class)
|
|
|
|
return model
|
|
|
|
def register_decorator(self, model=None, icon="cog", **kwargs):
|
|
"""
|
|
Register a model as a setting in the Wagtail admin
|
|
"""
|
|
if model is None:
|
|
return lambda model: self.register(model, icon=icon, **kwargs)
|
|
return self.register(model, icon=icon, **kwargs)
|
|
|
|
def get_by_natural_key(self, app_label, model_name):
|
|
"""
|
|
Get a setting model using its app_label and model_name.
|
|
|
|
If the app_label.model_name combination is not a valid model, or the
|
|
model is not registered as a setting, returns None.
|
|
"""
|
|
try:
|
|
Model = apps.get_model(app_label, model_name)
|
|
except LookupError:
|
|
return None
|
|
else:
|
|
if Model not in registry:
|
|
return None
|
|
return Model
|
|
|
|
|
|
registry = Registry()
|
|
register_setting = registry.register_decorator
|