fmartingr
/
shelfzilla
Archived
1
0
Fork 0
This repository has been archived on 2021-06-29. You can view files and clone it, but cannot push or open issues or pull requests.
shelfzilla/shelfzilla/apps/manga/models.py

371 lines
11 KiB
Python

from uuid import uuid4
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.db.models.signals import post_save, post_delete
from django.utils.text import slugify
from django.core.urlresolvers import reverse
from filer.fields.image import FilerImageField
from filer.models.foldermodels import Folder
from shelfzilla.models import Model
class Publisher(Model):
name = models.CharField(_('Name'), max_length=128)
slug = models.SlugField(_('Slug'), blank=True, null=True)
url = models.URLField(_('URL'), blank=True, null=True)
# Cache
_series = None
_volumes = None
def __unicode__(self):
return u'{}'.format(self.name)
def get_series_volumes(self, series):
try:
series = self.series.get(pk=series.pk)
return series.volumes.filter(publisher=self)
except Series.DoesNotExist:
return []
def get_absolute_url(self):
args = [self.pk]
if self.slug:
args.append(self.slug)
return reverse('publishers.detail', args=args)
@property
def series(self):
result = []
if not self._series:
queryset = self.volumes.order_by('series__id')\
.distinct('series').values_list('series')
result = Series.objects.filter(pk__in=queryset)
self._series = result
return self._series
class Meta:
ordering = ['name']
verbose_name = _('Publisher')
verbose_name_plural = _('Publishers')
class Series(Model):
SERIES_STATUS = (
('open', _('Open')),
('finished', _('Finished')),
('cancelled', _('Cancelled')),
('on-hold', _('On-hold'))
)
name = models.CharField(_('Name'), max_length=256)
slug = models.SlugField(_('Slug'), blank=True, null=True, max_length=256)
cover = FilerImageField(blank=True, null=True)
summary = models.TextField(_('Summary'), blank=True, null=True)
finished = models.BooleanField(_('Finished'), default=False)
status = models.CharField(_('Status'), choices=SERIES_STATUS,
default='open', max_length=16)
original_publisher = models.ForeignKey(
Publisher, related_name='original_series', null=True, blank=True)
art = models.ManyToManyField(
'Person', related_name='artist_of', null=True, blank=True)
story = models.ManyToManyField(
'Person', related_name='scriptwriter_of', null=True, blank=True)
folder = models.ForeignKey(Folder, null=True, blank=True)
# Cache
_languages = None
def __unicode__(self):
return u'{}'.format(self.name)
def have_review_pending(self):
if self.for_review:
return True
for vol in self.volumes.all():
if vol.for_review:
return True
return False
def get_absolute_url(self):
args = [self.pk]
if self.slug:
args.append(self.slug)
return reverse('series.detail', args=args)
def get_status_display_class(self):
pairs = {
'open': 'success', 'finished': 'success', 'cancelled': 'danger',
'on-hold': 'warning'
}
return pairs[self.status]
@property
def volumes_by_publisher(self):
return self.volumes.order_by('publisher__name', 'language', 'number')
@property
def last_volume_cover(self):
return self.volumes.filter(cover__isnull=False).last().cover
def languages(self):
if not self._languages:
result = []
queryset = self.volumes.order_by('language__id')\
.distinct('language').values_list('language')
result = Language.objects.filter(pk__in=queryset)
self._languages = result
return self._languages
class Meta:
ordering = ['name']
verbose_name = _('Series')
verbose_name_plural = _('Series')
class SeriesSummary(Model):
series = models.ForeignKey('Series', related_name='summaries')
language = models.ForeignKey('Language')
summary = models.TextField(_('Summary'), null=True, blank=True)
class Meta:
unique_together = ('series', 'language', )
class SeriesPublisher(Model):
series = models.ForeignKey('Series', related_name='publishers')
publisher = models.ForeignKey('Publisher', related_name='series_published')
status = models.CharField(_('Status'), choices=Series.SERIES_STATUS,
default='open', max_length=16)
actual_publisher = models.BooleanField(_('Current publisher'),
default=True)
def get_status_display_class(self):
pairs = {
'open': 'success', 'finished': 'success', 'cancelled': 'danger',
'on-hold': 'warning'
}
return pairs[self.status]
@property
def volumes(self):
return self.series.volumes.filter(publisher=self.publisher)
class Volume(Model):
collection = models.ForeignKey('VolumeCollection', null=True,
related_name='volumes')
number = models.IntegerField(_('Number'), null=True, blank=True)
name = models.CharField(_('Name'), max_length=64, null=True, blank=True)
series = models.ForeignKey(Series, related_name="volumes")
publisher = models.ForeignKey(Publisher, related_name="volumes")
cover = FilerImageField(null=True, blank=True)
isbn_10 = models.CharField(
_('ISBN-10'), max_length=10, blank=True, null=True)
isbn_13 = models.CharField(
_('ISBN-13'), max_length=13, blank=True, null=True)
language = models.ForeignKey('Language', null=True)
retail_price = models.DecimalField(
_('Retail price'), max_digits=5, decimal_places=2,
null=True, blank=True)
pages = models.IntegerField(_('Pages'), null=True, blank=True)
release_date = models.DateField(_('Release date'), null=True)
def __unicode__(self):
if self.name:
return u'{} {}'.format(self.series.name, self.name)
elif self.number:
return u'{} #{}'.format(self.series.name, self.number)
else:
return u'{}'.format(self.series.name)
class Meta:
ordering = ['series__name', 'language', 'number']
verbose_name = _('Volume')
verbose_name_plural = _('Volumes')
class VolumeCollection(Model):
name = models.CharField(_('Name'), max_length=32)
series = models.ForeignKey('Series', related_name='collections')
default = models.BooleanField(_('Default'), default=True)
def __unicode__(self):
return u'{} - {}'.format(self.series, self.name)
class Meta:
ordering = ['name', ]
verbose_name = _('Collection')
verbose_name_plural = _('Collections')
class Person(Model):
name = models.CharField(_('Name'), max_length=256)
slug = models.SlugField(_('Slug'), blank=True, null=True)
def __unicode__(self):
return u'{}'.format(self.name)
class Meta:
ordering = ['name']
verbose_name = _('Person')
verbose_name_plural = _('Persons')
class Language(models.Model):
name = models.CharField(_('Name'), max_length=32)
code = models.CharField(_('Code'), max_length=5)
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
verbose_name = _('Language')
verbose_name_plural = _('Languages')
#
# RELATIONS
#
class UserHaveVolume(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='have_volumes')
volume = models.ForeignKey(Volume, related_name='owned_by')
date = models.DateTimeField(_('Date'), auto_now_add=True)
def __unicode__(self):
return "{} {} {}".format(
self.user.username,
_('have'),
self.volume
)
class Meta:
ordering = ('volume__series__name', 'volume__number', )
class UserWishlistVolume(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='wishlisted_volumes')
volume = models.ForeignKey(Volume, related_name='wishlisted_by')
date = models.DateTimeField(_('Date'), auto_now_add=True)
def __unicode__(self):
return "{} {} {}".format(
self.user.username,
_('wants'),
self.volume
)
class Meta:
ordering = ('volume__series__name', 'volume__number', )
class UserReadVolume(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='read_volumes')
volume = models.ForeignKey(Volume, related_name='read_by')
date = models.DateTimeField(_('Date'), auto_now_add=True)
def __unicode__(self):
return "{} {} {}".format(
self.user.username,
_('have read'),
self.volume
)
class Meta:
ordering = ('volume__series__name', 'volume__number', )
#
# SIGNALS
#
def series_check_filer(sender, instance, created, **kwargs):
name = instance.name
# Check folder
# Fix for loaddata import
if instance.folder_id:
try:
Folder.objects.get(pk=instance.folder_id)
except Folder.DoesNotExist:
instance.folder_id = None
instance.folder = None
if not instance.folder:
folder, is_new = Folder.objects.get_or_create(
name=name,
parent_id=settings.COVER_FOLDER_PK,
owner_id=settings.COVER_FOLDER_OWNER_PK,
)
instance.folder = folder
instance.save()
else:
# Check for name change
if instance.folder.name != name:
instance.folder.name = name
instance.folder.save()
# Check file name
if instance.cover:
if instance.cover.name != 'Cover':
instance.cover.name = 'Cover'
instance.cover.save()
if instance.cover.folder != instance.folder:
instance.cover.folder = instance.folder
instance.cover.save()
def volume_check_filer(sender, instance, created, **kwargs):
if instance.cover:
# Check cover to be in series folder
if instance.cover.folder != instance.series.folder:
instance.cover.folder = instance.series.folder
instance.cover.save()
# Check filename
cover_name = uuid4()
if instance.name:
cover_name = slugify(instance.name)
elif instance.number:
cover_name = '{:03}'.format(instance.number)
if instance.cover.name != cover_name:
instance.cover.name = cover_name
instance.cover.save()
def series_delete_folder(sender, instance, using, **kwargs):
if instance.folder:
instance.folder.delete()
def volume_delete_cover(sender, instance, **kwargs):
try:
if instance.cover:
instance.cover.delete()
except:
pass
post_save.connect(series_check_filer, sender=Series)
post_save.connect(volume_check_filer, sender=Volume)
post_delete.connect(series_delete_folder, sender=Series)
post_delete.connect(volume_delete_cover, sender=Volume)