''' database schema for books and shelves ''' from datetime import datetime from django.db import models from uuid import uuid4 from fedireads.settings import DOMAIN from fedireads.utils.fields import JSONField, ArrayField from fedireads.utils.models import FedireadsModel class Book(FedireadsModel): ''' a generic book, which can mean either an edition or a work ''' # these identifiers apply to both works and editions openlibrary_key = models.CharField(max_length=255, unique=True, null=True) librarything_key = models.CharField(max_length=255, unique=True, null=True) local_key = models.CharField(max_length=255, unique=True, default=uuid4) misc_identifiers = JSONField(null=True) # info about where the data comes from and where/if to sync origin = models.CharField(max_length=255, unique=True, null=True) local_edits = models.BooleanField(default=False) sync = models.BooleanField(default=True) last_sync_date = models.DateTimeField(default=datetime.now) # TODO: edit history # book/work metadata title = models.CharField(max_length=255) sort_title = models.CharField(max_length=255, null=True) subtitle = models.TextField(blank=True, null=True) description = models.TextField(blank=True, null=True) language = models.CharField(max_length=255, null=True) series = models.CharField(max_length=255, blank=True, null=True) series_number = models.CharField(max_length=255, blank=True, null=True) # TODO: include an annotation about the type of authorship (ie, translator) authors = models.ManyToManyField('Author') # TODO: also store cover thumbnail cover = models.ImageField(upload_to='covers/', blank=True, null=True) first_published_date = models.DateTimeField(null=True) published_date = models.DateTimeField(null=True) shelves = models.ManyToManyField( 'Shelf', symmetrical=False, through='ShelfBook', through_fields=('book', 'shelf') ) # TODO: why can't I just call this work???? parent_work = models.ForeignKey('Work', on_delete=models.PROTECT, null=True) @property def absolute_id(self): ''' constructs the absolute reference to any db object ''' base_path = 'https://%s' % DOMAIN model_name = type(self).__name__.lower() return '%s/%s/%s' % (base_path, model_name, self.openlibrary_key) class Work(Book): ''' a work (an abstract concept of a book that manifests in an edition) ''' # library of congress catalog control number lccn = models.CharField(max_length=255, unique=True, null=True) class Edition(Book): ''' an edition of a book ''' # these identifiers only apply to work isbn = models.CharField(max_length=255, unique=True, null=True) oclc_number = models.CharField(max_length=255, unique=True, null=True) pages = models.IntegerField(null=True) class Author(FedireadsModel): ''' copy of an author from OL ''' openlibrary_key = models.CharField(max_length=255, null=True, unique=True) wikipedia_link = models.CharField(max_length=255, blank=True, null=True) # idk probably other keys would be useful here? born = models.DateTimeField(null=True) died = models.DateTimeField(null=True) name = models.CharField(max_length=255) last_name = models.CharField(max_length=255, null=True) first_name = models.CharField(max_length=255, null=True) aliases = ArrayField(models.CharField(max_length=255), blank=True) bio = models.TextField(null=True, blank=True)