class BaseRecipe(schema.Document): #fields to keep track of what the recipe generated generated_applications = schema.ListField( schema.ReferenceField(Application), editable=False) generated_collections = schema.ListField( schema.ReferenceField(BaseCollection), editable=False) generated_indexes = schema.ListField(schema.ReferenceField(Index), editable=False) generated_view_points = schema.ListField( schema.ReferenceField(BaseViewPoint), editable=False) generated_subsites = schema.ListField(schema.ReferenceField(Subsite), editable=False) class Meta: typed_field = 'recipe_type' verbose_name = 'Recipe' collection = 'dockitcms.recipe' def cook_recipe(self): raise NotImplementedError #build out apps, collections and such here def save(self, *args, **kwargs): if not self.pk: self.cook_recipe() return super(BaseRecipe, self).save(*args, **kwargs)
class Recipe( BaseRecipe ): #represents typical recipe design pattern; creates an app and attaches view points to an existing subsite application_name = schema.CharField() #name of app to create subsite = schema.ReferenceField(Subsite) def get_application_kwargs(self): return {'name': self.application_name} def create_application(self): application = Application(**self.get_application_kwargs()) application.save() self.generated_applications.append(application) def get_view_point_kwargs(self): return {'subsite': self.subsite} def get_collection_kwargs(self): return { 'application': self.applications[0], 'admin_options': { 'list_per_page': 100 }, } class Meta: proxy = True
class IndexMixin(schema.Schema): index = schema.ReferenceField(CollectionIndex) def get_object_class(self): return self.index.get_object_class() def get_index(self): return self.index.get_index()
class PredefinedWidget(Widget): widget = schema.ReferenceField(ReusableWidget) def render(self, context): return self.widget.render(context) def __unicode__(self): if self.widget: return unicode(self.widget) return repr(self) class Meta: typed_key = 'widgetblock.predefinedwidget'
class CollectionReferenceField(BaseFieldEntry): collection = schema.ReferenceField(VirtualDocumentCollection) field_class = schema.ReferenceField def get_field_kwargs(self): kwargs = dict(super(CollectionReferenceField, self).get_field_kwargs()) kwargs['document'] = self.collection.get_document() assert issubclass(kwargs['document'], schema.Document) kwargs.pop('collection', None) return kwargs class Meta: typed_key = 'CollectionReferenceField'
class PublicCollectionResource(PublicResource): collection = schema.ReferenceField(Collection) view_points = schema.ListField(schema.SchemaField(BaseViewPoint)) @property def cms_resource(self): return self.collection.get_collection_resource() def get_public_resource_kwargs(self, **kwargs): kwargs.setdefault('view_points', self.view_points) return super(PublicCollectionResource, self).get_public_resource_kwargs(**kwargs) class Meta: typed_key = 'collection'
class CollectionIndex(Index): collection = schema.ReferenceField(Collection) def get_document(self): return self.collection.get_document() def get_object_class(self): return self.get_document() def register_index(self): self.get_index().commit() def __unicode__(self): return u'%s - %s' % (self.collection, self.name) class Meta: proxy = True
class ModelIndex(Index): collection = schema.ReferenceField(ModelCollection) def get_model(self): return self.collection.get_model() def get_object_class(self): return self.get_model() def register_index(self): pass def __unicode__(self): return u'%s - %s' % (self.collection.model, self.name) class Meta: proxy = True
class PublicPageCollectionResource(PublicResource): collection = schema.ReferenceField(PageCollection) #view_points = schema.ListField(schema.SchemaField(BaseViewPoint)) @property def cms_resource(self): return self.collection.get_collection_resource() def get_public_resource_kwargs(self, **kwargs): #print 'get_collection_kwargs' from dockitcms.pagecollection.viewpoints import PageViewPoint kwargs['view_points'] = [ PageViewPoint(page_resource=self) ] return super(PublicPageCollectionResource, self).get_public_resource_kwargs(**kwargs) class Meta: typed_key = 'pagecollection'
class BasePage(schema.Schema): parent = schema.ReferenceField('self', blank=True, null=True) url = schema.CharField(blank=True) url_name = schema.SlugField(blank=True, help_text='registers the page with the url tag with this name') path = schema.CharField(editable=False) title = schema.CharField() slug = schema.SlugField() published = schema.BooleanField() template = schema.CharField() inline_css = schema.TextField(blank=True) inline_js = schema.TextField(blank=True) def clean_path(self): if self.url: return self.url if self.parent: return self.parent.path + self.slug + '/' return self.slug + '/'
class BaseCollection(schema.Document): application = schema.ReferenceField(Application) admin_options = schema.SchemaField(AdminOptions) title = None @permalink def get_admin_manage_url(self): return ('admin:dockitcms_basecollection_manage', [self.pk], {}) def admin_manage_link(self): url = self.get_admin_manage_url() return u'<a href="%s">%s</a>' % (url, _('Manage')) admin_manage_link.short_description = _('Manage') admin_manage_link.allow_tags = True class Meta: typed_field = 'collection_type' verbose_name = 'collection'
class PublicResource(schema.Document, create_document_mixin(SUBSITE_RESOURCE_MIXINS)): subsite = schema.ReferenceField(Subsite) url = schema.CharField() name = schema.CharField() def get_base_url(self): url = self.url or '' if url.startswith('/'): url = url[1:] if not url.startswith('^'): url = '^' + url return url def get_public_resource_class(self): from dockitcms.resources.public import PublicResource return PublicResource def get_public_resource_kwargs(self, **kwargs): collection = self.collection params = { 'collection': collection, 'base_url': self.get_base_url(), 'app_name': collection.application.slug, 'resource_adaptor': collection.get_collection_resource().resource_adaptor, 'view_points': [], } params.update(kwargs) return params def register_public_resource(self, site): klass = self.get_public_resource_class() kwargs = self.get_public_resource_kwargs(site=site) return site.register_endpoint(klass, **kwargs) class Meta: typed_field = '_resource_type'
class BaseViewPoint(schema.Document, ManageUrlsMixin, create_document_mixin(VIEW_POINT_MIXINS)): subsite = schema.ReferenceField(Subsite) def contains_url(self, url): raise NotImplementedError def _base_url(self): return self.subsite.url base_url = property(_base_url) #TODO this is currently only called during the save def register_view_point(self): pass def send_view_point_event(self, event, view, kwargs): ''' The view calls this to notify the mixins that an event has happened ''' mixins = self.get_active_mixins(self) results = [] for mixin_cls in mixins: if not hasattr(mixin_cls, 'handle_view_point_event'): continue mixin = mixin_cls(_primitive_data=self._primitive_data) val = mixin.handle_view_point_event(event, view, kwargs) results.append((mixin, val)) return results def get_scopes(self): site_scope = get_site_scope() subsite_scope = Scope('subsite', object=self.subsite) subsite_scope.add_data('object', self.subsite, self.subsite.get_manage_urls()) viewpoint_scope = Scope('viewpoint', object=self) viewpoint_scope.add_data('object', self, self.get_manage_urls()) return ScopeList([site_scope, subsite_scope, viewpoint_scope]) def get_admin_view(self, **kwargs): from dockitcms.admin.views import ViewPointDesignerFragmentView kwargs['view_spec'] = self return ViewPointDesignerFragmentView.as_view(**kwargs) def get_urls(self): from django.conf.urls.defaults import patterns return patterns('') def get_resolver(self): from dockitcms.common import CMSURLResolver urls = self.get_urls() return CMSURLResolver(r'^' + self.base_url, urls) def dispatch(self, request): resolver = self.get_resolver() view_match = resolver.resolve(request.path) return view_match.func(request, *view_match.args, **view_match.kwargs) def reverse(self, name, *args, **kwargs): resolver = self.get_resolver() return self.base_url + resolver.reverse(name, *args, **kwargs) def save(self, *args, **kwargs): super(BaseViewPoint, self).save(*args, **kwargs) self.register_view_point() class Meta: typed_field = 'view_type' verbose_name = 'View Point' collection = 'dockitcms.viewpoint'
class CategoryViewPoint(ViewPoint, CanonicalMixin): category_collection = schema.ReferenceField(Collection) #TODO #category_index = schema.ReferenceField(CollectionIndex) #category_index_param = schema.CharField() category_slug_field = schema.CharField(blank=True) category_template_source = schema.CharField( choices=TEMPLATE_SOURCE_CHOICES, default='name') category_template_name = schema.CharField(default='dockitcms/detail.html', blank=True) category_template_html = schema.TextField(blank=True) category_content = schema.TextField(blank=True, help_text=CATEGORY_CONTEXT_DESCRIPTION) item_collection = schema.ReferenceField(Collection) #TODO #item_index = schema.ReferenceField(CollectionIndex) #item_index_param = schema.CharField() item_slug_field = schema.CharField(blank=True) #TODO #item_category_index = schema.ReferenceField(CollectionIndex) #dot_path = schema.CharField() item_category_index_param = schema.CharField() item_template_source = schema.CharField(choices=TEMPLATE_SOURCE_CHOICES, default='name') item_template_name = schema.CharField(default='dockitcms/detail.html', blank=True) item_template_html = schema.TextField(blank=True) item_content = schema.TextField(blank=True, help_text=ITEM_CONTEXT_DESCRIPTION) category_view_class = CategoryDetailView item_view_class = ItemDetailView class Meta: typed_key = 'dockitcms.collectioncategoryview' def get_category_index(self): return self.category_index.get_index() def get_item_index(self): return self.item_index.get_index() def get_item_category_index(self): return self.item_category_index.get_index() def get_category_document(self): doc_cls = self.category_index.get_object_class() view_point = self def get_absolute_url_for_instance(instance): if view_point.category_slug_field: return view_point.reverse( 'category-detail', instance[view_point.category_slug_field]) return view_point.reverse('category-detail', instance.pk) if self.canonical: setattr(doc_cls, 'get_absolute_url', get_absolute_url_for_instance) #doc_cls.get_absolute_url = get_absolute_url_for_instance class WrappedDoc(doc_cls): get_absolute_url = get_absolute_url_for_instance class Meta: proxy = True return WrappedDoc def get_item_document(self): doc_cls = self.item_index.get_object_class() view_point = self def get_absolute_url_for_instance(instance): if view_point.item_slug_field: return view_point.reverse('item-detail', instance[view_point.item_slug_field]) return view_point.reverse('item-detail', instance.pk) if self.canonical: doc_cls.get_absolute_url = get_absolute_url_for_instance class WrappedDoc(doc_cls): get_absolute_url = get_absolute_url_for_instance class Meta: proxy = True return WrappedDoc def _configuration_from_prefix(self, params, prefix): config = dict() for key in ('template_source', 'template_name', 'template_html', 'content'): config[key] = params.get('%s_%s' % (prefix, key), None) return config def get_inner_urls(self): category_document = self.get_category_document() item_document = self.get_item_document() category_index = self.get_category_index() item_index = self.get_item_index() item_category_index = self.get_item_category_index() params = self.to_primitive(self) urlpatterns = patterns( '', #url(r'^$', # self.list_view_class.as_view(document=document, # configuration=self._configuration_from_prefix(params, 'list'), # paginate_by=params.get('paginate_by', None)), # name='index', #), ) if self.category_slug_field: urlpatterns += patterns( '', url( r'^c/(?P<slug>.+)/$', self.category_view_class.as_view( document=item_document, slug_field=self.category_slug_field, view_point=self, category_index=category_index, item_category_index=item_category_index, item_category_index_param=self. item_category_index_param, configuration=self._configuration_from_prefix( params, 'category'), ), name='category-detail', ), ) else: urlpatterns += patterns( '', url( r'^c/(?P<pk>.+)/$', self.category_view_class.as_view( document=item_document, view_point=self, category_index=category_index, item_category_index=item_category_index, item_category_index_param=self. item_category_index_param, configuration=self._configuration_from_prefix( params, 'category'), ), name='category-detail', ), ) if self.item_slug_field: urlpatterns += patterns( '', url( r'^i/(?P<slug>.+)/$', self.item_view_class.as_view( document=item_document, slug_field=self.item_slug_field, queryset=item_index, view_point=self, configuration=self._configuration_from_prefix( params, 'item'), ), name='item-detail', ), ) else: urlpatterns += patterns( '', url( r'^i/(?P<pk>.+)/$', self.item_view_class.as_view( document=item_document, queryset=item_index, view_point=self, configuration=self._configuration_from_prefix( params, 'item'), ), name='item-detail', ), ) return urlpatterns
class Collection(ManageUrlsMixin, schema.Document, EventMixin): key = schema.SlugField(unique=True) application = schema.ReferenceField(Application) admin_options = schema.SchemaField(AdminOptions) title = None mixins = schema.SetField(schema.CharField(), choices=COLLECTION_MIXINS.choices, blank=True) mixin_function_events = { 'get_document_kwargs': { 'post': PostEventFunction(event='document_kwargs', keyword='document_kwargs'), }, #'get_view_endpoints': { #'collect': CollectEventFunction(event='view_endpoints', extend_function='extends'), #'post': PostEventFunction(event='view_endpoints', keyword='view_endpoints'), #}, } @classmethod def register_mixin(self, key, mixin_class): self.get_available_mixins()[key] = mixin_class @classmethod def get_available_mixins(self): return COLLECTION_MIXINS def __getattribute__(self, name): function_events = object.__getattribute__(self, 'mixin_function_events') if name in function_events: ret = object.__getattribute__(self, name) return self._mixin_function(ret, function_events[name]) return schema.Document.__getattribute__(self, name) def get_active_mixins(self): mixins = list() available_mixins = self.get_available_mixins() for mixin_key in self.mixins: if mixin_key in available_mixins: mixin_cls = available_mixins[mixin_key] mixins.append(mixin_cls(self)) return mixins @permalink def get_admin_manage_url(self): return self.get_resource_item().get_absolute_url() def admin_manage_link(self): url = self.get_admin_manage_url() return '<a href="%s">%s</a>' % (url, _('Manage')) admin_manage_link.short_description = _('Manage') admin_manage_link.allow_tags = True def get_object_class(self): raise NotImplementedError def get_resource_class(self): raise NotImplementedError @classmethod def get_collection_admin_client(cls): #TODO this should be configurable from dockitcms.urls import admin_client return admin_client.api_endpoint def get_collection_resource(self): admin_client = self.get_collection_admin_client() cls = self.get_object_class() try: return admin_client.registry[cls] except Exception as error: seen = list() for key, resource in admin_client.registry.iteritems(): seen.append((resource.collection.collection_type, key, resource.collection)) #if resource.collection.collection_type != 'dockitcms.virtualdocument': # assert False, str("%s, %s, %s, %s" % (resource.collection, self, resource.collection==self, resource.collection.collection_type)) if hasattr(resource, 'collection') and resource.collection == self: return resource assert False, str(seen) def register_collection(self): pass def save(self, *args, **kwargs): ret = super(Collection, self).save(*args, **kwargs) self.register_collection() return ret class Meta: typed_field = 'collection_type' verbose_name = 'collection'