mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2025-02-01 20:02:21 +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 """
|
""" using django model forms """
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from file_resubmit.widgets import ResubmitImageWidget
|
from file_resubmit.widgets import ResubmitImageWidget
|
||||||
|
@ -25,7 +26,6 @@ class EditionForm(CustomForm):
|
||||||
"subtitle",
|
"subtitle",
|
||||||
"description",
|
"description",
|
||||||
"series",
|
"series",
|
||||||
"series_number",
|
|
||||||
"languages",
|
"languages",
|
||||||
"subjects",
|
"subjects",
|
||||||
"publishers",
|
"publishers",
|
||||||
|
@ -55,9 +55,6 @@ class EditionForm(CustomForm):
|
||||||
attrs={"aria-describedby": "desc_description"}
|
attrs={"aria-describedby": "desc_description"}
|
||||||
),
|
),
|
||||||
"series": forms.TextInput(attrs={"aria-describedby": "desc_series"}),
|
"series": forms.TextInput(attrs={"aria-describedby": "desc_series"}),
|
||||||
"series_number": forms.TextInput(
|
|
||||||
attrs={"aria-describedby": "desc_series_number"}
|
|
||||||
),
|
|
||||||
"subjects": ArrayWidget(),
|
"subjects": ArrayWidget(),
|
||||||
"languages": forms.TextInput(
|
"languages": forms.TextInput(
|
||||||
attrs={"aria-describedby": "desc_languages_help desc_languages"}
|
attrs={"aria-describedby": "desc_languages_help desc_languages"}
|
||||||
|
@ -116,7 +113,6 @@ class EditionFromWorkForm(CustomForm):
|
||||||
"description",
|
"description",
|
||||||
"languages",
|
"languages",
|
||||||
"series",
|
"series",
|
||||||
"series_number",
|
|
||||||
"subjects",
|
"subjects",
|
||||||
"subject_places",
|
"subject_places",
|
||||||
"cover",
|
"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 """
|
""" bring all the models into the app namespace """
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -7,6 +8,8 @@ from .author import Author
|
||||||
from .link import Link, FileLink, LinkDomain
|
from .link import Link, FileLink, LinkDomain
|
||||||
from .connector import Connector
|
from .connector import Connector
|
||||||
|
|
||||||
|
from .series import Series, SeriesBook
|
||||||
|
|
||||||
from .shelf import Shelf, ShelfBook
|
from .shelf import Shelf, ShelfBook
|
||||||
from .list import List, ListItem
|
from .list import List, ListItem
|
||||||
|
|
||||||
|
|
|
@ -229,8 +229,11 @@ class Book(BookDataModel):
|
||||||
languages = fields.ArrayField(
|
languages = fields.ArrayField(
|
||||||
models.CharField(max_length=255), blank=True, default=list
|
models.CharField(max_length=255), blank=True, default=list
|
||||||
)
|
)
|
||||||
series = fields.TextField(max_length=255, blank=True, null=True)
|
series = models.ManyToManyField(
|
||||||
series_number = fields.CharField(max_length=255, blank=True, null=True)
|
"Series",
|
||||||
|
through="SeriesBook",
|
||||||
|
through_fields=("book", "series"),
|
||||||
|
)
|
||||||
subjects = fields.ArrayField(
|
subjects = fields.ArrayField(
|
||||||
models.CharField(max_length=255), blank=True, null=True, default=list
|
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 }}
|
{{ book.title }}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
{% if book.subtitle or book.series %}
|
{% if book.subtitle or book.series.exists %}
|
||||||
<p class="subtitle title is-5">
|
<p class="subtitle title is-5">
|
||||||
{% if book.subtitle %}
|
{% if book.subtitle %}
|
||||||
<meta
|
<meta
|
||||||
|
@ -44,24 +44,19 @@
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if book.series %}
|
{% for book_series in book.series.all %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<span itemprop="isPartOf" itemscope itemtype="https://schema.org/BookSeries">
|
<span itemprop="isPartOf" itemscope itemtype="https://schema.org/BookSeries">
|
||||||
{% if book.authors.exists %}
|
<a href="{{ book_series.local_path }}" itemprop="url">
|
||||||
<a href="{% url 'book-series-by' book.authors.first.id %}?series_name={{ book.series | urlencode }}"
|
<span itemprop="name">{{ book_series.series.name }}</span>
|
||||||
itemprop="url">
|
|
||||||
{% endif %}
|
|
||||||
<span itemprop="name">{{ book.series }}</span>
|
|
||||||
{% if book.authors.exists %}
|
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% if book_series.number %}
|
||||||
</span>
|
|
||||||
{% if book.series_number %}
|
|
||||||
<span>, #</span>
|
<span>, #</span>
|
||||||
<span itemprop="position">{{ book.series_number }}</span>
|
<span itemprop="position">{{ book.series_number }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</span>
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue