Ebooks are now named after the book's slug and overwrite old versions.
authorRadek Czajka <radekczajka@nowoczesnapolska.org.pl>
Fri, 14 Feb 2014 11:57:55 +0000 (12:57 +0100)
committerRadek Czajka <radekczajka@nowoczesnapolska.org.pl>
Fri, 14 Feb 2014 13:20:53 +0000 (14:20 +0100)
Also:
avoid hitting DB just by importing modules,
update Feedparser and django-pipeline.

12 files changed:
apps/catalogue/management/commands/checkcovers.py
apps/catalogue/migrations/0017_auto__chg_field_book_pdf_file__chg_field_book_html_file__chg_field_boo.py [new file with mode: 0644]
apps/catalogue/models/book.py
apps/catalogue/models/bookmedia.py
apps/catalogue/templatetags/catalogue_tags.py
apps/catalogue/tests/book_import.py
apps/catalogue/utils.py
apps/oai/views.py
apps/opds/views.py
requirements.txt
wolnelektury/settings/static.py
wolnelektury/utils.py

index 1af39e1..7535dd4 100644 (file)
@@ -6,6 +6,7 @@ from optparse import make_option
 from django.contrib.sites.models import Site
 from django.core.management.base import BaseCommand
 from catalogue import app_settings
+from django.utils.functional import lazy
 
 
 def ancestor_has_cover(book):
@@ -16,7 +17,7 @@ def ancestor_has_cover(book):
     return False
 
 
