mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2025-02-01 11:52:20 +00:00
WIP: Add Series model
This commit is contained in:
parent
c4b21ee258
commit
5fcdfbc9c6
6 changed files with 201 additions and 21 deletions
|
@ -1,4 +1,5 @@
|
|||
""" using django model forms """
|
||||
|
||||
from django import forms
|
||||
|
||||
from file_resubmit.widgets import ResubmitImageWidget
|
||||
|
@ -25,7 +26,6 @@ class EditionForm(CustomForm):
|
|||
"subtitle",
|
||||
"description",
|
||||
"series",
|
||||
"series_number",
|
||||
"languages",
|
||||
"subjects",
|
||||
"publishers",
|
||||
|
@ -55,9 +55,6 @@ class EditionForm(CustomForm):
|
|||
attrs={"aria-describedby": "desc_description"}
|
||||
),
|
||||
"series": forms.TextInput(attrs={"aria-describedby": "desc_series"}),
|
||||
"series_number": forms.TextInput(
|
||||
attrs={"aria-describedby": "desc_series_number"}
|
||||
),
|
||||
"subjects": ArrayWidget(),
|
||||
"languages": forms.TextInput(
|
||||
attrs={"aria-describedby": "desc_languages_help desc_languages"}
|
||||
|
@ -116,7 +113,6 @@ class EditionFromWorkForm(CustomForm):
|
|||
"description",
|
||||
"languages",
|
||||
"series",
|
||||
"series_number",
|
||||
"subjects",
|
||||
"subject_places",
|
||||
"cover",
|
||||
|
|
148
bookwyrm/migrations/0206_series_model.py
Normal file
148
bookwyrm/migrations/0206_series_model.py
Normal file
|
@ -0,0 +1,148 @@
|
|||
# Generated by Django 3.2.23 on 2024-02-04 20:27
|
||||
|
||||
import bookwyrm.models.fields
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
def make_series(apps, schema_editor):
|
||||
Edition = apps.get_model("bookwyrm", "Edition")
|
||||
Series = apps.get_model("bookwyrm", "Series")
|
||||
SeriesBook = apps.get_model("bookwyrm", "SeriesBook")
|
||||
|
||||
db_alias = schema_editor.connection.alias
|
||||
|
||||
with_series = (
|
||||
Edition.objects.using(db_alias)
|
||||
.exclude(series_name__isnull=True)
|
||||
.exclude(series_name__exact="")
|
||||
.order_by("series_name", "series_number")
|
||||
)
|
||||
for edition in with_series:
|
||||
# TODO: Try to parse number from series_name if series_number is empty?
|
||||
series, _ = Series.objects.using(db_alias).get_or_create(
|
||||
name=edition.series_name,
|
||||
authors=edition.authors.all(),
|
||||
)
|
||||
SeriesBook.objects.using(db_alias).create(
|
||||
book=edition, series=series, number=edition.series_number
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("bookwyrm", "0205_merge_20240413_0232.py"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name="book",
|
||||
old_name="series",
|
||||
new_name="series_name",
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Series",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("created_date", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_date", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"remote_id",
|
||||
bookwyrm.models.fields.RemoteIdField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
validators=[bookwyrm.models.fields.validate_remote_id],
|
||||
),
|
||||
),
|
||||
("name", bookwyrm.models.fields.CharField(max_length=100)),
|
||||
(
|
||||
"authors",
|
||||
bookwyrm.models.fields.ManyToManyField(to="bookwyrm.Author"),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="SeriesBook",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("created_date", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_date", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"remote_id",
|
||||
bookwyrm.models.fields.RemoteIdField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
validators=[bookwyrm.models.fields.validate_remote_id],
|
||||
),
|
||||
),
|
||||
(
|
||||
"number",
|
||||
bookwyrm.models.fields.CharField(
|
||||
blank=True, max_length=255, null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"book",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT, to="bookwyrm.book"
|
||||
),
|
||||
),
|
||||
(
|
||||
"series",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="bookwyrm.series",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"ordering": ["-number"],
|
||||
"unique_together": {("book", "series")},
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="series",
|
||||
name="books",
|
||||
field=bookwyrm.models.fields.ManyToManyField(
|
||||
related_name="series_books",
|
||||
through="bookwyrm.SeriesBook",
|
||||
to="bookwyrm.Book",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="book",
|
||||
name="series",
|
||||
field=models.ManyToManyField(
|
||||
through="bookwyrm.SeriesBook", to="bookwyrm.Series"
|
||||
),
|
||||
),
|
||||
migrations.RunPython(make_series), # TODO: reverse_code
|
||||
migrations.RemoveField(
|
||||
model_name="book",
|
||||
name="series_number",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="book",
|
||||
name="series_name",
|
||||
),
|
||||
]
|
|
@ -1,4 +1,5 @@
|
|||
""" bring all the models into the app namespace """
|
||||
|
||||
import inspect
|
||||
import sys
|
||||
|
||||
|
@ -7,6 +8,8 @@ from .author import Author
|
|||
from .link import Link, FileLink, LinkDomain
|
||||
from .connector import Connector
|
||||
|
||||
from .series import Series, SeriesBook
|
||||
|
||||
from .shelf import Shelf, ShelfBook
|
||||
from .list import List, ListItem
|
||||
|
||||
|
|
|
@ -229,8 +229,11 @@ class Book(BookDataModel):
|
|||
languages = fields.ArrayField(
|
||||
models.CharField(max_length=255), blank=True, default=list
|
||||
)
|
||||
series = fields.TextField(max_length=255, blank=True, null=True)
|
||||
series_number = fields.CharField(max_length=255, blank=True, null=True)
|
||||
series = models.ManyToManyField(
|
||||
"Series",
|
||||
through="SeriesBook",
|
||||
through_fields=("book", "series"),
|
||||
)
|
||||
subjects = fields.ArrayField(
|
||||
models.CharField(max_length=255), blank=True, null=True, default=list
|
||||
)
|
||||
|
|
35
bookwyrm/models/series.py
Normal file
35
bookwyrm/models/series.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
"""series of books"""
|
||||
|
||||
from django.db import models
|
||||
|
||||
from .base_model import BookWyrmModel
|
||||
from . import fields
|
||||
|
||||
|
||||
class Series(BookWyrmModel):
|
||||
"""a named series of books"""
|
||||
|
||||
name = fields.CharField(max_length=100)
|
||||
authors = fields.ManyToManyField("Author") # TODO: add on Author model
|
||||
books = fields.ManyToManyField(
|
||||
"Book",
|
||||
through="SeriesBook",
|
||||
through_fields=("series", "book"),
|
||||
related_name="series_books",
|
||||
)
|
||||
|
||||
|
||||
class SeriesBook(BookWyrmModel):
|
||||
"""membership of a series"""
|
||||
|
||||
book = models.ForeignKey("Book", on_delete=models.PROTECT)
|
||||
series = models.ForeignKey("Series", on_delete=models.PROTECT)
|
||||
number = fields.CharField(max_length=255, blank=True, null=True)
|
||||
|
||||
collection_field = "series"
|
||||
|
||||
class Meta:
|
||||
"""a series can't contain the same book twice"""
|
||||
|
||||
unique_together = ("book", "series")
|
||||
ordering = ["-number"]
|
|
@ -31,7 +31,7 @@
|
|||
{{ book.title }}
|
||||
</h1>
|
||||
|
||||
{% if book.subtitle or book.series %}
|
||||
{% if book.subtitle or book.series.exists %}
|
||||
<p class="subtitle title is-5">
|
||||
{% if book.subtitle %}
|
||||
<meta
|
||||
|
@ -44,24 +44,19 @@
|
|||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if book.series %}
|
||||
{% for book_series in book.series.all %}
|
||||
{% spaceless %}
|
||||
<span itemprop="isPartOf" itemscope itemtype="https://schema.org/BookSeries">
|
||||
{% if book.authors.exists %}
|
||||
<a href="{% url 'book-series-by' book.authors.first.id %}?series_name={{ book.series | urlencode }}"
|
||||
itemprop="url">
|
||||
{% endif %}
|
||||
<span itemprop="name">{{ book.series }}</span>
|
||||
{% if book.authors.exists %}
|
||||
<a href="{{ book_series.local_path }}" itemprop="url">
|
||||
<span itemprop="name">{{ book_series.series.name }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% if book.series_number %}
|
||||
{% if book_series.number %}
|
||||
<span>, #</span>
|
||||
<span itemprop="position">{{ book.series_number }}</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endspaceless %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
|
|
Loading…
Reference in a new issue