From db00cdfa47efb038db8c33393a25df1d240fd76b Mon Sep 17 00:00:00 2001 From: Jan Szejko Date: Thu, 8 Mar 2018 15:29:55 +0100 Subject: [PATCH] weasyprint support - in progress --- .../0018_auto__add_field_lesson_weasy_pdf.py | 102 ++++++++++++++++++ catalogue/models.py | 10 ++ catalogue/publish.py | 49 +++++++++ lib/librarian | 2 +- 4 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 catalogue/migrations/0018_auto__add_field_lesson_weasy_pdf.py diff --git a/catalogue/migrations/0018_auto__add_field_lesson_weasy_pdf.py b/catalogue/migrations/0018_auto__add_field_lesson_weasy_pdf.py new file mode 100644 index 0000000..440b908 --- /dev/null +++ b/catalogue/migrations/0018_auto__add_field_lesson_weasy_pdf.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as 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 'Lesson.weasy_pdf' + db.add_column(u'catalogue_lesson', 'weasy_pdf', + self.gf('django.db.models.fields.files.FileField')(max_length=255, null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Lesson.weasy_pdf' + db.delete_column(u'catalogue_lesson', 'weasy_pdf') + + + models = { + u'catalogue.attachment': { + 'Meta': {'ordering': "['slug', 'ext']", 'unique_together': "(['lesson', 'slug', 'ext'],)", 'object_name': 'Attachment'}, + 'ext': ('django.db.models.fields.CharField', [], {'max_length': '15'}), + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'lesson': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Lesson']"}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + u'catalogue.lesson': { + 'Meta': {'ordering': "['section', 'level', 'order']", 'object_name': 'Lesson'}, + 'curriculum_courses': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['curriculum.CurriculumCourse']", 'symmetrical': 'False', 'blank': 'True'}), + 'dc': ('jsonfield.fields.JSONField', [], {'default': "'{}'"}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'html_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['curriculum.Level']"}), + 'order': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'package': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'pdf': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'section': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Section']", 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}), + 'student_package': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'student_pdf': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}), + 'weasy_pdf': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'xml_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) + }, + u'catalogue.lessonstub': { + 'Meta': {'ordering': "['section', 'level', 'order']", 'object_name': 'LessonStub'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['curriculum.Level']"}), + 'order': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'section': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Section']", 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}) + }, + u'catalogue.part': { + 'Meta': {'object_name': 'Part'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'lesson': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Lesson']"}), + 'pdf': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'student_pdf': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}) + }, + u'catalogue.section': { + 'Meta': {'ordering': "['order']", 'object_name': 'Section'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'pic': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'pic_attribution': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'pic_src': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}), + 'summary': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'xml_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) + }, + u'curriculum.curriculumcourse': { + 'Meta': {'ordering': "['slug']", 'object_name': 'CurriculumCourse'}, + 'accusative': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + u'curriculum.level': { + 'Meta': {'ordering': "['order']", 'object_name': 'Level'}, + 'group_en': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}), + 'group_pl': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'meta_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'name_en': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}), + 'name_pl': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'package': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'student_package': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['catalogue'] \ No newline at end of file diff --git a/catalogue/models.py b/catalogue/models.py index 8ecf7ac..c5ed66c 100644 --- a/catalogue/models.py +++ b/catalogue/models.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 +from django.conf import settings from django.core.files import File from django.core.urlresolvers import reverse from django.db import models @@ -109,6 +110,9 @@ class Lesson(models.Model): student_pdf = models.FileField( upload_to="catalogue/lesson/student_pdf", null=True, blank=True, max_length=255, storage=bofh_storage) + weasy_pdf = models.FileField( + upload_to="catalogue/lesson/weasy", + null=True, blank=True, max_length=255, storage=bofh_storage) class Meta: ordering = ['section', 'level', 'order'] @@ -235,6 +239,12 @@ class Lesson(models.Model): pdf = PdfFormat(wldoc, teacher=True).build() self.pdf.save("%s.pdf" % self.slug, File(open(pdf.get_filename()))) + def build_weasy_pdf(self): + from .publish import WeasyFormat + wldoc = self.wldocument() + pdf = WeasyFormat(wldoc, media_root=settings.MEDIA_ROOT).build() + self.weasy_pdf.save("%s.pdf" % self.slug, File(open(pdf.get_filename()))) + def add_to_zip(self, zipf, student=False, prefix=''): pdf = self.student_pdf if student else self.pdf if pdf: diff --git a/catalogue/publish.py b/catalogue/publish.py index bc2e37a..1fc4ade 100755 --- a/catalogue/publish.py +++ b/catalogue/publish.py @@ -4,6 +4,7 @@ from django.core.urlresolvers import reverse from librarian import DocProvider, IOFile from librarian.pyhtml import EduModuleFormat from librarian.pypdf import EduModulePDFFormat +from librarian.weasy import EduModuleWeasyFormat from .models import Lesson, Attachment from fnpdjango.utils.text.slughifi import slughifi @@ -119,6 +120,54 @@ class PdfFormat(EduModulePDFFormat): return src_img +class WeasyFormat(EduModuleWeasyFormat): + IMAGE_FORMATS = ('PNG', 'JPEG', 'GIF') + DEFAULT_IMAGE_WIDTH = 1600 + + def find_attachment(self, slug, fmt): + lesson_slug = self.wldoc.book_info.url.slug + try: + # If already saved, use it. + att = Attachment.objects.get(lesson__slug=lesson_slug, + slug=slug, ext=fmt) + except Attachment.DoesNotExist, e: + # If attached to source IOFile, save now. + att_name = "%s.%s" % (slug, fmt) + try: + att_file = self.wldoc.source.attachments[att_name] + except KeyError: + print u"ATTACHMENT MISSING:", att_name + raise self.MaterialNotFound() + else: + lesson = Lesson.objects.get(slug=lesson_slug) + att = lesson.attachment_set.create(slug=slug, ext=fmt) + att.file.save(att_name, File(att_file.get_file())) + return att + else: + return att + + def url_for_material(self, slug, fmt): + return self.find_attachment(slug, fmt).file.url + + def image(self, slug, fmt, width=None): + try: + src_img = self.find_attachment(slug, fmt).file + except self.MaterialNotFound: + return None + img = get_image(src_img.path, width, self.DEFAULT_IMAGE_WIDTH, self.IMAGE_FORMATS) + return img or src_img + + def url_for_image(self, slug, fmt, image=None, **kwargs): + img = image or self.image(slug, fmt, **kwargs) + if img: + return img.url + else: + return '' + + def text_to_anchor(self, text): + return slughifi(text) + + class OrmDocProvider(DocProvider): def by_slug(self, slug): """Should return a file-like object with a WL document XML.""" diff --git a/lib/librarian b/lib/librarian index 935dcf2..e4ffa9f 160000 --- a/lib/librarian +++ b/lib/librarian @@ -1 +1 @@ -Subproject commit 935dcf2282ee3c08f776e221bc71f9a0744cb85e +Subproject commit e4ffa9f5172b88a5a49ed832634105dd65b9727f -- 2.20.1