+ def set_publishable(self, publishable):
+ self.publishable = publishable
+ self.save()
+ post_publishable.send(sender=self, publishable=publishable)
+
+
+def create_tag_model(model):
+ name = model.__name__ + 'Tag'
+
+ class Meta(Tag.Meta):
+ app_label = model._meta.app_label
+ verbose_name = string_concat(
+ _("tag"), " ", _("for:"), " ", model._meta.verbose_name)
+ verbose_name_plural = string_concat(
+ _("tags"), " ", _("for:"), " ", model._meta.verbose_name)
+
+ attrs = {
+ '__module__': model.__module__,
+ 'Meta': Meta,
+ }
+ return type(name, (Tag,), attrs)
+
+
+def create_change_model(model):
+ name = model.__name__ + 'Change'
+ repo = GzipFileSystemStorage(location=model.REPO_PATH)
+
+ class Meta(Change.Meta):
+ app_label = model._meta.app_label
+ verbose_name = string_concat(
+ _("change"), " ", _("for:"), " ", model._meta.verbose_name)
+ verbose_name_plural = string_concat(
+ _("changes"), " ", _("for:"), " ", model._meta.verbose_name)
+
+ attrs = {
+ '__module__': model.__module__,
+ 'tree': models.ForeignKey(model, related_name='change_set', verbose_name=_('document')),
+ 'tags': models.ManyToManyField(model.tag_model, verbose_name=_('tags'), related_name='change_set'),
+ 'data': models.FileField(_('data'), upload_to=data_upload_to, storage=repo),
+ 'Meta': Meta,
+ }
+ return type(name, (Change,), attrs)
+
+
+class DocumentMeta(ModelBase):
+ """Metaclass for Document models."""
+ def __new__(cls, name, bases, attrs):
+
+ model = super(DocumentMeta, cls).__new__(cls, name, bases, attrs)
+ if not model._meta.abstract:
+ # create a real Tag object and `stage' fk
+ model.tag_model = create_tag_model(model)
+ models.ForeignKey(model.tag_model, verbose_name=_('stage'),
+ null=True, blank=True).contribute_to_class(model, 'stage')
+
+ # create real Change model and `head' fk
+ model.change_model = create_change_model(model)
+
+ models.ForeignKey(
+ model.change_model, null=True, blank=True, default=None,
+ verbose_name=_('head'), help_text=_("This document's current head."),
+ editable=False).contribute_to_class(model, 'head')
+
+ models.ForeignKey(
+ User, null=True, blank=True, editable=False,
+ verbose_name=_('creator'), related_name="created_%s" % name.lower()
+ ).contribute_to_class(model, 'creator')
+
+ return model
+