moviewyrm/fedireads/models/book.py
2020-03-06 22:58:51 -08:00

84 lines
3.5 KiB
Python

''' 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)
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)
@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 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)