Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Comic import fails due to issue having a non-integer comic number #53

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions comics/migrations/0005_issue_number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2017-11-07 21:42
from __future__ import unicode_literals

from django.db import migrations, models

from ..utils.comicapi.issuestring import IssueString


def add_issue_number_data(apps, schema_editor):

Issue = apps.get_model('comics', 'Issue')
query = Issue.objects.all()
for issue in query:
new_number = IssueString(issue.number).asString(pad=3)
issue.number = new_number
issue.save()


def remove_issue_number_data(apps, schema_editor):

Issue = apps.get_model('comics', 'Issue')
Issue.objects.update(number='')


class Migration(migrations.Migration):

dependencies = [
('comics', '0004_issue_page_count'),
]

operations = [
migrations.AlterField(
model_name='issue',
name='number',
field=models.CharField(max_length=25, verbose_name='Issue number'),
),
migrations.RunPython(
add_issue_number_data,
reverse_code=remove_issue_number_data
),
]
256 changes: 140 additions & 116 deletions comics/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from __future__ import unicode_literals

import datetime,os,rarfile,zipfile,tarfile
import datetime
import os
import rarfile
import zipfile
import tarfile

from shutil import copyfile
from multiselectfield import MultiSelectField
Expand All @@ -17,156 +21,176 @@
Choices for model use.
"""
# Generated years
YEAR_CHOICES = [(r,r) for r in range(1837, datetime.date.today().year+1)]
YEAR_CHOICES = [(r, r) for r in range(1837, datetime.date.today().year + 1)]

# Comic read status
STATUS_CHOICES = (
(0, 'Unread'),
(1, 'Partially read'),
(2, 'Completed'),
(0, 'Unread'),
(1, 'Partially read'),
(2, 'Completed'),
)

# Creator roles for an issue
ROLE_CHOICES = (
('artist', 'Artist'),
('colorist', 'Colorist'),
('cover', 'Cover'),
('editor', 'Editor'),
('inker', 'Inker'),
('journalist', 'Journalist'),
('letterer', 'Letterer'),
('other', 'Other'),
('penciler', 'Penciler'),
('production', 'Production'),
('writer', 'Writer'),
('artist', 'Artist'),
('colorist', 'Colorist'),
('cover', 'Cover'),
('editor', 'Editor'),
('inker', 'Inker'),
('journalist', 'Journalist'),
('letterer', 'Letterer'),
('other', 'Other'),
('penciler', 'Penciler'),
('production', 'Production'),
('writer', 'Writer'),
)


class Settings(SingletonModel):
api_key = models.CharField(
'ComicVine API Key',
help_text="A 40-character key provided by ComicVine. This is used to retrieve metadata about your comics. You can create a ComicVine API Key at <a target=\"_blank\" href=\"http://comicvine.gamespot.com/api/\">ComicVine's API Page</a> (ComicVine account is required).",
validators=[RegexValidator(
regex='^.{40}$',
message='Length must be 40 characters.',
code='nomatch'
)],
max_length=40,
blank=True
)

def __str__(self):
return "Settings"
api_key = models.CharField(
'ComicVine API Key',
help_text="A 40-character key provided by ComicVine. This is used to retrieve metadata about your comics. You can create a ComicVine API Key at <a target=\"_blank\" href=\"http://comicvine.gamespot.com/api/\">ComicVine's API Page</a> (ComicVine account is required).",
validators=[RegexValidator(
regex='^.{40}$',
message='Length must be 40 characters.',
code='nomatch'
)],
max_length=40,
blank=True
)

def __str__(self):
return "Settings"


class Arc(models.Model):
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Arc name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
image = models.FilePathField('Image file path', path="media/images", blank=True)
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Arc name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
image = models.FilePathField(
'Image file path', path="media/images", blank=True)

def __str__(self):
return self.name

def __str__(self):
return self.name

class Team(models.Model):
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Team name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
image = models.FilePathField('Image file path', path="media/images", blank=True)
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Team name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
image = models.FilePathField(
'Image file path', path="media/images", blank=True)

def __str__(self):
return self.name

def __str__(self):
return self.name

class Character(models.Model):
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Character name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
teams = models.ManyToManyField(Team, blank=True)
image = models.FilePathField('Image file path', path="media/images", blank=True)
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Character name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
teams = models.ManyToManyField(Team, blank=True)
image = models.FilePathField(
'Image file path', path="media/images", blank=True)

def __str__(self):
return self.name

def __str__(self):
return self.name

class Creator(models.Model):
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Creator name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
image = models.FilePathField('Image file path', path="media/images", blank=True)
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Creator name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
image = models.FilePathField(
'Image file path', path="media/images", blank=True)

def __str__(self):
return self.name

def __str__(self):
return self.name

class Publisher(models.Model):
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Series name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
logo = models.FilePathField('Logo file path', path="media/images", blank=True)
cvid = models.CharField(max_length=15)
cvurl = models.URLField(max_length=200)
name = models.CharField('Series name', max_length=200)
desc = models.TextField('Description', max_length=500, blank=True)
logo = models.FilePathField(
'Logo file path', path="media/images", blank=True)

def __str__(self):
return self.name

def __str__(self):
return self.name

class Series(models.Model):
cvid = models.CharField(max_length=15, blank=True)
cvurl = models.URLField(max_length=200, blank=True)
name = models.CharField('Series name', max_length=200)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE, null=True, blank=True)
year = models.PositiveSmallIntegerField('year', choices=YEAR_CHOICES, default=datetime.datetime.now().year, blank=True)
desc = models.TextField('Description', max_length=500, blank=True)
cvid = models.CharField(max_length=15, blank=True)
cvurl = models.URLField(max_length=200, blank=True)
name = models.CharField('Series name', max_length=200)
publisher = models.ForeignKey(
Publisher, on_delete=models.CASCADE, null=True, blank=True)
year = models.PositiveSmallIntegerField(
'year', choices=YEAR_CHOICES, default=datetime.datetime.now().year, blank=True)
desc = models.TextField('Description', max_length=500, blank=True)

def __str__(self):
return self.name
def __str__(self):
return self.name

def issue_numerical_order_set(self):
return self.issue_set.all().order_by('number')
def issue_numerical_order_set(self):
return self.issue_set.all().order_by('number')

def issue_count(self):
return self.issue_set.all().count()
def issue_count(self):
return self.issue_set.all().count()

def unread_issue_count(self):
return self.issue_set.exclude(status=2).count()
def unread_issue_count(self):
return self.issue_set.exclude(status=2).count()

class Meta:
verbose_name_plural = "Series"

class Meta:
verbose_name_plural = "Series"

class Issue(models.Model):
cvid = models.CharField('ComicVine ID', max_length=15, blank=True)
cvurl = models.URLField(max_length=200, blank=True)
series = models.ForeignKey(Series, on_delete=models.CASCADE, blank=True)
name = models.CharField('Issue name', max_length=200, blank=True)
number = models.PositiveSmallIntegerField('Issue number')
date = models.DateField('Cover date', blank=True)
desc = models.TextField('Description', max_length=500, blank=True)
arcs = models.ManyToManyField(Arc, blank=True)
characters = models.ManyToManyField(Character, blank=True)
teams = models.ManyToManyField(Team, blank=True)
file = models.FilePathField('File path', path="files/", recursive=True)
cover = models.FilePathField('Cover file path', path="media/images", blank=True)
status = models.PositiveSmallIntegerField('Status', choices=STATUS_CHOICES, default=0, blank=True)
leaf = models.PositiveSmallIntegerField(editable=False, default=1, blank=True)
page_count = models.PositiveSmallIntegerField(editable=False, default=1, blank=True)

def __str__(self):
return self.series.name + ' #' + str(self.number)

def get_absolute_url(self):
return reverse('author-detail', kwargs={'pk': self.pk})

def page_set(self):
comicfilehandler = ComicFileHandler()
comic = comicfilehandler.extract_comic(self.file, self.id)

return comic
cvid = models.CharField('ComicVine ID', max_length=15, blank=True)
cvurl = models.URLField(max_length=200, blank=True)
series = models.ForeignKey(Series, on_delete=models.CASCADE, blank=True)
name = models.CharField('Issue name', max_length=200, blank=True)
number = models.CharField('Issue number', max_length=25)
date = models.DateField('Cover date', blank=True)
desc = models.TextField('Description', max_length=500, blank=True)
arcs = models.ManyToManyField(Arc, blank=True)
characters = models.ManyToManyField(Character, blank=True)
teams = models.ManyToManyField(Team, blank=True)
file = models.FilePathField('File path', path="files/", recursive=True)
cover = models.FilePathField(
'Cover file path', path="media/images", blank=True)
status = models.PositiveSmallIntegerField(
'Status', choices=STATUS_CHOICES, default=0, blank=True)
leaf = models.PositiveSmallIntegerField(
editable=False, default=1, blank=True)
page_count = models.PositiveSmallIntegerField(
editable=False, default=1, blank=True)

def __str__(self):
return self.series.name + ' #' + str(self.number)

def get_absolute_url(self):
return reverse('author-detail', kwargs={'pk': self.pk})

def page_set(self):
comicfilehandler = ComicFileHandler()
comic = comicfilehandler.extract_comic(self.file, self.id)

return comic


class Roles(models.Model):
creator = models.ForeignKey(Creator, on_delete=models.CASCADE)
issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
roles = MultiSelectField(choices=ROLE_CHOICES)
creator = models.ForeignKey(Creator, on_delete=models.CASCADE)
issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
roles = MultiSelectField(choices=ROLE_CHOICES)

def __str__(self):
return self.issue.series.name + ' #' + str(self.issue.number) + ' - ' + self.creator.name
def __str__(self):
return self.issue.series.name + ' #' + str(self.issue.number) + ' - ' + self.creator.name

class Meta:
verbose_name_plural = "Roles"
class Meta:
verbose_name_plural = "Roles"
Empty file.
Loading