')
- for page in value.documentpage_set.all():
+ for page in value.pages.all():
+
output.append(u'
')
+ output.append(u'
%(page_string)s %(page)s
' % {'page_string': ugettext(u'Page'), 'page': page.page_number})
output.append(
document_html_widget(
page.document,
@@ -128,7 +132,7 @@ class DocumentPreviewForm(forms.Form):
document = kwargs.pop('document', None)
super(DocumentPreviewForm, self).__init__(*args, **kwargs)
self.fields['preview'].initial = document
- self.fields['preview'].label = _(u'Document pages (%s)') % document.documentpage_set.count()
+ self.fields['preview'].label = _(u'Document pages (%s)') % document.pages.count()
preview = forms.CharField(widget=DocumentPagesCarouselWidget())
@@ -165,10 +169,50 @@ class DocumentForm(forms.ModelForm):
required=False,
label=_(u'Quick document rename'))
+ if instance:
+ self.version_fields(instance)
+
+ def version_fields(self, document):
+ self.fields['version_update'] = forms.ChoiceField(
+ label=_(u'Version update'),
+ choices=DocumentVersion.get_version_update_choices(document.latest_version)
+ )
+
+ self.fields['release_level'] = forms.ChoiceField(
+ label=_(u'Release level'),
+ choices=RELEASE_LEVEL_CHOICES,
+ initial=RELEASE_LEVEL_FINAL,
+ )
+
+ self.fields['serial'] = forms.IntegerField(
+ label=_(u'Release level serial'),
+ initial=0,
+ widget=forms.widgets.TextInput(
+ attrs = {'style': 'width: auto;'}
+ ),
+ )
+
+ self.fields['comment'] = forms.CharField(
+ label=_(u'Comment'),
+ required=False,
+ widget=forms.widgets.Textarea(attrs={'rows': 4}),
+ )
+
new_filename = forms.CharField(
label=_('New document filename'), required=False
)
+
+ def clean(self):
+ cleaned_data = self.cleaned_data
+ cleaned_data['new_version_data'] = {
+ 'comment': self.cleaned_data.get('comment'),
+ 'version_update': self.cleaned_data.get('version_update'),
+ 'release_level': self.cleaned_data.get('release_level'),
+ 'serial': self.cleaned_data.get('serial'),
+ }
+ # Always return the full collection of cleaned data.
+ return cleaned_data
class DocumentForm_edit(DocumentForm):
"""
@@ -177,6 +221,13 @@ class DocumentForm_edit(DocumentForm):
class Meta:
model = Document
exclude = ('file', 'document_type', 'tags')
+
+ def __init__(self, *args, **kwargs):
+ super(DocumentForm_edit, self).__init__(*args, **kwargs)
+ self.fields.pop('serial')
+ self.fields.pop('release_level')
+ self.fields.pop('version_update')
+ self.fields.pop('comment')
class DocumentPropertiesForm(DetailForm):
@@ -198,7 +249,7 @@ class DocumentContentForm(forms.Form):
super(DocumentContentForm, self).__init__(*args, **kwargs)
content = []
self.fields['contents'].initial = u''
- for page in self.document.documentpage_set.all():
+ for page in self.document.pages.all():
if page.content:
content.append(page.content)
content.append(u'\n\n\n - Page %s - \n\n\n' % page.page_number)
diff --git a/apps/documents/literals.py b/apps/documents/literals.py
index cbb3b919d9..30b0284f5f 100644
--- a/apps/documents/literals.py
+++ b/apps/documents/literals.py
@@ -44,3 +44,21 @@ HISTORY_DOCUMENT_DELETED = {
'details': _(u'Document "%(document)s" deleted on %(datetime)s by %(fullname)s.'),
'expressions': {'fullname': 'user.get_full_name() if user.get_full_name() else user.username'}
}
+
+RELEASE_LEVEL_FINAL = 1
+RELEASE_LEVEL_ALPHA = 2
+RELEASE_LEVEL_BETA = 3
+RELEASE_LEVEL_RC = 4
+RELEASE_LEVEL_HF = 5
+
+RELEASE_LEVEL_CHOICES = (
+ (RELEASE_LEVEL_FINAL, _(u'final')),
+ (RELEASE_LEVEL_ALPHA, _(u'alpha')),
+ (RELEASE_LEVEL_BETA, _(u'beta')),
+ (RELEASE_LEVEL_RC, _(u'release candidate')),
+ (RELEASE_LEVEL_HF, _(u'hotfix')),
+)
+
+VERSION_UPDATE_MAJOR = u'major'
+VERSION_UPDATE_MINOR = u'minor'
+VERSION_UPDATE_MICRO = u'micro'
diff --git a/apps/documents/migrations/0004_auto__add_documentversion__add_unique_documentversion_document_mayor_m.py b/apps/documents/migrations/0004_auto__add_documentversion__add_unique_documentversion_document_mayor_m.py
new file mode 100644
index 0000000000..e6b0c9bf10
--- /dev/null
+++ b/apps/documents/migrations/0004_auto__add_documentversion__add_unique_documentversion_document_mayor_m.py
@@ -0,0 +1,188 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding model 'DocumentVersion'
+ db.create_table('documents_documentversion', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('document', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.Document'], null=True, blank=True)),
+ ('mayor', self.gf('django.db.models.fields.PositiveIntegerField')(default=1)),
+ ('minor', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
+ ('micro', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
+ ('release_level', self.gf('django.db.models.fields.PositiveIntegerField')(default=1)),
+ ('serial', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
+ ('timestamp', self.gf('django.db.models.fields.DateTimeField')()),
+ ('file', self.gf('django.db.models.fields.files.FileField')(max_length=100)),
+ ('mimetype', self.gf('django.db.models.fields.CharField')(default='', max_length=64)),
+ ('encoding', self.gf('django.db.models.fields.CharField')(default='', max_length=64)),
+ ('filename', self.gf('django.db.models.fields.CharField')(default=u'', max_length=255, db_index=True)),
+ ('checksum', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
+ ))
+ db.send_create_signal('documents', ['DocumentVersion'])
+
+ # Adding unique constraint on 'DocumentVersion', fields ['document', 'mayor', 'minor', 'micro', 'release_level', 'serial']
+ db.create_unique('documents_documentversion', ['document_id', 'mayor', 'minor', 'micro', 'release_level', 'serial'])
+
+ # Adding field 'DocumentPage.document_version'
+ db.add_column('documents_documentpage', 'document_version', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.DocumentVersion'], null=True, blank=True), keep_default=False)
+
+
+ def backwards(self, orm):
+
+ # Removing unique constraint on 'DocumentVersion', fields ['document', 'mayor', 'minor', 'micro', 'release_level', 'serial']
+ db.delete_unique('documents_documentversion', ['document_id', 'mayor', 'minor', 'micro', 'release_level', 'serial'])
+
+ # Deleting model 'DocumentVersion'
+ db.delete_table('documents_documentversion')
+
+ # Deleting field 'DocumentPage.document_version'
+ db.delete_column('documents_documentpage', 'document_version_id')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'comments.comment': {
+ 'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
+ 'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
+ 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_pk': ('django.db.models.fields.TextField', [], {}),
+ 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
+ 'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'documents.document': {
+ 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'file_filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'file_mime_encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file_mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'a8389d7d-b9f4-4e51-ac24-dd9dd310fd8c'", 'max_length': '48', 'blank': 'True'})
+ },
+ 'documents.documentpage': {
+ 'Meta': {'ordering': "['page_number']", 'object_name': 'DocumentPage'},
+ 'content': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'document_version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentVersion']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'page_label': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'page_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'})
+ },
+ 'documents.documentpagetransformation': {
+ 'Meta': {'ordering': "('order',)", 'object_name': 'DocumentPageTransformation'},
+ 'arguments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentPage']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'transformation': ('django.db.models.fields.CharField', [], {'max_length': '128'})
+ },
+ 'documents.documenttype': {
+ 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
+ },
+ 'documents.documenttypefilename': {
+ 'Meta': {'ordering': "['filename']", 'object_name': 'DocumentTypeFilename'},
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']"}),
+ 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'documents.documentversion': {
+ 'Meta': {'unique_together': "(('document', 'mayor', 'minor', 'micro', 'release_level', 'serial'),)", 'object_name': 'DocumentVersion'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']", 'null': 'True', 'blank': 'True'}),
+ 'encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mayor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'micro': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'minor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'release_level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'serial': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ 'documents.recentdocument': {
+ 'Meta': {'ordering': "('-datetime_accessed',)", 'object_name': 'RecentDocument'},
+ 'datetime_accessed': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'sites.site': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'taggit.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
+ },
+ 'taggit.taggeditem': {
+ 'Meta': {'object_name': 'TaggedItem'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
+ }
+ }
+
+ complete_apps = ['documents']
diff --git a/apps/documents/migrations/0005_document_versions.py b/apps/documents/migrations/0005_document_versions.py
new file mode 100644
index 0000000000..7244593da3
--- /dev/null
+++ b/apps/documents/migrations/0005_document_versions.py
@@ -0,0 +1,176 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+class Migration(DataMigration):
+
+ def forwards(self, orm):
+ for document in orm.Document.objects.all():
+ document_version = document.documentversion_set.create(
+ document = document,
+ timestamp = document.date_added,
+ file = document.file,
+ mimetype = document.file_mimetype,
+ encoding = document.file_mime_encoding,
+ filename = document.file_filename,
+ checksum = document.checksum,
+ )
+ document_version.save()
+ for document_page in document.documentpage_set.all():
+ document_page.document_version = document_version
+ document_page.save()
+
+ def backwards(self, orm):
+ for document in orm.Document.objects.all():
+ document_version = document.documentversion_set.all()[0]
+ document.date_added = document_version.timestamp
+ document.file = document_version.file
+ document.file_mimetype = document_version.mimetype
+ document.file_mime_encoding = document_version.encoding
+ document.filename = document_version.filename
+ document.checksum = document_version.checksum
+ document.save()
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'comments.comment': {
+ 'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
+ 'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
+ 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_pk': ('django.db.models.fields.TextField', [], {}),
+ 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
+ 'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'documents.document': {
+ 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'file_filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'file_mime_encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file_mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'6c189f1f-1d85-48b5-9b7d-e8e319603e77'", 'max_length': '48', 'blank': 'True'})
+ },
+ 'documents.documentpage': {
+ 'Meta': {'ordering': "['page_number']", 'object_name': 'DocumentPage'},
+ 'content': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'document_version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentVersion']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'page_label': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'page_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'})
+ },
+ 'documents.documentpagetransformation': {
+ 'Meta': {'ordering': "('order',)", 'object_name': 'DocumentPageTransformation'},
+ 'arguments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentPage']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'transformation': ('django.db.models.fields.CharField', [], {'max_length': '128'})
+ },
+ 'documents.documenttype': {
+ 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
+ },
+ 'documents.documenttypefilename': {
+ 'Meta': {'ordering': "['filename']", 'object_name': 'DocumentTypeFilename'},
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']"}),
+ 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'documents.documentversion': {
+ 'Meta': {'unique_together': "(('document', 'mayor', 'minor', 'micro', 'release_level', 'serial'),)", 'object_name': 'DocumentVersion'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']", 'null': 'True', 'blank': 'True'}),
+ 'encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mayor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'micro': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'minor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'release_level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'serial': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ 'documents.recentdocument': {
+ 'Meta': {'ordering': "('-datetime_accessed',)", 'object_name': 'RecentDocument'},
+ 'datetime_accessed': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'sites.site': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'taggit.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
+ },
+ 'taggit.taggeditem': {
+ 'Meta': {'object_name': 'TaggedItem'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
+ }
+ }
+
+ complete_apps = ['documents']
diff --git a/apps/documents/migrations/0006_fix_invalid_document_version_id_keys.py b/apps/documents/migrations/0006_fix_invalid_document_version_id_keys.py
new file mode 100644
index 0000000000..03f4ba4133
--- /dev/null
+++ b/apps/documents/migrations/0006_fix_invalid_document_version_id_keys.py
@@ -0,0 +1,159 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+class Migration(DataMigration):
+
+ def forwards(self, orm):
+ qs = orm.DocumentPage.objects.filter(document_version=None)
+ #print 'Invalid document pages to delete: %s' % qs.count()
+ for document_page in qs:
+ document_page.delete()
+
+ def backwards(self, orm):
+ def backwards(self, orm):
+ raise RuntimeError('Cannot reverse this migration.')
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'comments.comment': {
+ 'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
+ 'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
+ 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_pk': ('django.db.models.fields.TextField', [], {}),
+ 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
+ 'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'documents.document': {
+ 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'file_filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'file_mime_encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file_mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'6c189f1f-1d85-48b5-9b7d-e8e319603e77'", 'max_length': '48', 'blank': 'True'})
+ },
+ 'documents.documentpage': {
+ 'Meta': {'ordering': "['page_number']", 'object_name': 'DocumentPage'},
+ 'content': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'document_version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentVersion']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'page_label': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'page_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'})
+ },
+ 'documents.documentpagetransformation': {
+ 'Meta': {'ordering': "('order',)", 'object_name': 'DocumentPageTransformation'},
+ 'arguments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentPage']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'transformation': ('django.db.models.fields.CharField', [], {'max_length': '128'})
+ },
+ 'documents.documenttype': {
+ 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
+ },
+ 'documents.documenttypefilename': {
+ 'Meta': {'ordering': "['filename']", 'object_name': 'DocumentTypeFilename'},
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']"}),
+ 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'documents.documentversion': {
+ 'Meta': {'unique_together': "(('document', 'mayor', 'minor', 'micro', 'release_level', 'serial'),)", 'object_name': 'DocumentVersion'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']", 'null': 'True', 'blank': 'True'}),
+ 'encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mayor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'micro': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'minor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'release_level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'serial': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ 'documents.recentdocument': {
+ 'Meta': {'ordering': "('-datetime_accessed',)", 'object_name': 'RecentDocument'},
+ 'datetime_accessed': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'sites.site': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'taggit.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
+ },
+ 'taggit.taggeditem': {
+ 'Meta': {'object_name': 'TaggedItem'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
+ }
+ }
+
+ complete_apps = ['documents']
diff --git a/apps/documents/migrations/0007_remove_old_file_fields.py b/apps/documents/migrations/0007_remove_old_file_fields.py
new file mode 100644
index 0000000000..02c074fcfd
--- /dev/null
+++ b/apps/documents/migrations/0007_remove_old_file_fields.py
@@ -0,0 +1,202 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Changing field 'DocumentVersion.document'
+ db.alter_column('documents_documentversion', 'document_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.Document']))
+
+ # Deleting field 'Document.date_updated'
+ db.delete_column('documents_document', 'date_updated')
+
+ # Deleting field 'Document.file'
+ db.delete_column('documents_document', 'file')
+
+ # Deleting field 'Document.file_filename'
+ db.delete_column('documents_document', 'file_filename')
+
+ # Deleting field 'Document.file_mimetype'
+ db.delete_column('documents_document', 'file_mimetype')
+
+ # Deleting field 'Document.checksum'
+ db.delete_column('documents_document', 'checksum')
+
+ # Deleting field 'Document.file_mime_encoding'
+ db.delete_column('documents_document', 'file_mime_encoding')
+
+ # Deleting field 'DocumentPage.document'
+ db.delete_column('documents_documentpage', 'document_id')
+
+ # Changing field 'DocumentPage.document_version'
+ db.alter_column('documents_documentpage', 'document_version_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.DocumentVersion']))
+
+
+ def backwards(self, orm):
+
+ # Changing field 'DocumentVersion.document'
+ db.alter_column('documents_documentversion', 'document_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.Document'], null=True))
+
+ # Adding field 'Document.date_updated'
+ db.add_column('documents_document', 'date_updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, default=datetime.datetime(2011, 12, 2, 2, 17, 25, 53565), blank=True), keep_default=False)
+
+ # Adding field 'Document.file'
+ db.add_column('documents_document', 'file', self.gf('django.db.models.fields.files.FileField')(default='', max_length=100), keep_default=False)
+
+ # Adding field 'Document.file_filename'
+ db.add_column('documents_document', 'file_filename', self.gf('django.db.models.fields.CharField')(default=u'', max_length=255, db_index=True), keep_default=False)
+
+ # Adding field 'Document.file_mimetype'
+ db.add_column('documents_document', 'file_mimetype', self.gf('django.db.models.fields.CharField')(default='', max_length=64), keep_default=False)
+
+ # Adding field 'Document.checksum'
+ db.add_column('documents_document', 'checksum', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+ # Adding field 'Document.file_mime_encoding'
+ db.add_column('documents_document', 'file_mime_encoding', self.gf('django.db.models.fields.CharField')(default='', max_length=64), keep_default=False)
+
+ # Adding field 'DocumentPage.document'
+ db.add_column('documents_documentpage', 'document', self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['documents.Document']), keep_default=False)
+
+ # Changing field 'DocumentPage.document_version'
+ db.alter_column('documents_documentpage', 'document_version_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.DocumentVersion'], null=True))
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'comments.comment': {
+ 'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
+ 'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
+ 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_pk': ('django.db.models.fields.TextField', [], {}),
+ 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
+ 'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'documents.document': {
+ 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
+ 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'83100718-e901-4880-95f8-3618749c8a99'", 'max_length': '48', 'blank': 'True'})
+ },
+ 'documents.documentpage': {
+ 'Meta': {'ordering': "['page_number']", 'object_name': 'DocumentPage'},
+ 'content': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentVersion']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'page_label': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'page_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'})
+ },
+ 'documents.documentpagetransformation': {
+ 'Meta': {'ordering': "('order',)", 'object_name': 'DocumentPageTransformation'},
+ 'arguments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentPage']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'transformation': ('django.db.models.fields.CharField', [], {'max_length': '128'})
+ },
+ 'documents.documenttype': {
+ 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
+ },
+ 'documents.documenttypefilename': {
+ 'Meta': {'ordering': "['filename']", 'object_name': 'DocumentTypeFilename'},
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']"}),
+ 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'documents.documentversion': {
+ 'Meta': {'unique_together': "(('document', 'mayor', 'minor', 'micro', 'release_level', 'serial'),)", 'object_name': 'DocumentVersion'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mayor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'micro': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'minor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'release_level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'serial': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ 'documents.recentdocument': {
+ 'Meta': {'ordering': "('-datetime_accessed',)", 'object_name': 'RecentDocument'},
+ 'datetime_accessed': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'sites.site': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'taggit.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
+ },
+ 'taggit.taggeditem': {
+ 'Meta': {'object_name': 'TaggedItem'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
+ }
+ }
+
+ complete_apps = ['documents']
diff --git a/apps/documents/migrations/0008_fix_mayor_field_name.py b/apps/documents/migrations/0008_fix_mayor_field_name.py
new file mode 100644
index 0000000000..dc540dfbec
--- /dev/null
+++ b/apps/documents/migrations/0008_fix_mayor_field_name.py
@@ -0,0 +1,172 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Removing unique constraint on 'DocumentVersion', fields ['release_level', 'micro', 'serial', 'document', 'mayor', 'minor']
+ db.delete_unique('documents_documentversion', ['release_level', 'micro', 'serial', 'document_id', 'mayor', 'minor'])
+
+ # Deleting field 'DocumentVersion.mayor'
+ db.delete_column('documents_documentversion', 'mayor')
+
+ # Adding field 'DocumentVersion.major'
+ db.add_column('documents_documentversion', 'major', self.gf('django.db.models.fields.PositiveIntegerField')(default=1), keep_default=False)
+
+ # Adding unique constraint on 'DocumentVersion', fields ['major', 'release_level', 'micro', 'serial', 'document', 'minor']
+ db.create_unique('documents_documentversion', ['major', 'release_level', 'micro', 'serial', 'document_id', 'minor'])
+
+
+ def backwards(self, orm):
+
+ # Removing unique constraint on 'DocumentVersion', fields ['major', 'release_level', 'micro', 'serial', 'document', 'minor']
+ db.delete_unique('documents_documentversion', ['major', 'release_level', 'micro', 'serial', 'document_id', 'minor'])
+
+ # Adding field 'DocumentVersion.mayor'
+ db.add_column('documents_documentversion', 'mayor', self.gf('django.db.models.fields.PositiveIntegerField')(default=1), keep_default=False)
+
+ # Deleting field 'DocumentVersion.major'
+ db.delete_column('documents_documentversion', 'major')
+
+ # Adding unique constraint on 'DocumentVersion', fields ['release_level', 'micro', 'serial', 'document', 'mayor', 'minor']
+ db.create_unique('documents_documentversion', ['release_level', 'micro', 'serial', 'document_id', 'mayor', 'minor'])
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'comments.comment': {
+ 'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
+ 'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
+ 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_pk': ('django.db.models.fields.TextField', [], {}),
+ 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
+ 'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'documents.document': {
+ 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
+ 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'750a3848-39cf-45a5-9a96-e948d09833d7'", 'max_length': '48', 'blank': 'True'})
+ },
+ 'documents.documentpage': {
+ 'Meta': {'ordering': "['page_number']", 'object_name': 'DocumentPage'},
+ 'content': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentVersion']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'page_label': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'page_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'})
+ },
+ 'documents.documentpagetransformation': {
+ 'Meta': {'ordering': "('order',)", 'object_name': 'DocumentPageTransformation'},
+ 'arguments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentPage']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'transformation': ('django.db.models.fields.CharField', [], {'max_length': '128'})
+ },
+ 'documents.documenttype': {
+ 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
+ },
+ 'documents.documenttypefilename': {
+ 'Meta': {'ordering': "['filename']", 'object_name': 'DocumentTypeFilename'},
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']"}),
+ 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'documents.documentversion': {
+ 'Meta': {'unique_together': "(('document', 'major', 'minor', 'micro', 'release_level', 'serial'),)", 'object_name': 'DocumentVersion'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'major': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'micro': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'minor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'release_level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'serial': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ 'documents.recentdocument': {
+ 'Meta': {'ordering': "('-datetime_accessed',)", 'object_name': 'RecentDocument'},
+ 'datetime_accessed': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'sites.site': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'taggit.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
+ },
+ 'taggit.taggeditem': {
+ 'Meta': {'object_name': 'TaggedItem'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
+ }
+ }
+
+ complete_apps = ['documents']
diff --git a/apps/documents/migrations/0009_add_comment_field.py b/apps/documents/migrations/0009_add_comment_field.py
new file mode 100644
index 0000000000..2010270407
--- /dev/null
+++ b/apps/documents/migrations/0009_add_comment_field.py
@@ -0,0 +1,155 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding field 'DocumentVersion.comment'
+ db.add_column('documents_documentversion', 'comment', self.gf('django.db.models.fields.TextField')(default='', blank=True), keep_default=False)
+
+
+ def backwards(self, orm):
+
+ # Deleting field 'DocumentVersion.comment'
+ db.delete_column('documents_documentversion', 'comment')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'comments.comment': {
+ 'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
+ 'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
+ 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_pk': ('django.db.models.fields.TextField', [], {}),
+ 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
+ 'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'documents.document': {
+ 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
+ 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'123068ef-26d2-45bb-8933-cb6818cd87e4'", 'max_length': '48', 'blank': 'True'})
+ },
+ 'documents.documentpage': {
+ 'Meta': {'ordering': "['page_number']", 'object_name': 'DocumentPage'},
+ 'content': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentVersion']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'page_label': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'page_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'})
+ },
+ 'documents.documentpagetransformation': {
+ 'Meta': {'ordering': "('order',)", 'object_name': 'DocumentPageTransformation'},
+ 'arguments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentPage']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'transformation': ('django.db.models.fields.CharField', [], {'max_length': '128'})
+ },
+ 'documents.documenttype': {
+ 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
+ },
+ 'documents.documenttypefilename': {
+ 'Meta': {'ordering': "['filename']", 'object_name': 'DocumentTypeFilename'},
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']"}),
+ 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'documents.documentversion': {
+ 'Meta': {'unique_together': "(('document', 'major', 'minor', 'micro', 'release_level', 'serial'),)", 'object_name': 'DocumentVersion'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'major': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'micro': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'minor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'release_level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'serial': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ 'documents.recentdocument': {
+ 'Meta': {'ordering': "('-datetime_accessed',)", 'object_name': 'RecentDocument'},
+ 'datetime_accessed': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'sites.site': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'taggit.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
+ },
+ 'taggit.taggeditem': {
+ 'Meta': {'object_name': 'TaggedItem'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
+ }
+ }
+
+ complete_apps = ['documents']
diff --git a/apps/documents/migrations/0010_auto__chg_field_document_date_added.py b/apps/documents/migrations/0010_auto__chg_field_document_date_added.py
new file mode 100644
index 0000000000..6220ef13ad
--- /dev/null
+++ b/apps/documents/migrations/0010_auto__chg_field_document_date_added.py
@@ -0,0 +1,155 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Changing field 'Document.date_added'
+ db.alter_column('documents_document', 'date_added', self.gf('django.db.models.fields.DateTimeField')())
+
+
+ def backwards(self, orm):
+
+ # Changing field 'Document.date_added'
+ db.alter_column('documents_document', 'date_added', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True))
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'comments.comment': {
+ 'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
+ 'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
+ 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_pk': ('django.db.models.fields.TextField', [], {}),
+ 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
+ 'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'documents.document': {
+ 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
+ 'date_added': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '48', 'blank': 'True'})
+ },
+ 'documents.documentpage': {
+ 'Meta': {'ordering': "['page_number']", 'object_name': 'DocumentPage'},
+ 'content': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'document_version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentVersion']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'page_label': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'page_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'})
+ },
+ 'documents.documentpagetransformation': {
+ 'Meta': {'ordering': "('order',)", 'object_name': 'DocumentPageTransformation'},
+ 'arguments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'document_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentPage']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'transformation': ('django.db.models.fields.CharField', [], {'max_length': '128'})
+ },
+ 'documents.documenttype': {
+ 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
+ },
+ 'documents.documenttypefilename': {
+ 'Meta': {'ordering': "['filename']", 'object_name': 'DocumentTypeFilename'},
+ 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']"}),
+ 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'documents.documentversion': {
+ 'Meta': {'unique_together': "(('document', 'major', 'minor', 'micro', 'release_level', 'serial'),)", 'object_name': 'DocumentVersion'},
+ 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'major': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'micro': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
+ 'minor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'release_level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'serial': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ 'documents.recentdocument': {
+ 'Meta': {'ordering': "('-datetime_accessed',)", 'object_name': 'RecentDocument'},
+ 'datetime_accessed': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'sites.site': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'taggit.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
+ },
+ 'taggit.taggeditem': {
+ 'Meta': {'object_name': 'TaggedItem'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
+ }
+ }
+
+ complete_apps = ['documents']
diff --git a/apps/documents/models.py b/apps/documents/models.py
index ed578c36b9..581e1eea4f 100644
--- a/apps/documents/models.py
+++ b/apps/documents/models.py
@@ -4,6 +4,8 @@ import hashlib
from ast import literal_eval
import base64
from StringIO import StringIO
+import datetime
+import logging
from django.db import models
from django.utils.translation import ugettext_lazy as _
@@ -21,6 +23,8 @@ from converter.api import convert
from converter.exceptions import UnknownFileFormat, UnkownConvertError
from mimetype.api import get_mimetype, get_icon_file_path, \
get_error_icon_file_path
+from converter.literals import (DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION,
+ DEFAULT_PAGE_NUMBER)
from documents.conf.settings import CHECKSUM_FUNCTION
from documents.conf.settings import UUID_FUNCTION
@@ -30,26 +34,25 @@ from documents.conf.settings import DISPLAY_SIZE
from documents.conf.settings import CACHE_PATH
from documents.conf.settings import ZOOM_MAX_LEVEL
from documents.conf.settings import ZOOM_MIN_LEVEL
-
from documents.managers import RecentDocumentManager, \
DocumentPageTransformationManager
from documents.utils import document_save_to_temp_dir
-from converter.literals import DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, \
- DEFAULT_PAGE_NUMBER
+from documents.literals import (RELEASE_LEVEL_FINAL, RELEASE_LEVEL_CHOICES,
+ VERSION_UPDATE_MAJOR, VERSION_UPDATE_MINOR, VERSION_UPDATE_MICRO)
# document image cache name hash function
HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest()
+logger = logging.getLogger(__name__)
+
def get_filename_from_uuid(instance, filename):
"""
Store the orignal filename of the uploaded file and replace it with
a UUID
"""
- instance.file_filename = filename
- uuid = UUID_FUNCTION()
- instance.uuid = uuid
- return uuid
+ instance.filename = filename
+ return UUID_FUNCTION()
class DocumentType(models.Model):
@@ -69,20 +72,13 @@ class DocumentType(models.Model):
class Document(models.Model):
- """
+ '''
Defines a single document with it's fields and properties
- """
+ '''
+ uuid = models.CharField(max_length=48, blank=True, editable=False)
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'), null=True, blank=True)
- file = models.FileField(upload_to=get_filename_from_uuid, storage=STORAGE_BACKEND(), verbose_name=_(u'file'))
- uuid = models.CharField(max_length=48, default=UUID_FUNCTION(), blank=True, editable=False)
- file_mimetype = models.CharField(max_length=64, default='', editable=False)
- file_mime_encoding = models.CharField(max_length=64, default='', editable=False)
- #FAT filename can be up to 255 using LFN
- file_filename = models.CharField(max_length=255, default=u'', editable=False, db_index=True)
- date_added = models.DateTimeField(verbose_name=_(u'added'), auto_now_add=True, db_index=True)
- date_updated = models.DateTimeField(verbose_name=_(u'updated'), auto_now=True)
- checksum = models.TextField(blank=True, null=True, verbose_name=_(u'checksum'), editable=False)
description = models.TextField(blank=True, null=True, verbose_name=_(u'description'), db_index=True)
+ date_added = models.DateTimeField(verbose_name=_(u'added'), db_index=True)
tags = TaggableManager()
@@ -105,148 +101,20 @@ class Document(models.Model):
ordering = ['-date_added']
def __unicode__(self):
- return self.get_fullname()
-
- def save(self, *args, **kwargs):
- """
- Overloaded save method that updates the document's checksum,
- mimetype, page count and transformation when originally created
- """
- new_document = not self.pk
- transformations = kwargs.pop('transformations', None)
- super(Document, self).save(*args, **kwargs)
-
- if new_document:
- #Only do this for new documents
- self.update_checksum(save=False)
- self.update_mimetype(save=False)
- self.save()
- self.update_page_count(save=False)
- if transformations:
- self.apply_default_transformations(transformations)
+ return self.latest_version.filename
@models.permalink
def get_absolute_url(self):
return ('document_view_simple', [self.pk])
- def get_fullname(self):
- """
- Return the fullname of the document's file
- """
- return self.file_filename
-
- def update_mimetype(self, save=True):
- """
- Read a document's file and determine the mimetype by calling the
- get_mimetype wrapper
- """
- if self.exists():
- try:
- self.file_mimetype, self.file_mime_encoding = get_mimetype(self.open(), self.get_fullname())
- except:
- self.file_mimetype = u''
- self.file_mime_encoding = u''
- finally:
- if save:
- self.save()
-
- def open(self):
- """
- Return a file descriptor to a document's file irrespective of
- the storage backend
- """
- return self.file.storage.open(self.file.path)
-
- def update_checksum(self, save=True):
- """
- Open a document's file and update the checksum field using the
- user provided checksum function
- """
- if self.exists():
- source = self.open()
- self.checksum = unicode(CHECKSUM_FUNCTION(source.read()))
- source.close()
- if save:
- self.save()
-
- def update_page_count(self, save=True):
- handle, filepath = tempfile.mkstemp()
- # Just need the filepath, close the file description
- os.close(handle)
-
- self.save_to_file(filepath)
- try:
- detected_pages = get_page_count(filepath)
- except UnknownFileFormat:
- # If converter backend doesn't understand the format,
- # use 1 as the total page count
- detected_pages = 1
- self.description = ugettext(u'This document\'s file format is not known, the page count has therefore defaulted to 1.')
- self.save()
- try:
- os.remove(filepath)
- except OSError:
- pass
-
- current_pages = DocumentPage.objects.filter(document=self).order_by('page_number',)
- if current_pages.count() > detected_pages:
- for page in current_pages[detected_pages:]:
- page.delete()
-
- for page_number in range(detected_pages):
- DocumentPage.objects.get_or_create(
- document=self, page_number=page_number + 1)
-
- if save:
- self.save()
-
- return detected_pages
-
- @property
- def page_count(self):
- return self.documentpage_set.count()
-
- def save_to_file(self, filepath, buffer_size=1024 * 1024):
- """
- Save a copy of the document from the document storage backend
- to the local filesystem
- """
- input_descriptor = self.open()
- output_descriptor = open(filepath, 'wb')
- while True:
- copy_buffer = input_descriptor.read(buffer_size)
- if copy_buffer:
- output_descriptor.write(copy_buffer)
- else:
- break
-
- output_descriptor.close()
- input_descriptor.close()
- return filepath
-
- def exists(self):
- """
- Returns a boolean value that indicates if the document's file
- exists in storage
- """
- return self.file.storage.exists(self.file.path)
-
- def apply_default_transformations(self, transformations):
- #Only apply default transformations on new documents
- if reduce(lambda x, y: x + y, [page.documentpagetransformation_set.count() for page in self.documentpage_set.all()]) == 0:
- for transformation in transformations:
- for document_page in self.documentpage_set.all():
- page_transformation = DocumentPageTransformation(
- document_page=document_page,
- order=0,
- transformation=transformation.get('transformation'),
- arguments=transformation.get('arguments')
- )
-
- page_transformation.save()
+ def save(self, *args, **kwargs):
+ if not self.pk:
+ self.uuid = UUID_FUNCTION()
+ self.date_added = datetime.datetime.now()
+ super(Document, self).save(*args, **kwargs)
def get_cached_image_name(self, page):
- document_page = self.documentpage_set.get(page_number=page)
+ document_page = self.pages.get(page_number=page)
transformations, warnings = document_page.get_transformation_list()
hash_value = HASH_FUNCTION(u''.join([self.checksum, unicode(page), unicode(transformations)]))
return os.path.join(CACHE_PATH, hash_value), transformations
@@ -297,24 +165,336 @@ class Document(models.Model):
def add_as_recent_document_for_user(self, user):
RecentDocument.objects.add_document_for_user(user, self)
-
- def delete(self, *args, **kwargs):
- super(Document, self).delete(*args, **kwargs)
- return self.file.storage.delete(self.file.path)
+
+ # TODO: investigate if Document's save method calls all of it
+ # DocumentVersion's delete methods
+ #def delete(self, *args, **kwargs):
+ # super(Document, self).delete(*args, **kwargs)
+ # for version in self.documentversion_set.all():
+ # version.file.storage.delete(version.file.path)
@property
def size(self):
if self.exists():
- return self.file.storage.size(self.file.path)
+ return self.latest_version.exists()
else:
return None
+ def new_version(self, file, comment=None, version_update=None, release_level=None, serial=None):
+ logger.debug('creating new document version')
+ if version_update:
+ new_version_dict = self.latest_version.get_new_version_dict(version_update)
+ new_version = DocumentVersion(
+ document=self,
+ file=file,
+ major = new_version_dict.get('major'),
+ minor = new_version_dict.get('minor'),
+ micro = new_version_dict.get('micro'),
+ release_level = release_level,
+ serial = serial,
+ comment = comment,
+ )
+ new_version.save()
+ else:
+ new_version_dict = {}
+ new_version = DocumentVersion(
+ document=self,
+ file=file,
+ )
+ new_version.save()
+
+
+ logger.debug('new_version_dict: %s' % new_version_dict)
+
+ logger.debug('new_version saved')
+ return new_version
+
+ # Proxy methods
+ def open(self):
+ '''
+ Return a file descriptor to a document's file irrespective of
+ the storage backend
+ '''
+ return self.latest_version.open()
+
+ def save_to_file(self, *args, **kwargs):
+ return self.latest_version.save_to_file(*args, **kwargs)
+
+ def exists(self):
+ '''
+ Returns a boolean value that indicates if the document's
+ latest version file exists in storage
+ '''
+ return self.latest_version.exists()
+
+ # Compatibility methods
+ @property
+ def file(self):
+ return self.latest_version.file
+
+ @property
+ def file_mimetype(self):
+ return self.latest_version.mimetype
+
+ @property
+ def file_mime_encoding(self):
+ return self.latest_version.encoding
+
+ @property
+ def file_filename(self):
+ return self.latest_version.filename
+
+ @property
+ def date_updated(self):
+ return self.latest_version.timestamp
+
+ @property
+ def checksum(self):
+ return self.latest_version.checksum
+
+ @property
+ def pages(self):
+ return self.latest_version.pages
+
+ @property
+ def page_count(self):
+ return self.pages.count()
+
+ @property
+ def latest_version(self):
+ return self.documentversion_set.order_by('-timestamp')[0]
+
+ @property
+ def first_version(self):
+ return self.documentversion_set.order_by('timestamp')[0]
+
+ @property
+ def versions(self):
+ return self.documentversion_set
+
+ def _get_filename(self):
+ return self.latest_version.filename
+
+ def _set_filename(self, value):
+ version = self.latest_version
+ version.filename = value
+ return version.save()
+
+ filename = property(_get_filename, _set_filename)
+
+
+class DocumentVersion(models.Model):
+ '''
+ Model that describes a document version and its properties
+ '''
+ @staticmethod
+ def get_version_update_choices(document_version):
+ return (
+ (VERSION_UPDATE_MAJOR, _(u'Major %(major)i.%(minor)i, (new release)') % document_version.get_new_version_dict(VERSION_UPDATE_MAJOR)),
+ (VERSION_UPDATE_MINOR, _(u'Minor %(major)i.%(minor)i, (some updates)') % document_version.get_new_version_dict(VERSION_UPDATE_MINOR)),
+ (VERSION_UPDATE_MICRO, _(u'Micro %(major)i.%(minor)i.%(micro)i, (fixes)') % document_version.get_new_version_dict(VERSION_UPDATE_MICRO))
+ )
+
+ document = models.ForeignKey(Document, verbose_name=_(u'document'), editable=False)
+ major = models.PositiveIntegerField(verbose_name=_(u'mayor'), default=1, editable=False)
+ minor = models.PositiveIntegerField(verbose_name=_(u'minor'), default=0, editable=False)
+ micro = models.PositiveIntegerField(verbose_name=_(u'micro'), default=0, editable=False)
+ release_level = models.PositiveIntegerField(choices=RELEASE_LEVEL_CHOICES, default=RELEASE_LEVEL_FINAL, verbose_name=_(u'release level'), editable=False)
+ serial = models.PositiveIntegerField(verbose_name=_(u'serial'), default=0, editable=False)
+ timestamp = models.DateTimeField(verbose_name=_(u'timestamp'), editable=False)
+ comment = models.TextField(blank=True, verbose_name=_(u'comment'))
+
+ # File related fields
+ file = models.FileField(upload_to=get_filename_from_uuid, storage=STORAGE_BACKEND(), verbose_name=_(u'file'))
+ mimetype = models.CharField(max_length=64, default='', editable=False)
+ encoding = models.CharField(max_length=64, default='', editable=False)
+ filename = models.CharField(max_length=255, default=u'', editable=False, db_index=True)
+ checksum = models.TextField(blank=True, null=True, verbose_name=_(u'checksum'), editable=False)
+
+ class Meta:
+ unique_together = ('document', 'major', 'minor', 'micro', 'release_level', 'serial')
+ verbose_name = _(u'document version')
+ verbose_name_plural = _(u'document version')
+
+ def __unicode__(self):
+ return self.get_formated_version()
+
+ def get_new_version_dict(self, version_update_type):
+ logger.debug('version_update_type: %s' % version_update_type)
+
+ if version_update_type == VERSION_UPDATE_MAJOR:
+ return {
+ 'major': self.major + 1,
+ 'minor': 0,
+ 'micro': 0,
+ }
+ elif version_update_type == VERSION_UPDATE_MINOR:
+ return {
+ 'major': self.major,
+ 'minor': self.minor + 1,
+ 'micro': 0,
+ }
+ elif version_update_type == VERSION_UPDATE_MICRO:
+ return {
+ 'major': self.major,
+ 'minor': self.minor,
+ 'micro': self.micro + 1,
+ }
+
+ def get_formated_version(self):
+ '''
+ Return the formatted version information
+ '''
+ vers = [u'%i.%i' % (self.major, self.minor), ]
+
+ if self.micro:
+ vers.append(u'.%i' % self.micro)
+ if self.release_level != RELEASE_LEVEL_FINAL:
+ vers.append(u'%s%i' % (self.get_release_level_display(), self.serial))
+ return u''.join(vers)
+
+ @property
+ def pages(self):
+ return self.documentpage_set
+
+ def save(self, *args, **kwargs):
+ '''
+ Overloaded save method that updates the document version's checksum,
+ mimetype, page count and transformation when created
+ '''
+ new_document = not self.pk
+ if not self.pk:
+ self.timestamp = datetime.datetime.now()
+
+ #Only do this for new documents
+ transformations = kwargs.pop('transformations', None)
+ super(DocumentVersion, self).save(*args, **kwargs)
+
+ if new_document:
+ #Only do this for new documents
+ self.update_checksum(save=False)
+ self.update_mimetype(save=False)
+ self.save()
+ self.update_page_count(save=False)
+ if transformations:
+ self.apply_default_transformations(transformations)
+
+ def update_checksum(self, save=True):
+ '''
+ Open a document version's file and update the checksum field using the
+ user provided checksum function
+ '''
+ if self.exists():
+ source = self.open()
+ self.checksum = unicode(CHECKSUM_FUNCTION(source.read()))
+ source.close()
+ if save:
+ self.save()
+
+ def update_page_count(self, save=True):
+ handle, filepath = tempfile.mkstemp()
+ # Just need the filepath, close the file description
+ os.close(handle)
+
+ self.save_to_file(filepath)
+ try:
+ detected_pages = get_page_count(filepath)
+ except UnknownFileFormat:
+ # If converter backend doesn't understand the format,
+ # use 1 as the total page count
+ detected_pages = 1
+ self.description = ugettext(u'This document\'s file format is not known, the page count has therefore defaulted to 1.')
+ self.save()
+ try:
+ os.remove(filepath)
+ except OSError:
+ pass
+
+ current_pages = self.documentpage_set.order_by('page_number',)
+ if current_pages.count() > detected_pages:
+ for page in current_pages[detected_pages:]:
+ page.delete()
+
+ for page_number in range(detected_pages):
+ DocumentPage.objects.get_or_create(
+ document_version=self, page_number=page_number + 1)
+
+ if save:
+ self.save()
+
+ return detected_pages
+
+ def apply_default_transformations(self, transformations):
+ #Only apply default transformations on new documents
+ if reduce(lambda x, y: x + y, [page.documentpagetransformation_set.count() for page in self.pages.all()]) == 0:
+ for transformation in transformations:
+ for document_page in self.pages.all():
+ page_transformation = DocumentPageTransformation(
+ document_page=document_page,
+ order=0,
+ transformation=transformation.get('transformation'),
+ arguments=transformation.get('arguments')
+ )
+
+ page_transformation.save()
+
+ def update_mimetype(self, save=True):
+ '''
+ Read a document verions's file and determine the mimetype by calling the
+ get_mimetype wrapper
+ '''
+ if self.exists():
+ try:
+ self.mimetype, self.encoding = get_mimetype(self.open(), self.filename)
+ except:
+ self.mimetype = u''
+ self.encoding = u''
+ finally:
+ if save:
+ self.save()
+
+ def delete(self, *args, **kwargs):
+ super(Document, self).delete(*args, **kwargs)
+ return self.file.storage.delete(self.file.path)
+
+ def exists(self):
+ '''
+ Returns a boolean value that indicates if the document's file
+ exists in storage
+ '''
+ return self.file.storage.exists(self.file.path)
+
+ def open(self):
+ '''
+ Return a file descriptor to a document version's file irrespective of
+ the storage backend
+ '''
+ return self.file.storage.open(self.file.path)
+
+ def save_to_file(self, filepath, buffer_size=1024 * 1024):
+ '''
+ Save a copy of the document from the document storage backend
+ to the local filesystem
+ '''
+ input_descriptor = self.open()
+ output_descriptor = open(filepath, 'wb')
+ while True:
+ copy_buffer = input_descriptor.read(buffer_size)
+ if copy_buffer:
+ output_descriptor.write(copy_buffer)
+ else:
+ break
+
+ output_descriptor.close()
+ input_descriptor.close()
+ return filepath
+
class DocumentTypeFilename(models.Model):
- """
+ '''
List of filenames available to a specific document type for the
quick rename functionality
- """
+ '''
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
filename = models.CharField(max_length=128, verbose_name=_(u'filename'), db_index=True)
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
@@ -329,10 +509,13 @@ class DocumentTypeFilename(models.Model):
class DocumentPage(models.Model):
- """
- Model that describes a document page including it's content
- """
- document = models.ForeignKey(Document, verbose_name=_(u'document'))
+ '''
+ Model that describes a document version page including it's content
+ '''
+ # New parent field
+ document_version = models.ForeignKey(DocumentVersion, verbose_name=_(u'document version'))#, null=True, blank=True) # TODO: Remove these after datamigration
+
+ # Unchanged fields
content = models.TextField(blank=True, null=True, verbose_name=_(u'content'), db_index=True)
page_label = models.CharField(max_length=32, blank=True, null=True, verbose_name=_(u'page label'))
page_number = models.PositiveIntegerField(default=1, editable=False, verbose_name=_(u'page number'), db_index=True)
@@ -341,7 +524,7 @@ class DocumentPage(models.Model):
return _(u'Page %(page_num)d out of %(total_pages)d of %(document)s') % {
'document': unicode(self.document),
'page_num': self.page_number,
- 'total_pages': self.document.documentpage_set.count()
+ 'total_pages': self.document_version.documentpage_set.count()
}
class Meta:
@@ -356,6 +539,15 @@ class DocumentPage(models.Model):
def get_absolute_url(self):
return ('document_page_view', [self.pk])
+ @property
+ def siblings(self):
+ return DocumentPage.objects.filter(document_version=self.document_version)
+
+ # Compatibility methods
+ @property
+ def document(self):
+ return self.document_version.document
+
class ArgumentsValidator(object):
message = _(u'Enter a valid value.')
@@ -421,10 +613,10 @@ class RecentDocument(models.Model):
# Register the fields that will be searchable
register('document', Document, _(u'document'), [
{'name': u'document_type__name', 'title': _(u'Document type')},
- {'name': u'file_mimetype', 'title': _(u'MIME type')},
- {'name': u'file_filename', 'title': _(u'Filename')},
+ {'name': u'documentversion__mimetype', 'title': _(u'MIME type')},
+ {'name': u'documentversion__filename', 'title': _(u'Filename')},
{'name': u'documentmetadata__value', 'title': _(u'Metadata value')},
- {'name': u'documentpage__content', 'title': _(u'Content')},
+ {'name': u'documentversion__documentpage__content', 'title': _(u'Content')},
{'name': u'description', 'title': _(u'Description')},
{'name': u'tags__name', 'title': _(u'Tags')},
{'name': u'comments__comment', 'title': _(u'Comments')},
diff --git a/apps/documents/urls.py b/apps/documents/urls.py
index e3cfbf598d..239ec62df4 100644
--- a/apps/documents/urls.py
+++ b/apps/documents/urls.py
@@ -33,6 +33,9 @@ urlpatterns = patterns('documents.views',
url(r'^(?P
\d+)/create/siblings/$', 'document_create_siblings', (), 'document_create_siblings'),
url(r'^(?P\d+)/find_duplicates/$', 'document_find_duplicates', (), 'document_find_duplicates'),
url(r'^(?P\d+)/clear_transformations/$', 'document_clear_transformations', (), 'document_clear_transformations'),
+
+ url(r'^(?P\d+)/version/all/$', 'document_version_list', (), 'document_version_list'),
+ url(r'^document/version/(?P\d+)/download/$', 'document_download', (), 'document_version_download'),
url(r'^multiple/clear_transformations/$', 'document_multiple_clear_transformations', (), 'document_multiple_clear_transformations'),
url(r'^duplicates/list/$', 'document_find_all_duplicates', (), 'document_find_all_duplicates'),
diff --git a/apps/documents/views.py b/apps/documents/views.py
index ba0e18e315..4b08e9f5ee 100644
--- a/apps/documents/views.py
+++ b/apps/documents/views.py
@@ -45,16 +45,17 @@ from documents.literals import PERMISSION_DOCUMENT_CREATE, \
from documents.literals import HISTORY_DOCUMENT_CREATED, \
HISTORY_DOCUMENT_EDITED, HISTORY_DOCUMENT_DELETED
-from documents.forms import DocumentTypeSelectForm, \
- DocumentForm_edit, DocumentPropertiesForm, \
- DocumentPreviewForm, \
- DocumentPageForm, DocumentPageTransformationForm, \
- DocumentContentForm, DocumentPageForm_edit, \
- DocumentPageForm_text, PrintForm, DocumentTypeForm, \
- DocumentTypeFilenameForm, DocumentTypeFilenameForm_create
+from documents.forms import (DocumentTypeSelectForm,
+ DocumentForm_edit, DocumentPropertiesForm,
+ DocumentPreviewForm, DocumentPageForm,
+ DocumentPageTransformationForm, DocumentContentForm,
+ DocumentPageForm_edit, DocumentPageForm_text, PrintForm,
+ DocumentTypeForm, DocumentTypeFilenameForm,
+ DocumentTypeFilenameForm_create)
from documents.wizards import DocumentCreateWizard
-from documents.models import Document, DocumentType, DocumentPage, \
- DocumentPageTransformation, RecentDocument, DocumentTypeFilename
+from documents.models import (Document, DocumentType, DocumentPage,
+ DocumentPageTransformation, RecentDocument, DocumentTypeFilename,
+ DocumentVersion)
# Document type permissions
from documents.literals import PERMISSION_DOCUMENT_TYPE_EDIT, \
@@ -65,7 +66,7 @@ def document_list(request, object_list=None, title=None, extra_context=None):
check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
context = {
- 'object_list': object_list if not (object_list is None) else Document.objects.only('file_filename',).all(),
+ 'object_list': object_list if not (object_list is None) else Document.objects.all(),
'title': title if title else _(u'documents'),
'multi_select_as_buttons': True,
'hide_links': True,
@@ -114,7 +115,7 @@ def document_view(request, document_id, advanced=False):
if advanced:
document_properties_form = DocumentPropertiesForm(instance=document, extra_fields=[
- {'label': _(u'Filename'), 'field': 'file_filename'},
+ {'label': _(u'Filename'), 'field': 'filename'},
{'label': _(u'File mimetype'), 'field': 'file_mimetype'},
{'label': _(u'File mime encoding'), 'field': 'file_mime_encoding'},
{'label': _(u'File size'), 'field':lambda x: pretty_size(x.size) if x.size else '-'},
@@ -241,15 +242,15 @@ def document_edit(request, document_id):
for warning in warnings:
messages.warning(request, warning)
- document.file_filename = form.cleaned_data['new_filename']
+ document.filename = form.cleaned_data['new_filename']
document.description = form.cleaned_data['description']
if 'document_type_available_filenames' in form.cleaned_data:
if form.cleaned_data['document_type_available_filenames']:
- document.file_filename = form.cleaned_data['document_type_available_filenames'].filename
+ document.filename = form.cleaned_data['document_type_available_filenames'].filename
document.save()
- create_history(HISTORY_DOCUMENT_EDITED, document, {'user': request.user, 'diff': return_diff(old_document, document, ['file_filename', 'description'])})
+ create_history(HISTORY_DOCUMENT_EDITED, document, {'user': request.user, 'diff': return_diff(old_document, document, ['filename', 'description'])})
RecentDocument.objects.add_document_for_user(request.user, document)
messages.success(request, _(u'Document "%s" edited successfully.') % document)
@@ -262,7 +263,7 @@ def document_edit(request, document_id):
return HttpResponseRedirect(document.get_absolute_url())
else:
form = DocumentForm_edit(instance=document, initial={
- 'new_filename': document.file_filename})
+ 'new_filename': document.filename})
return render_to_response('generic_form.html', {
'form': form,
@@ -290,23 +291,27 @@ def get_document_image(request, document_id, size=PREVIEW_SIZE, base64_version=F
if base64_version:
return HttpResponse(u'
' % document.get_image(size=size, page=page, zoom=zoom, rotation=rotation, as_base64=True))
else:
- # TODO: hardcoded MIMETYPE
+ # TODO: fix hardcoded MIMETYPE
return sendfile.sendfile(request, document.get_image(size=size, page=page, zoom=zoom, rotation=rotation), mimetype=DEFAULT_FILE_FORMAT_MIMETYPE)
-
-def document_download(request, document_id):
+def document_download(request, document_id=None, document_version_pk=None):
check_permissions(request.user, [PERMISSION_DOCUMENT_DOWNLOAD])
- document = get_object_or_404(Document, pk=document_id)
+ if document_version_pk:
+ document_version = get_object_or_404(DocumentVersion, pk=document_version_pk)
+ else:
+ document_version = get_object_or_404(Document, pk=document_id).latest_version
+
try:
- #Test permissions and trigger exception
- document.open()
+ # Test permissions and trigger exception
+ fd = document_version.open()
+ fd.close()
return serve_file(
request,
- document.file,
- save_as=u'"%s"' % document.get_fullname(),
- content_type=document.file_mimetype if document.file_mimetype else 'application/octet-stream'
+ document_version.file,
+ save_as=u'"%s"' % document_version.filename,
+ content_type=document_version.mimetype if document_version.mimetype else 'application/octet-stream'
)
except Exception, e:
messages.error(request, e)
@@ -481,16 +486,16 @@ def document_update_page_count(request):
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
office_converter = OfficeConverter()
- qs = Document.objects.exclude(file_filename__iendswith='dxf').filter(file_mimetype__in=office_converter.mimetypes())
+ qs = DocumentVersion.objects.exclude(filename__iendswith='dxf').filter(mimetype__in=office_converter.mimetypes())
if request.method == 'POST':
updated = 0
processed = 0
- for document in qs:
- old_page_count = document.page_count
- document.update_page_count()
+ for document_version in qs:
+ old_page_count = document_version.pages.count()
+ document_version.update_page_count()
processed += 1
- if old_page_count != document.page_count:
+ if old_page_count != document_version.pages.count():
updated += 1
messages.success(request, _(u'Page count update complete. Documents processed: %(total)d, documents with changed page count: %(change)d') % {
@@ -526,7 +531,7 @@ def document_clear_transformations(request, document_id=None, document_id_list=N
if request.method == 'POST':
for document in documents:
try:
- for document_page in document.documentpage_set.all():
+ for document_page in document.pages.all():
document_page.document.invalidate_cached_image(document_page.page_number)
for transformation in document_page.documentpagetransformation_set.all():
transformation.delete()
@@ -662,11 +667,11 @@ def document_page_navigation_next(request, document_page_id):
view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path)
document_page = get_object_or_404(DocumentPage, pk=document_page_id)
- if document_page.page_number >= document_page.document.documentpage_set.count():
+ if document_page.page_number >= document_page.siblings.count():
messages.warning(request, _(u'There are no more pages in this document'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', u'/'))
else:
- document_page = get_object_or_404(DocumentPage, document=document_page.document, page_number=document_page.page_number + 1)
+ document_page = get_object_or_404(document_page.siblings, page_number=document_page.page_number + 1)
return HttpResponseRedirect(reverse(view, args=[document_page.pk]))
@@ -679,7 +684,7 @@ def document_page_navigation_previous(request, document_page_id):
messages.warning(request, _(u'You are already at the first page of this document'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', u'/'))
else:
- document_page = get_object_or_404(DocumentPage, document=document_page.document, page_number=document_page.page_number - 1)
+ document_page = get_object_or_404(document_page.siblings, page_number=document_page.page_number - 1)
return HttpResponseRedirect(reverse(view, args=[document_page.pk]))
@@ -688,7 +693,7 @@ def document_page_navigation_first(request, document_page_id):
view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path)
document_page = get_object_or_404(DocumentPage, pk=document_page_id)
- document_page = get_object_or_404(DocumentPage, document=document_page.document, page_number=1)
+ document_page = get_object_or_404(document_page.siblings, page_number=1)
return HttpResponseRedirect(reverse(view, args=[document_page.pk]))
@@ -697,7 +702,7 @@ def document_page_navigation_last(request, document_page_id):
view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path)
document_page = get_object_or_404(DocumentPage, pk=document_page_id)
- document_page = get_object_or_404(DocumentPage, document=document_page.document, page_number=document_page.document.documentpage_set.count())
+ document_page = get_object_or_404(document_page.siblings, page_number=document_page.siblings.count())
return HttpResponseRedirect(reverse(view, args=[document_page.pk]))
@@ -851,9 +856,9 @@ def document_hard_copy(request, document_id):
if page_range:
page_range = parse_range(page_range)
- pages = document.documentpage_set.filter(page_number__in=page_range)
+ pages = document.pages.filter(page_number__in=page_range)
else:
- pages = document.documentpage_set.all()
+ pages = document.pages.all()
return render_to_response('document_print.html', {
'object': document,
@@ -1142,3 +1147,44 @@ def document_clear_image_cache(request):
'title': _(u'Are you sure you wish to clear the document image cache?'),
'form_icon': u'camera_delete.png',
}, context_instance=RequestContext(request))
+
+
+def document_version_list(request, document_pk):
+ check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
+ document = get_object_or_404(Document, pk=document_pk)
+
+ context = {
+ 'object_list': document.versions.order_by('-timestamp'),
+ 'title': _(u'versions for document: %s') % document,
+ 'hide_object': True,
+ 'object': document,
+ 'extra_columns': [
+ {
+ 'name': _(u'version'),
+ 'attribute': 'get_formated_version',
+ },
+ {
+ 'name': _(u'time and date'),
+ 'attribute': 'timestamp',
+ },
+ {
+ 'name': _(u'mimetype'),
+ 'attribute': 'mimetype',
+ },
+ {
+ 'name': _(u'encoding'),
+ 'attribute': 'encoding',
+ },
+ {
+ 'name': _(u'filename'),
+ 'attribute': 'filename',
+ },
+ {
+ 'name': _(u'comment'),
+ 'attribute': 'comment',
+ },
+ ]
+ }
+
+ return render_to_response('generic_list.html', context,
+ context_instance=RequestContext(request))
diff --git a/apps/linking/forms.py b/apps/linking/forms.py
index 9568994b89..1e90e16c8a 100644
--- a/apps/linking/forms.py
+++ b/apps/linking/forms.py
@@ -45,7 +45,7 @@ class SmartLinkImageWidget(forms.widgets.Widget):
for document in value['documents']:
output.append(u'' % (u'border: 5px solid black; padding: 3px;' if value['current_document'] == document else u''))
output.append(u'
%s
' % document)
- output.append(u'
%s: %d
' % (ugettext(u'Pages'), document.documentpage_set.count()))
+ output.append(u'
%s: %d
' % (ugettext(u'Pages'), document.pages.count()))
output.append(get_tags_inline_widget(document))
output.append(u'
' % document)
output.append(document_html_widget(document, click_view='document_display', view='document_preview_multipage', fancybox_class='fancybox-noscaling', gallery_name=u'smart_link_%d_documents_gallery' % value['smart_link_instance'].pk))
diff --git a/apps/linking/managers.py b/apps/linking/managers.py
index 03f9203b24..050ddffea2 100644
--- a/apps/linking/managers.py
+++ b/apps/linking/managers.py
@@ -59,7 +59,7 @@ class SmartLinkManager(models.Manager):
if total_query:
try:
document_qs = Document.objects.filter(total_query)
- result[smart_link] = {'documents': document_qs.order_by('file_filename') or []}
+ result[smart_link] = {'documents': document_qs.order_by('date_added') or []}
except Exception, e:
result[smart_link] = {'documents': []}
errors.append(e)
diff --git a/apps/main/__init__.py b/apps/main/__init__.py
index 0532245481..582747e0d5 100644
--- a/apps/main/__init__.py
+++ b/apps/main/__init__.py
@@ -8,24 +8,33 @@ from project_tools.api import register_tool
from main.conf.settings import SIDE_BAR_SEARCH
from main.conf.settings import DISABLE_HOME_VIEW
+__author__ = 'Roberto Rosario'
+__copyright__ = 'Copyright 2011 Roberto Rosario'
+__credits__ = ['Roberto Rosario',]
+__license__ = 'GPL'
+__maintainer__ = 'Roberto Rosario'
+__email__ = 'roberto.rosario.gonzalez@gmail.com'
+__status__ = 'Production'
+
+__version_info__ = {
+ 'major': 0,
+ 'minor': 11,
+ 'micro': 0,
+ 'releaselevel': 'beta',
+ 'serial': 2
+}
+
def is_superuser(context):
return context['request'].user.is_staff or context['request'].user.is_superuser
+
maintenance_menu = {'text': _(u'maintenance'), 'view': 'maintenance_menu', 'famfam': 'wrench', 'icon': 'wrench.png'}
statistics = {'text': _(u'statistics'), 'view': 'statistics', 'famfam': 'table', 'icon': 'blackboard_sum.png'}
diagnostics = {'text': _(u'diagnostics'), 'view': 'diagnostics', 'famfam': 'pill', 'icon': 'pill.png'}
sentry = {'text': _(u'sentry'), 'view': 'sentry', 'famfam': 'bug', 'icon': 'bug.png', 'condition': is_superuser}
admin_site = {'text': _(u'admin site'), 'view': 'admin:index', 'famfam': 'keyboard', 'icon': 'keyboard.png', 'condition': is_superuser}
-__version_info__ = {
- 'major': 0,
- 'minor': 10,
- 'micro': 0,
- 'releaselevel': 'final',
- 'serial': 0
-}
-
if not DISABLE_HOME_VIEW:
register_top_menu('home', link={'text': _(u'home'), 'view': 'home', 'famfam': 'house'}, position=0)
if not SIDE_BAR_SEARCH:
@@ -36,14 +45,15 @@ def get_version():
"""
Return the formatted version information
"""
- vers = ["%(major)i.%(minor)i" % __version_info__, ]
+ vers = ['%(major)i.%(minor)i' % __version_info__, ]
if __version_info__['micro']:
- vers.append(".%(micro)i" % __version_info__)
+ vers.append('.%(micro)i' % __version_info__)
if __version_info__['releaselevel'] != 'final':
vers.append('%(releaselevel)s%(serial)i' % __version_info__)
return ''.join(vers)
+
__version__ = get_version()
register_setup(admin_site)
diff --git a/apps/ocr/__init__.py b/apps/ocr/__init__.py
index def0d7064b..b07fa07d72 100644
--- a/apps/ocr/__init__.py
+++ b/apps/ocr/__init__.py
@@ -108,11 +108,14 @@ def document_post_save(sender, instance, **kwargs):
post_save.connect(document_post_save, sender=Document)
-@receiver(post_save, dispatch_uid='call_queue', sender=QueueDocument)
-def call_queue(sender, **kwargs):
- if kwargs.get('created', False):
- logger.debug('got call_queue signal: %s' % kwargs)
- task_process_document_queues()
+# Disabled because it appears Django execute signals using the same
+# process effectively blocking the view until the OCR process completes
+# which could take several minutes :/
+#@receiver(post_save, dispatch_uid='call_queue', sender=QueueDocument)
+#def call_queue(sender, **kwargs):
+# if kwargs.get('created', False):
+# logger.debug('got call_queue signal: %s' % kwargs)
+# task_process_document_queues()
create_default_queue()
diff --git a/apps/ocr/api.py b/apps/ocr/api.py
index 4d70443f92..e568ecf6c8 100644
--- a/apps/ocr/api.py
+++ b/apps/ocr/api.py
@@ -88,7 +88,7 @@ def do_document_ocr(queue_document):
parser, if the parser fails or if there is no parser registered for
the document mimetype do a visual OCR by calling tesseract
"""
- for document_page in queue_document.document.documentpage_set.all():
+ for document_page in queue_document.document.pages.all():
try:
# Try to extract text by means of a parser
parse_document_page(document_page)
diff --git a/apps/ocr/parsers/__init__.py b/apps/ocr/parsers/__init__.py
index 8fac71c084..3d5a39635e 100644
--- a/apps/ocr/parsers/__init__.py
+++ b/apps/ocr/parsers/__init__.py
@@ -26,7 +26,7 @@ def register_parser(function, mimetype=None, mimetypes=None):
def pdf_parser(document_page, descriptor=None):
if not descriptor:
- descriptor = document_page.document.open()
+ descriptor = document_page.document_version.open()
pdf_pages = slate.PDF(descriptor)
descriptor.close()
diff --git a/apps/rest_api/resources.py b/apps/rest_api/resources.py
index 99a5c26613..869c78e407 100644
--- a/apps/rest_api/resources.py
+++ b/apps/rest_api/resources.py
@@ -8,15 +8,46 @@ from converter.exceptions import UnknownFileFormat, UnkownConvertError
class DocumentResourceSimple(ModelResource):
model = Document
- fields = ('url', 'pk', 'document_type', 'uuid', 'date_added', 'description', 'tags', 'comments', 'expensive_methods', 'files')
+ fields = ('url', 'pk', 'document_type', 'uuid', 'date_added', 'description', 'tags', 'comments', 'expensive_methods', 'versions')
- def files(self, instance):
+ def versions(self, instance):
+ return [
+ {
+ 'version': version.get_formated_version(),
+ 'major': version.major,
+ 'minor': version.minor,
+ 'micro': version.micro,
+ 'release_level': version.release_level,
+ 'serial': version.serial,
+ 'timestamp': version.timestamp,
+ 'comment': version.comment,
+ 'mimetype': version.mimetype,
+ 'encoding': version.encoding,
+ 'filename': version.filename,
+ 'checksum': version.checksum,
+ 'download': reverse('document_version_download', args=[version.pk]),
+ 'stored_filename': version.file.name,
+ # TODO: Add transformations
+ 'pages': [
+ {
+ 'content': page.content,
+ 'page_label': page.page_label,
+ 'page_number': page.page_number,
+ }
+ for page in version.pages.all()
+ ]
+
+ }
+ for version in instance.versions.all()
+ ]
+
+ '''
return [
{
'version': 1,
'mimetype': instance.file_mimetype,
'encoding': instance.file_mime_encoding,
- 'filename': instance.get_fullname(),
+ 'filename': instance.filename,
'date_updated': instance.date_updated,
'checksum': instance.checksum,
'size': instance.size,
@@ -33,6 +64,6 @@ class DocumentResourceSimple(ModelResource):
]
}
]
-
+ '''
def expensive_methods(self, instance):
return []
diff --git a/apps/sources/__init__.py b/apps/sources/__init__.py
index ad34940468..94d2727c9c 100644
--- a/apps/sources/__init__.py
+++ b/apps/sources/__init__.py
@@ -5,6 +5,8 @@ from navigation.api import register_links, \
from permissions.api import register_permission, set_namespace_title
from common.utils import encapsulate
from project_setup.api import register_setup
+from documents.models import Document
+from documents.literals import PERMISSION_DOCUMENT_CREATE
from sources.staging import StagingFile
from sources.models import WebForm, StagingFolder, SourceTransformation, \
@@ -41,6 +43,8 @@ setup_source_transformation_delete = {'text': _(u'delete'), 'view': 'setup_sourc
source_list = {'text': _(u'Document sources'), 'view': 'setup_web_form_list', 'famfam': 'page_add', 'children_url_regex': [r'sources/setup']}
+upload_interactive_version = {'text': _(u'upload new version'), 'view': 'upload_interactive_version', 'args': 'object.pk', 'famfam': 'page_add', 'permissions': [PERMISSION_DOCUMENT_CREATE]}
+
register_links(StagingFile, [staging_file_delete])
register_links(SourceTransformation, [setup_source_transformation_edit, setup_source_transformation_delete])
@@ -61,6 +65,9 @@ register_links(StagingFolder, [setup_source_transformation_list, setup_source_ed
register_links(WatchFolder, [setup_web_form_list, setup_staging_folder_list, setup_watch_folder_list], menu_name='form_header')
register_links(WatchFolder, [setup_source_transformation_list, setup_source_edit, setup_source_delete])
+# Document version
+register_links(Document, [upload_interactive_version])
+
register_links(['setup_source_transformation_create', 'setup_source_transformation_edit', 'setup_source_transformation_delete', 'setup_source_transformation_list'], [setup_source_transformation_create], menu_name='sidebar')
source_views = ['setup_web_form_list', 'setup_staging_folder_list', 'setup_watch_folder_list', 'setup_source_edit', 'setup_source_delete', 'setup_source_create', 'setup_source_transformation_list', 'setup_source_transformation_edit', 'setup_source_transformation_delete', 'setup_source_transformation_create']
diff --git a/apps/sources/forms.py b/apps/sources/forms.py
index de9b7ee1ce..4b046994cf 100644
--- a/apps/sources/forms.py
+++ b/apps/sources/forms.py
@@ -37,7 +37,7 @@ class StagingDocumentForm(DocumentForm):
staging_list_index = self.fields.keyOrder.index('staging_file_id')
staging_list = self.fields.keyOrder.pop(staging_list_index)
self.fields.keyOrder.insert(0, staging_list)
-
+
staging_file_id = forms.ChoiceField(label=_(u'Staging file'))
class Meta(DocumentForm.Meta):
@@ -45,6 +45,8 @@ class StagingDocumentForm(DocumentForm):
class WebFormForm(DocumentForm):
+ file = forms.FileField(label=_(u'File'))
+
def __init__(self, *args, **kwargs):
show_expand = kwargs.pop('show_expand', False)
self.source = kwargs.pop('source')
@@ -56,6 +58,10 @@ class WebFormForm(DocumentForm):
help_text=ugettext(u'Upload a compressed file\'s contained files as individual documents')
)
+ # Move the file filed to the top
+ self.fields.keyOrder.remove('file')
+ self.fields.keyOrder.insert(0, 'file')
+
def clean_file(self):
data = self.cleaned_data['file']
validate_whitelist_blacklist(data.name, self.source.whitelist.split(','), self.source.blacklist.split(','))
diff --git a/apps/sources/models.py b/apps/sources/models.py
index c97f2f4ca4..44822ee0ba 100644
--- a/apps/sources/models.py
+++ b/apps/sources/models.py
@@ -52,7 +52,7 @@ class BaseModel(models.Model):
def get_transformation_list(self):
return SourceTransformation.transformations.get_for_object_as_list(self)
- def upload_file(self, file_object, filename=None, document_type=None, expand=False, metadata_dict_list=None, user=None):
+ def upload_file(self, file_object, filename=None, document_type=None, expand=False, metadata_dict_list=None, user=None, document=None, new_version_data=None):
if expand:
try:
cf = CompressedFile(file_object)
@@ -63,31 +63,39 @@ class BaseModel(models.Model):
except NotACompressedFile:
self.upload_single_file(file_object, filename, document_type, metadata_dict_list, user)
else:
- self.upload_single_file(file_object, filename, document_type, metadata_dict_list, user)
+ self.upload_single_file(file_object, filename, document_type, metadata_dict_list, user, document, new_version_data)
file_object.close()
- def upload_single_file(self, file_object, filename=None, document_type=None, metadata_dict_list=None, user=None):
- transformations, errors = self.get_transformation_list()
- document = Document(file=file_object)
- if document_type:
- document.document_type = document_type
- document.save()
+ def upload_single_file(self, file_object, filename=None, document_type=None, metadata_dict_list=None, user=None, document=None, new_version_data=None):
+ if not document:
+ document = Document()
+ if document_type:
+ document.document_type = document_type
+ document.save()
+
+ if metadata_dict_list:
+ save_metadata_list(metadata_dict_list, document, create=True)
+ warnings = update_indexes(document)
+
+ if user:
+ document.add_as_recent_document_for_user(user)
+ create_history(HISTORY_DOCUMENT_CREATED, document, {'user': user})
+ else:
+ create_history(HISTORY_DOCUMENT_CREATED, document)
+
+ if not new_version_data:
+ new_version_data = {}
+
+ new_version = document.new_version(file=file_object, **new_version_data)
if filename:
- document.file_filename = filename
- document.save()
+ new_version.filename = filename
+ new_version.save()
- document.apply_default_transformations(transformations)
+ transformations, errors = self.get_transformation_list()
- if metadata_dict_list:
- save_metadata_list(metadata_dict_list, document, create=True)
- warnings = update_indexes(document)
-
- if user:
- document.add_as_recent_document_for_user(user)
- create_history(HISTORY_DOCUMENT_CREATED, document, {'user': user})
- else:
- create_history(HISTORY_DOCUMENT_CREATED, document)
+ new_version.apply_default_transformations(transformations)
+ #TODO: new HISTORY for version updates
class Meta:
ordering = ('title',)
diff --git a/apps/sources/urls.py b/apps/sources/urls.py
index b75573382d..cd42328138 100644
--- a/apps/sources/urls.py
+++ b/apps/sources/urls.py
@@ -8,8 +8,11 @@ urlpatterns = patterns('sources.views',
url(r'^staging_file/type/(?P
\w+)/(?P\d+)/(?P\w+)/delete/$', 'staging_file_delete', (), 'staging_file_delete'),
url(r'^staging_file/type/staging_folder/(?P\d+)/(?P\w+)/thumbnail/$', 'staging_file_thumbnail', (), 'staging_file_thumbnail'),
- url(r'^upload/interactive/(?P\w+)/(?P\d+)/$', 'upload_interactive', (), 'upload_interactive'),
- url(r'^upload/interactive/$', 'upload_interactive', (), 'upload_interactive'),
+ url(r'^upload/document/new/interactive/(?P\w+)/(?P\d+)/$', 'upload_interactive', (), 'upload_interactive'),
+ url(r'^upload/document/new/interactive/$', 'upload_interactive', (), 'upload_interactive'),
+
+ url(r'^upload/document/(?P\d+)/version/interactive/(?P\w+)/(?P\d+)/$', 'upload_interactive', (), 'upload_interactive_version'),
+ url(r'^upload/document/(?P\d+)/version/interactive/$', 'upload_interactive', (), 'upload_interactive_version'),
#Setup views
diff --git a/apps/sources/views.py b/apps/sources/views.py
index c2cde5e7d8..c668b23909 100644
--- a/apps/sources/views.py
+++ b/apps/sources/views.py
@@ -8,7 +8,7 @@ from django.utils.translation import ugettext
from django.utils.safestring import mark_safe
from documents.literals import PERMISSION_DOCUMENT_CREATE
-from documents.models import DocumentType
+from documents.models import DocumentType, Document
from documents.conf.settings import THUMBNAIL_SIZE
from metadata.api import decode_metadata_from_url, metadata_repr_as_list
from permissions.api import check_permissions
@@ -35,30 +35,34 @@ def return_function(obj):
return lambda context: context['source'].source_type == obj.source_type and context['source'].pk == obj.pk
-def get_active_tab_links():
- tab_links = []
+def get_tab_link_for_source(source, document=None):
+ if document:
+ view = u'upload_interactive_version'
+ args = [document.pk, u'"%s"' % source.source_type, source.pk]
+ else:
+ view = u'upload_interactive'
+ args = [u'"%s"' % source.source_type, source.pk]
+
+ return {
+ 'text': source.title,
+ 'view': view,
+ 'args': args,
+ 'famfam': source.icon,
+ 'keep_query': True,
+ 'conditional_highlight': return_function(source),
+ }
+
+def get_active_tab_links(document=None):
+ tab_links = []
+
web_forms = WebForm.objects.filter(enabled=True)
for web_form in web_forms:
- tab_links.append({
- 'text': web_form.title,
- 'view': 'upload_interactive',
- 'args': [u'"%s"' % web_form.source_type, web_form.pk],
- 'famfam': web_form.icon,
- 'keep_query': True,
- 'conditional_highlight': return_function(web_form),
- })
+ tab_links.append(get_tab_link_for_source(web_form, document))
staging_folders = StagingFolder.objects.filter(enabled=True)
for staging_folder in staging_folders:
- tab_links.append({
- 'text': staging_folder.title,
- 'view': 'upload_interactive',
- 'args': [u'"%s"' % staging_folder.source_type, staging_folder.pk],
- 'famfam': staging_folder.icon,
- 'keep_query': True,
- 'conditional_highlight': return_function(staging_folder),
- })
+ tab_links.append(get_tab_link_for_source(staging_folder, document))
return {
'tab_links': tab_links,
@@ -66,15 +70,19 @@ def get_active_tab_links():
SOURCE_CHOICE_STAGING: staging_folders
}
-
-def upload_interactive(request, source_type=None, source_id=None):
+def upload_interactive(request, source_type=None, source_id=None, document_pk=None):
check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE])
subtemplates_list = []
- context = {}
+ if document_pk:
+ document = get_object_or_404(Document, pk=document_pk)
+ results = get_active_tab_links(document)
+ else:
+ document = None
+ results = get_active_tab_links()
- results = get_active_tab_links()
+ context = {}
if results[SOURCE_CHOICE_WEB_FORM].count() == 0 and results[SOURCE_CHOICE_STAGING].count() == 0:
source_setup_link = mark_safe('%s' % (reverse('setup_web_form_list'), ugettext(u'here')))
@@ -113,43 +121,57 @@ def upload_interactive(request, source_type=None, source_id=None):
if request.method == 'POST':
form = WebFormForm(request.POST, request.FILES,
document_type=document_type,
- show_expand=(web_form.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK),
- source=web_form
+ show_expand=(web_form.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK) and not document,
+ source=web_form,
+ instance=document
)
if form.is_valid():
- try:
+ #try:
+ if document:
+ expand = False
+ else:
if web_form.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK:
- expand = form.cleaned_data['expand']
+ expand = form.cleaned_data.get('expand')
else:
if web_form.uncompress == SOURCE_UNCOMPRESS_CHOICE_Y:
expand = True
else:
expand = False
-
- new_filename = get_form_filename(form)
- web_form.upload_file(request.FILES['file'],
- new_filename, document_type=document_type,
- expand=expand,
- metadata_dict_list=decode_metadata_from_url(request.GET),
- user=request.user
- )
+
+ new_filename = get_form_filename(form)
+ web_form.upload_file(request.FILES['file'],
+ new_filename, document_type=document_type,
+ expand=expand,
+ metadata_dict_list=decode_metadata_from_url(request.GET),
+ user=request.user,
+ document=document,
+ new_version_data=form.cleaned_data.get('new_version_data')
+ )
+ #except Exception, e:
+ # messages.error(request, _(u'Unhandled exception: %s') % e)
+ if document:
+ messages.success(request, _(u'Document version uploaded successfully.'))
+ return HttpResponseRedirect(reverse('document_view_simple', args=[document.pk]))
+ else:
messages.success(request, _(u'Document uploaded successfully.'))
- except Exception, e:
- messages.error(request, e)
-
- return HttpResponseRedirect(request.get_full_path())
+ return HttpResponseRedirect(request.get_full_path())
else:
form = WebFormForm(
- show_expand=(web_form.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK),
+ show_expand=(web_form.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK) and not document,
document_type=document_type,
- source=web_form
+ source=web_form,
+ instance=document
)
-
+ if document:
+ title = _(u'upload a new version from source: %s') % web_form.title
+ else:
+ title = _(u'upload a local document from source: %s') % web_form.title
+
subtemplates_list.append({
'name': 'generic_form_subtemplate.html',
'context': {
'form': form,
- 'title': _(u'upload a local document from source: %s') % web_form.title,
+ 'title': title,
},
})
elif source_type == SOURCE_CHOICE_STAGING:
@@ -159,41 +181,54 @@ def upload_interactive(request, source_type=None, source_id=None):
if request.method == 'POST':
form = StagingDocumentForm(request.POST, request.FILES,
cls=StagingFile, document_type=document_type,
- show_expand=(staging_folder.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK),
- source=staging_folder
+ show_expand=(staging_folder.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK) and not document,
+ source=staging_folder,
+ instance=document
)
if form.is_valid():
- try:
- staging_file = StagingFile.get(form.cleaned_data['staging_file_id'])
+ #try:
+ staging_file = StagingFile.get(form.cleaned_data['staging_file_id'])
+ if document:
+ expand = False
+ else:
if staging_folder.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK:
- expand = form.cleaned_data['expand']
+ expand = form.cleaned_dataget('expand')
else:
if staging_folder.uncompress == SOURCE_UNCOMPRESS_CHOICE_Y:
expand = True
else:
expand = False
- new_filename = get_form_filename(form)
- staging_folder.upload_file(staging_file.upload(),
- new_filename, document_type=document_type,
- expand=expand,
- metadata_dict_list=decode_metadata_from_url(request.GET),
- user=request.user
- )
+
+ new_filename = get_form_filename(form)
+ staging_folder.upload_file(staging_file.upload(),
+ new_filename, document_type=document_type,
+ expand=expand,
+ metadata_dict_list=decode_metadata_from_url(request.GET),
+ user=request.user,
+ document=document,
+ new_version_data=form.cleaned_data.get('new_version_data')
+ )
+ if document:
+ messages.success(request, _(u'Document version from staging file: %s, uploaded successfully.') % staging_file.filename)
+ else:
messages.success(request, _(u'Staging file: %s, uploaded successfully.') % staging_file.filename)
- if staging_folder.delete_after_upload:
- transformations, errors = staging_folder.get_transformation_list()
- staging_file.delete(preview_size=staging_folder.get_preview_size(), transformations=transformations)
- messages.success(request, _(u'Staging file: %s, deleted successfully.') % staging_file.filename)
- except Exception, e:
- messages.error(request, e)
-
- return HttpResponseRedirect(request.get_full_path())
+ if staging_folder.delete_after_upload:
+ transformations, errors = staging_folder.get_transformation_list()
+ staging_file.delete(preview_size=staging_folder.get_preview_size(), transformations=transformations)
+ messages.success(request, _(u'Staging file: %s, deleted successfully.') % staging_file.filename)
+ #except Exception, e:
+ # messages.error(request, _(u'Unhandled exception: %s') % e)
+ if document:
+ return HttpResponseRedirect(reverse('document_view_simple', args=[document.pk]))
+ else:
+ return HttpResponseRedirect(request.get_full_path())
else:
form = StagingDocumentForm(cls=StagingFile,
document_type=document_type,
- show_expand=(staging_folder.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK),
- source=staging_folder
+ show_expand=(staging_folder.uncompress == SOURCE_UNCOMPRESS_CHOICE_ASK) and not document,
+ source=staging_folder,
+ instance=document
)
try:
staging_filelist = StagingFile.get_all()
@@ -201,12 +236,17 @@ def upload_interactive(request, source_type=None, source_id=None):
messages.error(request, e)
staging_filelist = []
finally:
+ if document:
+ title = _(u'upload a new version from staging source: %s') % staging_folder.title
+ else:
+ title = _(u'upload a document from staging source: %s') % staging_folder.title
+
subtemplates_list = [
{
'name': 'generic_form_subtemplate.html',
'context': {
'form': form,
- 'title': _(u'upload a document from staging source: %s') % staging_folder.title,
+ 'title': title,
}
},
{
@@ -219,20 +259,40 @@ def upload_interactive(request, source_type=None, source_id=None):
},
]
+ if document:
+ context['object'] = document
+
context.update({
'document_type_id': document_type_id,
'subtemplates_list': subtemplates_list,
- 'sidebar_subtemplates_list': [
- {
- 'name': 'generic_subtemplate.html',
- 'context': {
- 'title': _(u'Current metadata'),
- 'paragraphs': metadata_repr_as_list(decode_metadata_from_url(request.GET)),
- 'side_bar': True,
- }
- }],
- 'temporary_navigation_links': {'form_header': {'upload_interactive': {'links': results['tab_links']}}},
+ 'temporary_navigation_links': {
+ 'form_header': {
+ 'upload_interactive_version': {
+ 'links': results['tab_links']
+ },
+ 'upload_interactive': {
+ 'links': results['tab_links']
+ }
+ }
+ },
})
+
+ if not document:
+ context.update(
+ {
+ 'sidebar_subtemplates_list': [
+ {
+ 'name': 'generic_subtemplate.html',
+ 'context': {
+ 'title': _(u'Current metadata'),
+ 'paragraphs': metadata_repr_as_list(decode_metadata_from_url(request.GET)),
+ 'side_bar': True,
+ }
+ }
+ ],
+ }
+ )
+
return render_to_response('generic_form.html', context,
context_instance=RequestContext(request))
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 6f5cd78643..17106351dd 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -1,3 +1,7 @@
+2011-12-2
+---------
+* Added migrations and model updated to support document versions
+
2011-12-1
---------
* OCR queue processing improvements