-current_domain = Site.objects.get_current().domain
+current_domain = lazy(lambda: Site.objects.get_current().domain, str)()
 def full_url(obj):
     return 'http://%s%s' % (
                 current_domain,
diff --git a/apps/catalogue/migrations/0017_auto__chg_field_book_pdf_file__chg_field_book_html_file__chg_field_boo.py b/apps/catalogue/migrations/0017_auto__chg_field_book_pdf_file__chg_field_book_html_file__chg_field_boo.py
new file mode 100644 (file)
index 0000000..df96042
--- /dev/null
@@ -0,0 +1,243 @@
+# -*- coding: 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 'Book.pdf_file'
+        db.alter_column(u'catalogue_book', 'pdf_file', self.gf('catalogue.fields.EbookField')(max_length=255, format_name='pdf'))
+
+        # Changing field 'Book.html_file'
+        db.alter_column(u'catalogue_book', 'html_file', self.gf('catalogue.fields.EbookField')(max_length=255, format_name='html'))
+
+        # Changing field 'Book.fb2_file'
+        db.alter_column(u'catalogue_book', 'fb2_file', self.gf('catalogue.fields.EbookField')(max_length=255, format_name='fb2'))
+
+        # Changing field 'Book.xml_file'
+        db.alter_column(u'catalogue_book', 'xml_file', self.gf('catalogue.fields.EbookField')(max_length=255, format_name='xml'))
+
+        # Changing field 'Book.txt_file'
+        db.alter_column(u'catalogue_book', 'txt_file', self.gf('catalogue.fields.EbookField')(max_length=255, format_name='txt'))
+
+        # Changing field 'Book.mobi_file'
+        db.alter_column(u'catalogue_book', 'mobi_file', self.gf('catalogue.fields.EbookField')(max_length=255, format_name='mobi'))
+
+        # Changing field 'Book.epub_file'
+        db.alter_column(u'catalogue_book', 'epub_file', self.gf('catalogue.fields.EbookField')(max_length=255, format_name='epub'))
+
+        # Changing field 'Book.cover_thumb'
+        db.alter_column(u'catalogue_book', 'cover_thumb', self.gf('catalogue.fields.EbookField')(max_length=255, null=True, format_name='cover_thumb'))
+
+        # Changing field 'Book.cover'
+        db.alter_column(u'catalogue_book', 'cover', self.gf('catalogue.fields.EbookField')(max_length=255, null=True, format_name='cover'))
+
+        # Changing field 'BookMedia.file'
+        db.alter_column(u'catalogue_bookmedia', 'file', self.gf('catalogue.fields.OverwritingFileField')(max_length=600))
+
+        # Changing field 'BookMedia.type'
+        db.alter_column(u'catalogue_bookmedia', 'type', self.gf('django.db.models.fields.CharField')(max_length=20))
+
+    def backwards(self, orm):
+
+        # Changing field 'Book.pdf_file'
+        db.alter_column(u'catalogue_book', 'pdf_file', self.gf('catalogue.fields.EbookField')(max_length=100, format_name='pdf'))
+
+        # Changing field 'Book.html_file'
+        db.alter_column(u'catalogue_book', 'html_file', self.gf('catalogue.fields.EbookField')(max_length=100, format_name='html'))
+
+        # Changing field 'Book.fb2_file'
+        db.alter_column(u'catalogue_book', 'fb2_file', self.gf('catalogue.fields.EbookField')(max_length=100, format_name='fb2'))
+
+        # Changing field 'Book.xml_file'
+        db.alter_column(u'catalogue_book', 'xml_file', self.gf('catalogue.fields.EbookField')(max_length=100, format_name='xml'))
+
+        # Changing field 'Book.txt_file'
+        db.alter_column(u'catalogue_book', 'txt_file', self.gf('catalogue.fields.EbookField')(max_length=100, format_name='txt'))
+
+        # Changing field 'Book.mobi_file'
+        db.alter_column(u'catalogue_book', 'mobi_file', self.gf('catalogue.fields.EbookField')(max_length=100, format_name='mobi'))
+
+        # Changing field 'Book.epub_file'
+        db.alter_column(u'catalogue_book', 'epub_file', self.gf('catalogue.fields.EbookField')(max_length=100, format_name='epub'))
+
+        # Changing field 'Book.cover_thumb'
+        db.alter_column(u'catalogue_book', 'cover_thumb', self.gf('catalogue.fields.EbookField')(max_length=100, null=True, format_name='cover_thumb'))
+
+        # Changing field 'Book.cover'
+        db.alter_column(u'catalogue_book', 'cover', self.gf('catalogue.fields.EbookField')(max_length=100, null=True, format_name='cover'))
+
+        # Changing field 'BookMedia.file'
+        db.alter_column(u'catalogue_bookmedia', 'file', self.gf('catalogue.fields.OverwritingFileField')(max_length=100))
+
+        # Changing field 'BookMedia.type'
+        db.alter_column(u'catalogue_bookmedia', 'type', self.gf('django.db.models.fields.CharField')(max_length='100'))
+
+    models = {
+        u'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        u'auth.permission': {
+            'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
+            u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'catalogue.book': {
+            'Meta': {'ordering': "('sort_key',)", 'object_name': 'Book'},
+            '_related_info': ('jsonfield.fields.JSONField', [], {'null': 'True', 'blank': 'True'}),
+            'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'common_slug': ('django.db.models.fields.SlugField', [], {'max_length': '120'}),
+            'cover': ('catalogue.fields.EbookField', [], {'max_length': '255', 'null': 'True', 'format_name': "'cover'", 'blank': 'True'}),
+            'cover_thumb': ('catalogue.fields.EbookField', [], {'max_length': '255', 'null': 'True', 'format_name': "'cover_thumb'", 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'epub_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '255', 'format_name': "'epub'", 'blank': 'True'}),
+            'extra_info': ('jsonfield.fields.JSONField', [], {'default': '{}'}),
+            'fb2_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '255', 'format_name': "'fb2'", 'blank': 'True'}),
+            'gazeta_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
+            'html_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '255', 'format_name': "'html'", 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'language': ('django.db.models.fields.CharField', [], {'default': "'pol'", 'max_length': '3', 'db_index': 'True'}),
+            'mobi_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '255', 'format_name': "'mobi'", 'blank': 'True'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['catalogue.Book']"}),
+            'parent_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'pdf_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '255', 'format_name': "'pdf'", 'blank': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '120'}),
+            'sort_key': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}),
+            'sort_key_author': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '120', 'db_index': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '120'}),
+            'txt_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '255', 'format_name': "'txt'", 'blank': 'True'}),
+            'wiki_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
+            'xml_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '255', 'format_name': "'xml'", 'blank': 'True'})
+        },
+        'catalogue.bookmedia': {
+            'Meta': {'ordering': "('type', 'name')", 'object_name': 'BookMedia'},
+            'book': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'media'", 'to': "orm['catalogue.Book']"}),
+            'extra_info': ('jsonfield.fields.JSONField', [], {'default': '{}'}),
+            'file': ('catalogue.fields.OverwritingFileField', [], {'max_length': '600'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'source_sha1': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '20', 'db_index': 'True'}),
+            'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'})
+        },
+        'catalogue.collection': {
+            'Meta': {'ordering': "('title',)", 'object_name': 'Collection'},
+            'book_slugs': ('django.db.models.fields.TextField', [], {}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_de': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_en': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_es': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_fr': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_it': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_lt': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_pl': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_ru': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_uk': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'kind': ('django.db.models.fields.CharField', [], {'default': "'book'", 'max_length': '10', 'db_index': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '120', 'primary_key': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}),
+            'title_de': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '120', 'null': 'True', 'blank': 'True'}),
+            'title_en': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '120', 'null': 'True', 'blank': 'True'}),
+            'title_es': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '120', 'null': 'True', 'blank': 'True'}),
+            'title_fr': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '120', 'null': 'True', 'blank': 'True'}),
+            'title_it': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '120', 'null': 'True', 'blank': 'True'}),
+            'title_lt': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '120', 'null': 'True', 'blank': 'True'}),
+            'title_pl': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '120', 'null': 'True', 'blank': 'True'}),
+            'title_ru': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '120', 'null': 'True', 'blank': 'True'}),
+            'title_uk': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '120', 'null': 'True', 'blank': 'True'})
+        },
+        'catalogue.fragment': {
+            'Meta': {'ordering': "('book', 'anchor')", 'object_name': 'Fragment'},
+            'anchor': ('django.db.models.fields.CharField', [], {'max_length': '120'}),
+            'book': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'fragments'", 'to': "orm['catalogue.Book']"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'short_text': ('django.db.models.fields.TextField', [], {}),
+            'text': ('django.db.models.fields.TextField', [], {})
+        },
+        'catalogue.tag': {
+            'Meta': {'ordering': "('sort_key',)", 'unique_together': "(('slug', 'category'),)", 'object_name': 'Tag'},
+            'book_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'category': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+            'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'culturepl_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'description_de': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_en': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_es': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_fr': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_it': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_lt': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_pl': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_ru': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'description_uk': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'gazeta_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+            'name_de': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'name_en': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'name_es': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'name_fr': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'name_it': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'name_lt': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'name_pl': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'name_ru': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'name_uk': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'picture_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '120'}),
+            'sort_key': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'wiki_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
+            'wiki_link_de': ('django.db.models.fields.CharField', [], {'max_length': '240', 'null': 'True', 'blank': 'True'}),
+            'wiki_link_en': ('django.db.models.fields.CharField', [], {'max_length': '240', 'null': 'True', 'blank': 'True'}),
+            'wiki_link_es': ('django.db.models.fields.CharField', [], {'max_length': '240', 'null': 'True', 'blank': 'True'}),
+            'wiki_link_fr': ('django.db.models.fields.CharField', [], {'max_length': '240', 'null': 'True', 'blank': 'True'}),
+            'wiki_link_it': ('django.db.models.fields.CharField', [], {'max_length': '240', 'null': 'True', 'blank': 'True'}),
+            'wiki_link_lt': ('django.db.models.fields.CharField', [], {'max_length': '240', 'null': 'True', 'blank': 'True'}),
+            'wiki_link_pl': ('django.db.models.fields.CharField', [], {'max_length': '240', 'null': 'True', 'blank': 'True'}),
+            'wiki_link_ru': ('django.db.models.fields.CharField', [], {'max_length': '240', 'null': 'True', 'blank': 'True'}),
+            'wiki_link_uk': ('django.db.models.fields.CharField', [], {'max_length': '240', 'null': 'True', 'blank': 'True'})
+        },
+        'catalogue.tagrelation': {
+            'Meta': {'unique_together': "(('tag', 'content_type', 'object_id'),)", 'object_name': 'TagRelation', 'db_table': "u'catalogue_tag_relation'"},
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'items'", 'to': "orm['catalogue.Tag']"})
+        },
+        u'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'}),
+            u'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'})
+        }
+    }
+
+    complete_apps = ['catalogue']
\ No newline at end of file
index bd7d7e4..414d1ef 100644 (file)
@@ -11,14 +11,16 @@ import django.dispatch
 from django.utils.datastructures import SortedDict
 from django.utils.translation import ugettext_lazy as _
 import jsonfield
