148 lines
5.2 KiB
Python
148 lines
5.2 KiB
Python
from django.core.exceptions import ImproperlyConfigured
|
|
from django.urls import reverse
|
|
from django.utils.functional import cached_property
|
|
|
|
from wagtail.admin.menu import WagtailMenuRegisterable, WagtailMenuRegisterableGroup
|
|
|
|
|
|
class ViewSet(WagtailMenuRegisterable):
|
|
"""
|
|
Defines a viewset to be registered with the Wagtail admin.
|
|
|
|
All properties of the viewset can be defined as class-level attributes, or passed as
|
|
keyword arguments to the constructor (in which case they will override any class-level
|
|
attributes). Additionally, the :attr:`name` property can be passed as the first positional
|
|
argument to the constructor.
|
|
|
|
For more information on how to use this class, see :ref:`using_base_viewset`.
|
|
"""
|
|
|
|
#: A special value that, when passed in a kwargs dict to construct a view, indicates that
|
|
#: the attribute should not be written and should instead be left as the view's initial value
|
|
UNDEFINED = object()
|
|
|
|
#: A name for this viewset, used as the default URL prefix and namespace.
|
|
name = None
|
|
|
|
#: The icon to use across the views.
|
|
icon = ""
|
|
|
|
def __init__(self, name=None, **kwargs):
|
|
if name:
|
|
self.__dict__["name"] = name
|
|
|
|
for key, value in kwargs.items():
|
|
self.__dict__[key] = value
|
|
|
|
def get_common_view_kwargs(self, **kwargs):
|
|
"""
|
|
Returns a dictionary of keyword arguments to be passed to all views within this viewset.
|
|
"""
|
|
return kwargs
|
|
|
|
def construct_view(self, view_class, **kwargs):
|
|
"""
|
|
Wrapper for view_class.as_view() which passes the kwargs returned from get_common_view_kwargs
|
|
in addition to any kwargs passed to this method. Items from get_common_view_kwargs will be
|
|
filtered to only include those that are valid for the given view_class.
|
|
"""
|
|
merged_kwargs = self.get_common_view_kwargs()
|
|
merged_kwargs.update(kwargs)
|
|
filtered_kwargs = {
|
|
key: value
|
|
for key, value in merged_kwargs.items()
|
|
if hasattr(view_class, key) and value is not self.UNDEFINED
|
|
}
|
|
return view_class.as_view(**filtered_kwargs)
|
|
|
|
def inject_view_methods(self, view_class, method_names):
|
|
"""
|
|
Check for the presence of any of the named methods on this viewset. If any are found,
|
|
create a subclass of view_class that overrides those methods to call the implementation
|
|
on this viewset instead. Otherwise, return view_class unmodified.
|
|
"""
|
|
viewset = self
|
|
overrides = {}
|
|
for method_name in method_names:
|
|
viewset_method = getattr(viewset, method_name, None)
|
|
if viewset_method:
|
|
|
|
def view_method(self, *args, **kwargs):
|
|
return viewset_method(*args, **kwargs)
|
|
|
|
view_method.__name__ = method_name
|
|
overrides[method_name] = view_method
|
|
|
|
if overrides:
|
|
return type(view_class.__name__, (view_class,), overrides)
|
|
else:
|
|
return view_class
|
|
|
|
@cached_property
|
|
def url_prefix(self):
|
|
"""
|
|
The preferred URL prefix for views within this viewset. When registered through
|
|
Wagtail's :ref:`register_admin_viewset` hook, this will be used as the URL path component
|
|
following ``/admin/``. Other URL registration mechanisms (e.g. editing ``urls.py`` manually)
|
|
may disregard this and use a prefix of their own choosing.
|
|
|
|
Defaults to the viewset's ``name``.
|
|
"""
|
|
if not self.name:
|
|
raise ImproperlyConfigured(
|
|
"ViewSet %r must provide a `name` property" % self
|
|
)
|
|
return self.name
|
|
|
|
@cached_property
|
|
def url_namespace(self):
|
|
"""
|
|
The URL namespace for views within this viewset. Will be used internally as the
|
|
application namespace for the viewset's URLs, and generally be the instance namespace
|
|
too.
|
|
|
|
Defaults to the viewset's ``name``.
|
|
"""
|
|
if not self.name:
|
|
raise ImproperlyConfigured(
|
|
"ViewSet %r must provide a `name` property" % self
|
|
)
|
|
return self.name
|
|
|
|
def on_register(self):
|
|
"""
|
|
Called when the viewset is registered; subclasses can override this to perform additional setup.
|
|
"""
|
|
self.register_menu_item()
|
|
|
|
def get_urlpatterns(self):
|
|
"""
|
|
Returns a set of URL routes to be registered with the Wagtail admin.
|
|
"""
|
|
return []
|
|
|
|
def get_url_name(self, view_name):
|
|
"""
|
|
Returns the namespaced URL name for the given view.
|
|
"""
|
|
return self.url_namespace + ":" + view_name
|
|
|
|
@cached_property
|
|
def menu_icon(self):
|
|
return self.icon
|
|
|
|
@cached_property
|
|
def menu_url(self):
|
|
return reverse(self.get_url_name(self.get_urlpatterns()[0].name))
|
|
|
|
|
|
class ViewSetGroup(WagtailMenuRegisterableGroup):
|
|
"""
|
|
A container for grouping together multiple :class:`ViewSet` instances.
|
|
Creates a menu item with a submenu for accessing the main URL for each instances.
|
|
|
|
For more information on how to use this class, see :ref:`using_base_viewsetgroup`.
|
|
"""
|
|
|
|
def on_register(self):
|
|
self.register_menu_item()
|