Str/bytes fix for publishing audiobooks.
[wolnelektury.git] / src / social / models.py
1 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
3 #
4 from django.db import models
5 from django.conf import settings
6 from django.core.exceptions import ValidationError
7 from django.core.urlresolvers import reverse
8 from django.utils.translation import ugettext_lazy as _
9 from ssify import flush_ssi_includes
10 from catalogue.models import Book
11
12
13 class BannerGroup(models.Model):
14     name = models.CharField(_('name'), max_length=255, unique=True)
15     created_at = models.DateTimeField(_('created at'), auto_now_add=True)
16
17     class Meta:
18         ordering = ('name',)
19         verbose_name = _('banner group')
20         verbose_name_plural = _('banner groups')
21
22     def __str__(self):
23         return self.name
24
25     def get_absolute_url(self):
26         """This is used for testing."""
27         return "%s?banner_group=%d" % (reverse('main_page'), self.id)
28
29
30 class Cite(models.Model):
31     book = models.ForeignKey(Book, verbose_name=_('book'), null=True, blank=True)
32     text = models.TextField(_('text'), blank=True)
33     small = models.BooleanField(_('small'), default=False, help_text=_('Make this cite display smaller.'))
34     vip = models.CharField(_('VIP'), max_length=128, null=True, blank=True)
35     link = models.URLField(_('link'))
36     video = models.URLField(_('video'), blank=True)
37     picture = models.ImageField(_('picture'), blank=True)
38
39     sticky = models.BooleanField(_('sticky'), default=False, db_index=True,
40                                  help_text=_('Sticky cites will take precedense.'))
41     banner = models.BooleanField(_('banner'), default=False, help_text=_('Adjust size to image, ignore the text'))
42
43     image = models.ImageField(
44         _('image'), upload_to='social/cite', null=True, blank=True,
45         help_text=_('Best image is exactly 975px wide and weights under 100kB.'))
46     image_shift = models.IntegerField(
47         _('shift'), null=True, blank=True,
48         help_text=_(u'Vertical shift, in percents. 0 means top, 100 is bottom. Default is 50%.'))
49     image_title = models.CharField(_('title'), max_length=255, null=True, blank=True)
50     image_author = models.CharField(_('author'), max_length=255, blank=True, null=True)
51     image_link = models.URLField(_('link'), blank=True, null=True)
52     image_license = models.CharField(_('license name'), max_length=255, blank=True, null=True)
53     image_license_link = models.URLField(_('license link'), blank=True, null=True)
54
55     created_at = models.DateTimeField(_('created at'), auto_now_add=True)
56     group = models.ForeignKey(BannerGroup, verbose_name=_('group'), null=True, blank=True, on_delete=models.SET_NULL)
57
58     class Meta:
59         ordering = ('vip', 'text')
60         verbose_name = _('banner')
61         verbose_name_plural = _('banners')
62
63     def __str__(self):
64         return u"%s: %s…" % (self.vip, self.text[:60])
65
66     def get_absolute_url(self):
67         """This is used for testing."""
68         return "%s?choose_cite=%d" % (reverse('main_page'), self.id)
69
70     def save(self, *args, **kwargs):
71         ret = super(Cite, self).save(*args, **kwargs)
72         self.flush_includes()
73         return ret
74
75     def flush_includes(self):
76         flush_ssi_includes([
77             template % (self.pk, lang)
78             for template in [
79                 '/ludzie/cite/%s.%s.html',
80                 '/ludzie/cite_main/%s.%s.html',
81             ]
82             for lang in [lc for (lc, _ln) in settings.LANGUAGES]] +
83             ['/ludzie/cite_info/%s.html' % self.pk])
84
85
86 class Carousel(models.Model):
87     slug = models.SlugField(_('slug'), unique=True)
88
89     class Meta:
90         ordering = ('slug',)
91         verbose_name = _('carousel')
92         verbose_name_plural = _('carousels')
93
94     def __str__(self):
95         return self.slug
96
97 class CarouselItem(models.Model):
98     order = models.PositiveSmallIntegerField(_('order'), unique=True)
99     carousel = models.ForeignKey(Carousel, models.CASCADE, verbose_name=_('carousel'))
100     banner = models.ForeignKey(Cite, models.CASCADE, null=True, blank=True, verbose_name=_('banner'))
101     banner_group = models.ForeignKey(BannerGroup, models.CASCADE, null=True, blank=True, verbose_name=_('banner group'))
102
103     class Meta:
104         ordering = ('order',)
105         unique_together = [('carousel', 'order')]
106         verbose_name = _('carousel item')
107         verbose_name_plural = _('carousel items')
108
109     def __str__(self):
110         return str(self.banner or self.banner_group)
111
112     def clean(self):
113         if not self.banner and not self.banner_group:
114             raise ValidationError(_('Either banner or banner group is required.'))
115         elif self.banner and self.banner_group:
116             raise ValidationError(_('Either banner or banner group is required.'))