+from fnpdjango.storage import BofhFileSystemStorage
 from catalogue import constants
 from catalogue.fields import EbookField
 from catalogue.models import Tag, Fragment, BookMedia
-from catalogue.utils import create_zip, split_tags, book_upload_path, related_tag_name
+from catalogue.utils import create_zip, split_tags, related_tag_name
 from catalogue import app_settings
 from catalogue import tasks
 from newtagging import managers
 
+bofh_storage = BofhFileSystemStorage()
 
 permanent_cache = get_cache('permanent')
 
@@ -43,10 +45,14 @@ class Book(models.Model):
     # files generated during publication
 
     cover = EbookField('cover', _('cover'),
-                upload_to=book_upload_path('jpg'), null=True, blank=True)
+            null=True, blank=True,
+            upload_to=lambda i, n: 'book/cover/%s.jpg' % i.slug,
+            storage=bofh_storage, max_length=255)
     # Cleaner version of cover for thumbs
-    cover_thumb = EbookField('cover_thumb', _('cover thumbnail'),
-                upload_to=book_upload_path('th.jpg'), null=True, blank=True)
+    cover_thumb = EbookField('cover_thumb', _('cover thumbnail'), 
+            null=True, blank=True,
+            upload_to=lambda i, n: 'book/cover_thumb/%s.jpg' % i.slug,
+            max_length=255)
     ebook_formats = constants.EBOOK_FORMATS
     formats = ebook_formats + ['html', 'xml']
 
