Generally working version.
[wolnelektury.git] / src / catalogue / management / commands / pack.py
1 # -*- coding: utf-8 -*-
2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
4 #
5 from optparse import make_option
6
7 from django.core.management.base import BaseCommand
8 from django.core.management.color import color_style
9 import zipfile
10
11 from catalogue.models import Book, Tag
12
13
14 class Command(BaseCommand):
15     option_list = BaseCommand.option_list + (
16         make_option('-t', '--tags', dest='tags', metavar='SLUG,...',
17             help='Use only books tagged with this tags'),
18         make_option('-i', '--include', dest='include', metavar='SLUG,...',
19             help='Include specific books by slug'),
20         make_option('-e', '--exclude', dest='exclude', metavar='SLUG,...',
21             help='Exclude specific books by slug')
22     )
23     help = 'Prepare ZIP package with files of given type.'
24     args = '[%s] output_path.zip' % '|'.join(Book.formats)
25
26     def handle(self, ftype, path, **options):
27         self.style = color_style()
28         verbose = int(options.get('verbosity'))
29         tags = options.get('tags')
30         include = options.get('include')
31         exclude = options.get('exclude')
32
33         if ftype in Book.formats:
34             field = "%s_file" % ftype
35         else:
36             print self.style.ERROR('Unknown file type.')
37             return
38
39         books = []
40
41         if include:
42             books += list(Book.objects.filter(slug__in=include.split(',')).only('slug', field))
43
44         if tags:
45             books += list(Book.tagged.with_all(Tag.objects.filter(slug__in=tags.split(','))).only('slug', field))
46         elif not include:
47             books = list(Book.objects.all().only('slug', field))
48
49         if exclude:
50             books = [book for book in books if book.slug not in exclude.split(',')]
51
52         archive = zipfile.ZipFile(path, 'w', zipfile.ZIP_DEFLATED)
53
54         processed = skipped = 0
55         for book in books:
56             if verbose >= 2:
57                 print 'Parsing', book.slug
58             content = getattr(book, field)
59             if not content:
60                 if verbose >= 1:
61                     print self.style.NOTICE('%s has no %s file' % (book.slug, ftype))
62                 skipped += 1
63                 continue
64             archive.write(content.path, str('%s.%s' % (book.slug, ftype)))
65             processed += 1
66         archive.close()
67
68         if not processed:
69             if skipped:
70                 print self.style.ERROR("No books with %s files found" % ftype)
71             else:
72                 print self.style.ERROR("No books found")
73             return
74
75         if verbose >= 1:
76             print "%d processed, %d skipped" % (processed, skipped)
77             print "Results written to %s" % path