new exercises
[edumed.git] / catalogue / publish.py
1 # -*- coding: utf-8
2 from django.core.files.base import ContentFile
3 from django.core.files import File
4 from django.core.urlresolvers import reverse
5 from librarian import DocProvider, IOFile
6 from librarian.pyhtml import EduModuleFormat
7 from librarian.pypdf import EduModulePDFFormat
8 from .models import Lesson, Attachment
9 from fnpdjango.utils.text.slughifi import slughifi
10
11
12 # TODO: Using sorl.thumbnail for now,
13 # but this should be done in Librarian,
14 # directly using convert or PIL as a fallback.
15 def get_image(src_img_path, width=None,
16         default_width=1600, formats=('PNG', 'JPEG', 'GIF')):
17     """ Returns an object with `url` and `storage` attributes,
18         or None if using the original image is OK.
19     """
20     
21     from PIL import Image
22     from sorl.thumbnail import get_thumbnail
23     
24     # Does it need converting?
25     # Yes, if width is given explicitly.
26     convert = width is not None
27     if not convert:
28         # Looks like it doesn't need converting.
29         # But let's try opening it and checking its type.
30         try:
31             simg = Image.open(src_img_path)
32         except IOError:
33             # It doesn't look like image,
34             # but maybe it's convertable to one.
35             convert = True
36         else:
37             if simg.format not in formats:
38                 # It's an image, but it's in some weird format.
39                 convert = True
40                 width = simg.size[0]
41
42     if convert:
43         if width is None:
44             width = default_width
45         return get_thumbnail(src_img_path, '%sx%s' % (width, 10*width))
46     else:
47         return None
48
49
50 class HtmlFormat(EduModuleFormat):
51     IMAGE_FORMATS = ('PNG', 'JPEG', 'GIF')
52     DEFAULT_IMAGE_WIDTH = 1600
53
54     def find_attachment(self, slug, fmt):
55         lesson_slug = self.wldoc.book_info.url.slug
56         try:
57             # If already saved, use it.
58             att = Attachment.objects.get(lesson__slug=lesson_slug,
59                                          slug=slug, ext=fmt)
60         except Attachment.DoesNotExist, e:
61             # If attached to source IOFile, save now.
62             att_name = "%s.%s" % (slug, fmt)
63             try:
64                 att_file = self.wldoc.source.attachments[att_name]
65             except KeyError:
66                 print u"ATTACHMENT MISSING:", att_name
67                 raise self.MaterialNotFound()
68             else:
69                 lesson = Lesson.objects.get(slug=lesson_slug)
70                 att = lesson.attachment_set.create(slug=slug, ext=fmt)
71                 att.file.save(att_name, File(att_file.get_file()))
72                 return att
73         else:
74             return att
75
76     def url_for_material(self, slug, fmt):
77         return self.find_attachment(slug, fmt).file.url
78
79     def url_for_image(self, slug, fmt, width=None):
80         try:
81             src_img = self.find_attachment(slug, fmt).file
82         except self.MaterialNotFound:
83             return ''
84         img = get_image(src_img.path, width,
85             self.DEFAULT_IMAGE_WIDTH, self.IMAGE_FORMATS)
86         return (img or src_img).url
87
88     def text_to_anchor(self, text):
89         return slughifi(text)
90
91     def get_forma_url(self, forma):
92         return '%s#%s' % (
93             reverse('catalogue_lesson', args=['metody']),
94             self.text_to_anchor(forma)
95         )
96
97     def get_help_url(self, naglowek):
98         return '%s%s#%s' % (
99             '//edukacjamedialna.edu.pl',
100             reverse('info', args=['jak-korzystac/']),
101             self.naglowek_to_anchor(naglowek)
102         )
103
104
105 class PdfFormat(EduModulePDFFormat):
106     IMAGE_FORMATS = ('PNG', 'JPEG', 'GIF')
107     DEFAULT_IMAGE_WIDTH = 1600
108
109     def get_image(self, name):
110         src_img = super(PdfFormat, self).get_image(name)
111         img = get_image(src_img.get_filename(),
112                 default_width=self.DEFAULT_IMAGE_WIDTH,
113                 formats=self.IMAGE_FORMATS
114             )
115         if img:
116             return IOFile.from_filename(img.storage.path(img))
117         else:
118             return src_img
119
120
121 class OrmDocProvider(DocProvider):
122     def by_slug(self, slug):
123         """Should return a file-like object with a WL document XML."""
124         return IOFile.from_filename(Lesson.objects.get(slug=slug).xml_file.path)