@@ -620,6 +626,13 @@ class Book(models.Model):
 # add the file fields
 for format_ in Book.formats:
     field_name = "%s_file" % format_
+    upload_to = (lambda upload_path:
+            lambda i, n: upload_path % i.slug
+        )('book/%s/%%s.%s' % (format_, format_))
     EbookField(format_, _("%s file" % format_.upper()),
-            upload_to=book_upload_path(format_),
-            blank=True, default='').contribute_to_class(Book, field_name)
+        upload_to=upload_to,
+        storage=bofh_storage,
+        max_length=255,
+        blank=True,
+        default=''
+    ).contribute_to_class(Book, field_name)
index 42781e9..6291329 100644 (file)
@@ -8,8 +8,8 @@ from django.db import models
 from django.utils.translation import ugettext_lazy as _
 from django.utils.datastructures import SortedDict
 import jsonfield
+from fnpdjango.utils.text.slughifi import slughifi
 from catalogue.fields import OverwritingFileField
-from catalogue.utils import book_upload_path
 
 
 class BookMedia(models.Model):
@@ -23,11 +23,13 @@ class BookMedia(models.Model):
     format_choices = [(k, _('%s file') % t.name)
             for k, t in formats.items()]
 
-    type        = models.CharField(_('type'), db_index=True, choices=format_choices, max_length="100")
-    name        = models.CharField(_('name'), max_length=512)
-    file        = OverwritingFileField(_('file'), upload_to=book_upload_path())
+    type = models.CharField(_('type'), db_index=True, choices=format_choices, max_length=20)
+    name = models.CharField(_('name'), max_length=512)
+    file = OverwritingFileField(_('file'), max_length=600,
+        upload_to=lambda i, _n: 'book/%(ext)s/%(name)s.%(ext)s' % {
+                    'ext': i.ext(), 'name': slughifi(i.name)})
     uploaded_at = models.DateTimeField(_('creation date'), auto_now_add=True, editable=False, db_index=True)
