Source code for widgy.site

from django.conf.urls import url
from django.core.urlresolvers import reverse
from django.core.exceptions import PermissionDenied
from django.contrib.staticfiles import finders
from django.contrib.auth import get_permission_codename
from django.utils.functional import cached_property

from widgy import registry
from widgy.views import (
    NodeView,
    ContentView,
    ShelfView,
    NodeEditView,
    NodeTemplatesView,
    NodeParentsView,
    CommitView,
    HistoryView,
    RevertView,
    DiffView,
    ResetView,
)
from widgy.exceptions import (
    MutualRejection,
    ParentWasRejected,
    ChildWasRejected,
)


[docs]class WidgySite(object): def get_registry(self): return registry
[docs] def get_all_content_classes(self): return self.get_registry()
[docs] def get_urls(self): urlpatterns = [ url('^node/$', self.node_view), url('^node/(?P<node_pk>[^/]+)/$', self.node_view), url('^node/(?P<node_pk>[^/]+)/available-children-recursive/$', self.shelf_view), url('^node/(?P<node_pk>[^/]+)/edit/$', self.node_edit_view), url('^node/(?P<node_pk>[^/]+)/templates/$', self.node_templates_view), url('^node/(?P<node_pk>[^/]+)/possible-parents/$', self.node_parents_view), url('^contents/(?P<app_label>[A-z_][\w_]*)/(?P<object_name>[A-z_][\w_]*)/(?P<object_pk>[^/]+)/$', self.content_view), # versioning url('^revert/(?P<pk>[^/]+)/(?P<commit_pk>[^/]+)/$', self.revert_view), url('^commit/(?P<pk>[^/]+)/$', self.commit_view), url('^history/(?P<pk>[^/]+)/$', self.history_view), url('^reset/(?P<pk>[^/]+)/$', self.reset_view), url('^diff/$', self.diff_view), ] return urlpatterns
@property def urls(self): return self.get_urls()
[docs] def reverse(self, *args, **kwargs): """ We tried to use namespaced URLs per site just like ModelAdmins, however, as we refer to the views by their function objects, we can't use namespaces because there is a bug in Django: https://code.djangoproject.com/ticket/17914 We should use named URLs instead of function references, but we couldn't get that working. """ return reverse(*args, **kwargs)
[docs] def authorize_view(self, request, view): if not (request.user.is_authenticated() and request.user.is_staff): raise PermissionDenied
[docs] def has_add_permission(self, request, parent, created_obj_cls): codename = get_permission_codename('add', created_obj_cls._meta) return request.user.has_perm('%s.%s' % (created_obj_cls._meta.app_label, codename))
[docs] def has_change_permission(self, request, obj_or_class): codename = get_permission_codename('change', obj_or_class._meta) return request.user.has_perm('%s.%s' % (obj_or_class._meta.app_label, codename))
[docs] def has_delete_permission(self, request, obj_or_class): def has_perm(o): codename = get_permission_codename('delete', o._meta) return request.user.has_perm('%s.%s' % (o._meta.app_label, codename)) if isinstance(obj_or_class, type): return has_perm(obj_or_class) else: return all(has_perm(o) for o in obj_or_class.depth_first_order()) # These must return the same instance throughout the whole lifetime # of the widgy site for reverse to work.
@cached_property def node_view(self): return NodeView.as_view(site=self) @cached_property def content_view(self): return ContentView.as_view(site=self) @cached_property def shelf_view(self): return ShelfView.as_view(site=self) @cached_property def node_edit_view(self): return NodeEditView.as_view(site=self) @cached_property def node_templates_view(self): return NodeTemplatesView.as_view(site=self) @cached_property def node_parents_view(self): return NodeParentsView.as_view(site=self) @cached_property def commit_view(self): return CommitView.as_view(site=self) @cached_property def history_view(self): return HistoryView.as_view(site=self) @cached_property def revert_view(self): return RevertView.as_view(site=self) @cached_property def diff_view(self): return DiffView.as_view(site=self) @cached_property def reset_view(self): return ResetView.as_view(site=self)
[docs] def valid_parent_of(self, parent, child_class, child=None): return parent.valid_parent_of(child_class, child)
[docs] def valid_child_of(self, parent, child_class, child=None): return child_class.valid_child_of(parent, child)
[docs] def validate_relationship(self, parent, child): if isinstance(child, type): child_class = child child = None else: child_class = type(child) bad_child = not self.valid_parent_of(parent, child_class, child) bad_parent = not self.valid_child_of(parent, child_class, child) if bad_parent and bad_child: raise MutualRejection("Neither {parent} nor {child} want to be together.".format( child=child_class.__name__, parent=type(parent).__name__, )) elif bad_parent: raise ParentWasRejected("{child} refuses to be put in {parent}.".format( child=child_class.__name__, parent=type(parent).__name__, )) elif bad_child: raise ChildWasRejected("{parent} refuses to accept {child}.".format( child=child_class.__name__, parent=type(parent).__name__, ))
[docs] def get_version_tracker_model(self): from widgy.models import VersionTracker return VersionTracker
def filter_existing_staticfiles(self, filename): path = finders.find(filename) return bool(path) def find_media_files(self, extension, hierarchy=['widgy/{app_label}/{model_name}{extension}']): files = set() for widget in self.get_all_content_classes(): files.update(widget.get_templates_hierarchy( hierarchy=hierarchy, extension=extension, )) return sorted(filter(self.filter_existing_staticfiles, files)) @cached_property def scss_files(self): return self.find_media_files('.scss') @cached_property def js_files(self): return self.find_media_files('.js') @cached_property def admin_scss_files(self): return self.find_media_files( extension='.scss', hierarchy=[ 'widgy/{app_label}/{model_name}.admin{extension}', 'widgy/{app_label}/admin{extension}', ])