Files
old-saburly-wagtail-web/env/lib/python3.10/site-packages/wagtail/admin/admin_url_finder.py
2024-08-27 20:33:44 +02:00

108 lines
3.2 KiB
Python

from django.contrib.admin.utils import quote
from django.core.exceptions import ImproperlyConfigured
from django.urls import reverse
from wagtail.hooks import search_for_hooks
from wagtail.utils.registry import ObjectTypeRegistry
"""
A mechanism for finding the admin edit URL for an arbitrary object instance, optionally applying
permission checks.
url_finder = AdminURLFinder(request.user)
url_finder.get_edit_url(some_page) # => "/admin/pages/123/edit/"
url_finder.get_edit_url(some_image) # => "/admin/images/456/"
url_finder.get_edit_url(some_site) # => None (user does not have edit permission for sites)
If the user parameter is omitted, edit URLs are returned without considering permissions.
Handlers for new models can be registered via register_admin_url_finder:
class SprocketAdminURLFinder(ModelAdminURLFinder):
edit_url_name = 'wagtailsprockets:edit'
register_admin_url_finder(Sprocket, SprocketAdminURLFinder)
"""
class ModelAdminURLFinder:
"""
Handles admin edit URL lookups for an individual model
"""
edit_url_name = None
permission_policy = None
def __init__(self, user=None):
self.user = user
def construct_edit_url(self, instance):
"""
Return the edit URL for the given instance - regardless of whether the user can access it -
or None if no edit URL is available.
"""
if self.edit_url_name is None:
raise ImproperlyConfigured(
"%r must define edit_url_name or override construct_edit_url"
% type(self)
)
return reverse(self.edit_url_name, args=(quote(instance.pk),))
def get_edit_url(self, instance):
"""
Return the edit URL for the given instance if one exists and the user has permission for it,
or None otherwise.
"""
if (
self.user
and self.permission_policy
and not self.permission_policy.user_has_permission_for_instance(
self.user, "change", instance
)
):
return None
else:
return self.construct_edit_url(instance)
class NullAdminURLFinder:
"""
A dummy AdminURLFinder that always returns None
"""
def __init__(self, user=None):
pass
def get_edit_url(self, instance):
return None
finder_classes = ObjectTypeRegistry()
def register_admin_url_finder(model, handler):
finder_classes.register(model, value=handler)
class AdminURLFinder:
"""
The 'main' admin URL finder, which searches across all registered models
"""
def __init__(self, user=None):
search_for_hooks() # ensure wagtail_hooks files have been loaded
self.user = user
self.finders_by_model = {}
def get_edit_url(self, instance):
model = type(instance)
try:
# do we already have a finder for this model and user?
finder = self.finders_by_model[model]
except KeyError:
finder_class = finder_classes.get(instance) or NullAdminURLFinder
finder = finder_class(self.user)
self.finders_by_model[model] = finder
return finder.get_edit_url(instance)