Stabilize the magazine repository app

This commit is contained in:
2025-12-08 22:48:14 +01:00
parent 5e6366e10c
commit 7f456890dd
6 changed files with 261 additions and 48 deletions

View File

@@ -76,7 +76,7 @@ class BookAdmin(SortableAdminBase, admin.ModelAdmin):
autocomplete_fields = ("authors", "publisher", "shop")
readonly_fields = ("invoices", "creation_time", "updated_time")
search_fields = ("title", "publisher__name", "authors__last_name")
list_filter = ("publisher__name", "authors")
list_filter = ("publisher__name", "authors", "published")
fieldsets = (
(
@@ -239,7 +239,12 @@ class CatalogAdmin(SortableAdminBase, admin.ModelAdmin):
autocomplete_fields = ("manufacturer",)
readonly_fields = ("invoices", "creation_time", "updated_time")
search_fields = ("manufacturer__name", "years", "scales__scale")
list_filter = ("manufacturer__name", "publication_year", "scales__scale")
list_filter = (
"manufacturer__name",
"publication_year",
"scales__scale",
"published",
)
fieldsets = (
(
@@ -358,8 +363,8 @@ class CatalogAdmin(SortableAdminBase, admin.ModelAdmin):
actions = [publish, unpublish, download_csv]
@admin.register(Issue)
class MagazineIssueAdmin(admin.ModelAdmin):
@admin.register(MagazineIssue)
class MagazineIssueAdmin(SortableAdminBase, admin.ModelAdmin):
inlines = (
BookPropertyInline,
BookImageInline,
@@ -370,10 +375,8 @@ class MagazineIssueAdmin(admin.ModelAdmin):
"issue_number",
"published",
)
# autocomplete_fields = ("publisher",)
# readonly_fields = ("creation_time", "updated_time")
# search_fields = ("title", "publisher__name")
# list_filter = ("publisher__name", "language")
autocomplete_fields = ("shop",)
readonly_fields = ("magazine", "creation_time", "updated_time")
def get_model_perms(self, request):
"""
@@ -381,14 +384,106 @@ class MagazineIssueAdmin(admin.ModelAdmin):
"""
return {}
fieldsets = (
(
None,
{
"fields": (
"published",
"magazine",
"issue_number",
"publication_year",
"publication_month",
"ISBN",
"language",
"number_of_pages",
"description",
"tags",
)
},
),
(
"Purchase data",
{
"classes": ("collapse",),
"fields": (
"shop",
"purchase_date",
"price",
),
},
),
(
"Notes",
{"classes": ("collapse",), "fields": ("notes",)},
),
(
"Audit",
{
"classes": ("collapse",),
"fields": (
"creation_time",
"updated_time",
),
},
),
)
actions = [publish, unpublish]
class MagazineIssueInline(admin.StackedInline):
model = MagazineIssue
min_num = 0
extra = 0
autocomplete_fields = ("shop",)
show_change_link = True
fieldsets = (
(
None,
{
"fields": (
"published",
"issue_number",
"publication_year",
"publication_month",
)
},
),
(
"Additional info",
{
"classes": ("collapse",),
"fields": (
"language",
"number_of_pages",
"ISBN",
"tags",
),
},
),
(
"Purchase data",
{
"classes": ("collapse",),
"fields": (
"shop",
"purchase_date",
"price",
),
},
),
)
class Media:
js = ('admin/js/magazine_issue_defaults.js',)
@admin.register(Magazine)
class MagazineAdmin(admin.ModelAdmin):
class MagazineAdmin(SortableAdminBase, admin.ModelAdmin):
inlines = (
MagazineIssueInline,
)
list_display = (
"__str__",
"publisher",
@@ -397,6 +492,37 @@ class MagazineAdmin(admin.ModelAdmin):
autocomplete_fields = ("publisher",)
readonly_fields = ("creation_time", "updated_time")
search_fields = ("name", "publisher__name")
list_filter = ("publisher__name", "language")
list_filter = ("publisher__name", "published")
fieldsets = (
(
None,
{
"fields": (
"published",
"name",
"publisher",
"ISBN",
"language",
"description",
"image",
"tags",
)
},
),
(
"Notes",
{"classes": ("collapse",), "fields": ("notes",)},
),
(
"Audit",
{
"classes": ("collapse",),
"fields": (
"creation_time",
"updated_time",
),
},
),
)
actions = [publish, unpublish]

View File

@@ -1,4 +1,4 @@
# Generated by Django 5.2.8 on 2025-11-13 23:01
# Generated by Django 6.0 on 2025-12-08 17:47
import bookshelf.models
import django.db.models.deletion
@@ -11,32 +11,11 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookshelf", "0023_delete_basebookdocument"),
("bookshelf", "0024_alter_basebook_language"),
("metadata", "0025_alter_company_options_alter_manufacturer_options_and_more"),
]
operations = [
migrations.CreateModel(
name="Issue",
fields=[
(
"basebook_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="bookshelf.basebook",
),
),
("issue_number", models.CharField(max_length=100)),
],
options={
"abstract": False,
},
bases=("bookshelf.basebook",),
),
migrations.CreateModel(
name="Magazine",
fields=[
@@ -55,12 +34,13 @@ class Migration(migrations.Migration):
("updated_time", models.DateTimeField(auto_now=True)),
("published", models.BooleanField(default=True)),
("name", models.CharField(max_length=200)),
("ISBN", models.CharField(blank=True, max_length=17)),
(
"image",
models.ImageField(
blank=True,
storage=ram.utils.DeduplicatedStorage,
upload_to=bookshelf.models.magazine_image_upload,
upload_to=bookshelf.models.book_image_upload,
),
),
(
@@ -108,6 +88,7 @@ class Migration(migrations.Migration):
("hi", "Hindi"),
("hr", "Croatian"),
("hsb", "Upper Sorbian"),
("ht", "Haitian Creole"),
("hu", "Hungarian"),
("hy", "Armenian"),
("ia", "Interlingua"),
@@ -193,34 +174,51 @@ class Migration(migrations.Migration):
name="MagazineIssue",
fields=[
(
"id",
models.BigAutoField(
"basebook_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
verbose_name="ID",
to="bookshelf.basebook",
),
),
("issue_number", models.CharField(max_length=100)),
(
"issue",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="magazine_issue",
to="bookshelf.issue",
"publication_month",
models.SmallIntegerField(
blank=True,
choices=[
(1, "January"),
(2, "February"),
(3, "March"),
(4, "April"),
(5, "May"),
(6, "June"),
(7, "July"),
(8, "August"),
(9, "September"),
(10, "October"),
(11, "November"),
(12, "December"),
],
null=True,
),
),
(
"magazine",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="magazine_issue",
related_name="issue",
to="bookshelf.magazine",
),
),
],
options={
"ordering": ["magazine", "issue"],
"unique_together": {("magazine", "issue")},
"ordering": ["magazine", "issue_number"],
"unique_together": {("magazine", "issue_number")},
},
bases=("bookshelf.basebook",),
),
]

View File

@@ -4,6 +4,7 @@ from django.db import models
from django.conf import settings
from django.urls import reverse
from django.utils.dates import MONTHS
from django.core.exceptions import ValidationError
from django_countries.fields import CountryField
from ram.utils import DeduplicatedStorage
@@ -212,4 +213,11 @@ class MagazineIssue(BaseBook):
ordering = ["magazine", "issue_number"]
def __str__(self):
return f"{self.magazine.name} - {self.issue.issue_number}"
return f"{self.magazine.name} - {self.issue_number}"
def clean(self):
if self.magazine.published is False and self.published is True:
raise ValidationError(
"Cannot set an issue as published if the magazine is not "
"published."
)

View File

@@ -0,0 +1,16 @@
document.addEventListener('formset:added', function(event) {
const newForm = event.target; // the new inline form element
const defaultLanguage = document.querySelector('#id_language').value;
const defaultStatus = document.querySelector('#id_published').checked;
const languageInput = newForm.querySelector('select[name$="language"]');
const statusInput = newForm.querySelector('input[name$="published"]');
if (languageInput) {
languageInput.value = defaultLanguage;
}
if (statusInput) {
statusInput.checked = defaultStatus;
}
});