class ModelCollection(Collection): model = schema.ModelReferenceField(ContentType) mixins = schema.SetField(schema.CharField(), choices=MODEL_COLLECTION_MIXINS.choices, blank=True) @classmethod def get_available_mixins(self): return MODEL_COLLECTION_MIXINS def get_model(self): return self.model.model_class() def get_object_class(self): return self.get_model() def get_resource_class(self): from dockitcms.resources.collection import ModelResource return ModelResource class Meta: typed_key = 'dockitcms.model'
class MixinSchema(schema.Schema, EventMixin): mixins = schema.SetField(schema.CharField(), choices=mixin_choices, blank=True) @classmethod def register_mixin(self, key, mixin_class): MIXINS[key] = mixin_class @classmethod def get_available_mixins(self): return MIXINS def __getattribute__(self, name): function_events = object.__getattribute__(self, 'mixin_function_events') if name in function_events: return EventMixin.__getattribute__(self, name) return schema.Schema.__getattribute__(self, name) def get_active_mixins(self, target=None): #CONSIDER: this modifies the fields we have mixins = list() target = target or self 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(target)) return mixins def make_bound_schema(self): if getattr(self, '_mixin_bound', False): return type(self) original_fields = self._meta.fields.keys() def get_active_mixins(kls, target=None): return self.get_active_mixins(target=target) def send_mixin_event(kls, event, kwargs): return self.send_mixin_event(event, kwargs) cls = type(self) document_kwargs = { 'fields':{},#copy(self._meta.fields.fields), #fields => uber dictionary, fields.fields => fields we defined 'proxy': True, 'name': cls.__name__, 'parents': (cls,), 'module': cls.__module__, 'attrs': {'get_active_mixins':classmethod(get_active_mixins), 'send_mixin_event':classmethod(send_mixin_event), '_mixin_bound':True}, } self.send_mixin_event('document_kwargs', {'document_kwargs':document_kwargs}) new_cls = create_document(**document_kwargs) assert self._meta.fields.keys() == original_fields return new_cls @classmethod def to_python(cls, val, parent=None): #chicken and egg problem #hack because super(cls).to_python does not work original_to_python = schema.Document.to_python.im_func self = original_to_python(cls, val, parent) if getattr(cls, '_mixin_bound', False): return self else: new_cls = self.make_bound_schema() return original_to_python(new_cls, val, parent)
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'
class VirtualDocumentCollection(Collection, DocumentDesign): mixins = schema.SetField(schema.CharField(), choices=VIRTUAL_COLLECTION_MIXINS.choices, blank=True) @classmethod def get_available_mixins(self): return VIRTUAL_COLLECTION_MIXINS def get_collection_name(self): return 'dockitcms.virtual.%s' % self.key def get_document_kwargs(self, **kwargs): kwargs = super(VirtualDocumentCollection, self).get_document_kwargs(**kwargs) kwargs.setdefault('attrs', dict()) parents = list(kwargs.get('parents', list())) parents.append(VirtualManageUrlsMixin) if not any([issubclass(parent, schema.Document) for parent in parents]): parents.append(schema.Document) if parents: kwargs['parents'] = tuple(parents) if self.application: kwargs['app_label'] = self.application.name kwargs['attrs']['_collection_document'] = self return kwargs def register_collection(self): doc = DocumentDesign.get_document(self, virtual=False, verbose_name=self.title, collection=self.get_collection_name()) force_register_documents(doc._meta.app_label, doc) return doc def get_document(self): key = self.get_collection_name() #TODO how do we know if we should recreate the document? ie what if the design was modified on another node try: return get_base_document(key) except KeyError: doc = self.register_collection() return doc def get_object_class(self): return self.get_document() def get_resource_class(self): from dockitcms.resources.collection import VirtualDocumentResource return VirtualDocumentResource 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: for key, resource in admin_client.registry.iteritems(): if isinstance(key, type) and issubclass(cls, key): return resource #TODO why do we need this? if issubclass(key, schema.Document) and key._meta.collection == cls._meta.collection: return resource def __unicode__(self): if self.title: return self.title else: return self.__repr__() class Meta: typed_key = 'dockitcms.virtualdocument'
class Collection(BaseCollection, DocumentDesign, EventMixin): key = schema.SlugField(unique=True) mixins = schema.SetField(schema.CharField(), choices=mixin_choices, blank=True) mixin_function_events = { 'get_document_kwargs': { 'post': PostEventFunction(event='document_kwargs', keyword='document_kwargs') }, } @classmethod def register_mixin(self, key, mixin_class): COLLECTION_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 BaseCollection.__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 def save(self, *args, **kwargs): ret = super(Collection, self).save(*args, **kwargs) self.register_collection() return ret def get_collection_name(self): return 'dockitcms.virtual.%s' % self.key def get_document_kwargs(self, **kwargs): kwargs = super(Collection, self).get_document_kwargs(**kwargs) kwargs.setdefault('attrs', dict()) parents = list(kwargs.get('parents', list())) if parents and not any( [issubclass(parent, schema.Document) for parent in parents]): parents.append(schema.Document) if parents: kwargs['parents'] = tuple(parents) if self.application: kwargs['app_label'] = self.application.name def get_manage_urls(instance): base_url = self.get_admin_manage_url() urls = { 'add': base_url + 'add/', 'list': base_url, } if instance.pk: urls['edit'] = base_url + instance.pk + '/' return urls kwargs['attrs']['get_manage_urls'] = get_manage_urls kwargs['attrs']['_collection_document'] = self return kwargs def register_collection(self): doc = DocumentDesign.get_document( self, virtual=False, verbose_name=self.title, collection=self.get_collection_name()) force_register_documents(doc._meta.app_label, doc) return doc def get_document(self): key = self.get_collection_name() #TODO how do we know if we should recreate the document? ie what if the design was modified on another node try: return get_base_document(key) except KeyError: doc = self.register_collection() return doc def __unicode__(self): if self.title: return self.title else: return self.__repr__() class Meta: typed_key = 'document'