-    extra_info  = jsonfield.JSONField(_('extra information'), default={}, editable=False)
+    extra_info = jsonfield.JSONField(_('extra information'), default={}, editable=False)
     book = models.ForeignKey('Book', related_name='media')
     source_sha1 = models.CharField(null=True, blank=True, max_length=40, editable=False)
 
@@ -102,6 +104,9 @@ class BookMedia(models.Model):
         return {'artist_name': artist_name, 'director_name': director_name,
                 'project': project, 'funded_by': funded_by}
 
+    def ext(self):
+        return self.formats[self.type].ext
+
     @staticmethod
     def read_source_sha1(filepath, filetype):
         """
index 95288a4..6ff60a3 100644 (file)
@@ -284,7 +284,7 @@ def latest_blog_posts(feed_url, posts_to_show=5):
         feed = feedparser.parse(str(feed_url))
         posts = []
         for i in range(posts_to_show):
-            pub_date = feed['entries'][i].updated_parsed
+            pub_date = feed['entries'][i].published_parsed
             published = datetime.date(pub_date[0], pub_date[1], pub_date[2])
             posts.append({
                 'title': feed['entries'][i].title,
index 08d5243..4b01a8f 100644 (file)
@@ -435,8 +435,7 @@ class BookImportGenerateTest(WLTestCase):
 
     def test_custom_pdf(self):
         from catalogue.tasks import build_custom_pdf
-        from catalogue.utils import get_dynamic_path
-        out = get_dynamic_path(None, 'test-custom', ext='pdf')
+        out = 'test-custom.pdf'
         absoulute_path = path.join(settings.MEDIA_ROOT, out)
 
         if not path.exists(path.dirname(absoulute_path)):
index 98ee36c..a0e834c 100644 (file)
@@ -49,25 +49,6 @@ def split_tags(tags, initial=None):
     return result
 
 
-def get_dynamic_path(media, filename, ext=None, maxlen=100):
-    from fnpdjango.utils.text.slughifi import slughifi
-
-    # how to put related book's slug here?
-    if not ext:
-        # BookMedia case
-        ext = media.formats[media.type].ext
-    if media is None or not media.name:
-        name = slughifi(filename.split(".")[0])
-    else:
-        name = slughifi(media.name)
-    return 'book/%s/%s.%s' % (ext, name[:maxlen-len('book/%s/.%s' % (ext, ext))-4], ext)
-
-
-# TODO: why is this hard-coded ?
-def book_upload_path(ext=None, maxlen=100):
-    return lambda *args: get_dynamic_path(*args, ext=ext, maxlen=maxlen)
-
-
 class ExistingFile(UploadedFile):
 
     def __init__(self, path, *args, **kwargs):
index 1002671..5bb9025 100644 (file)
@@ -6,6 +6,7 @@ from oai.handlers import Catalogue, NS_DCTERMS, nsdcterms
 from oaipmh.server import ServerBase, NS_OAIDC, NS_DC, NS_XSI, nsoaidc, nsdc
 from oaipmh.metadata import MetadataRegistry
 from django.http import HttpResponse
+from django.utils.functional import SimpleLazyObject
 from lxml.etree import SubElement
 
 
@@ -57,8 +58,10 @@ metadata_registry.registerWriter('oai_dc', fbc_oai_dc_writer)
 metadata_registry.registerWriter('qdc', qdc_writer)
 
 
-server = ServerBase(Catalogue(metadata_registry), metadata_registry,
-    {'topxsi': NS_XSI})
+server = SimpleLazyObject(lambda: 
+    ServerBase(Catalogue(metadata_registry), metadata_registry,
+        {'topxsi': NS_XSI})
+    )
 
 
 def oaipmh(request):
index 4dd1ca2..d70501c 100644 (file)
@@ -12,6 +12,7 @@ from django.utils.feedgenerator import Atom1Feed
 from django.conf import settings
 from django.http import Http404
 from django.contrib.sites.models import Site
+from django.utils.functional import lazy
 
 from basicauth import logged_in_or_basicauth, factory_decorator
 from catalogue.models import Book, Tag
@@ -64,21 +65,22 @@ _root_feeds = (
 )
 
 
+current_domain = lazy(lambda: Site.objects.get_current().domain, str)()
 def full_url(url):
-    return urljoin("http://%s" % Site.objects.get_current().domain, url)
+    return urljoin("http://%s" % current_domain, url)
 
 
 class OPDSFeed(Atom1Feed):
     link_rel = u"subsection"
     link_type = u"application/atom+xml"
 
-    _book_parent_img = full_url(os.path.join(settings.STATIC_URL, "img/book-parent.png"))
+    _book_parent_img = lazy(lambda: full_url(os.path.join(settings.STATIC_URL, "img/book-parent.png")))()
     try:
         _book_parent_img_size = unicode(os.path.getsize(os.path.join(settings.STATIC_ROOT, "img/book-parent.png")))
     except:
         _book_parent_img_size = ''
 
-    _book_img = full_url(os.path.join(settings.STATIC_URL, "img/book.png"))
+    _book_img = lazy(lambda: full_url(os.path.join(settings.STATIC_URL, "img/book.png")))()
     try:
         _book_img_size = unicode(os.path.getsize(os.path.join(settings.STATIC_ROOT, "img/book.png")))
     except:
index 143f40e..9b92efa 100644 (file)
@@ -3,9 +3,9 @@
 
 # django
 Django>=1.6,<1.7
-fnpdjango>=0.1.8,<0.2
+fnpdjango>=0.1.15,<0.2
 South>=0.7 # migrations for django
-django-pipeline>=1.2.24,<1.3
+django-pipeline>=1.3,<1.4
 django-pagination>=1.0
 django-maintenancemode>=0.10
 django-piston>=0.2.2.1,<0.2.3
@@ -29,7 +29,7 @@ django-piwik
 python-fb
 
 # Feedparser 
-Feedparser>=4.1
+Feedparser>=5.1
 
 # PIL 
 PIL>=1.1.6
index 45bd8d6..2bfcd25 100644 (file)
@@ -140,7 +140,7 @@ PIPELINE_JS = {
 
 }
 
-STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'
+STATICFILES_STORAGE = 'wolnelektury.utils.GzipPipelineCachedStorage'
 PIPELINE_CSS_COMPRESSOR = None
 PIPELINE_JS_COMPRESSOR = None
 
index 0c256e5..e06fb1d 100644 (file)
@@ -5,6 +5,8 @@
 import pytz
 from django.utils import timezone
 from django.conf import settings
+from pipeline.storage import GZIPMixin
+from pipeline.storage import PipelineCachedStorage
 
 tz = pytz.timezone(settings.TIME_ZONE)
 
@@ -15,3 +17,6 @@ def localtime_to_utc(localtime):
 
 def utc_for_js(dt):
     return dt.strftime('%Y/%m/%d %H:%M:%S UTC')
+
+class GzipPipelineCachedStorage(GZIPMixin, PipelineCachedStorage):
+    pass