mirror of
https://github.com/daniviga/django-ram.git
synced 2025-12-26 07:18:32 +01:00
Stabilize the magazine repository app
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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",),
|
||||
),
|
||||
]
|
||||
@@ -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."
|
||||
)
|
||||
|
||||
16
ram/bookshelf/static/admin/js/magazine_issue_defaults.js
Normal file
16
ram/bookshelf/static/admin/js/magazine_issue_defaults.js
Normal 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;
|
||||
}
|
||||
});
|
||||
65
ram/repository/migrations/0004_magazineissuedocument.py
Normal file
65
ram/repository/migrations/0004_magazineissuedocument.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated by Django 6.0 on 2025-12-08 17:47
|
||||
|
||||
import django.db.models.deletion
|
||||
import ram.utils
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("bookshelf", "0025_magazine_magazineissue"),
|
||||
(
|
||||
"repository",
|
||||
"0003_alter_bookdocument_file_alter_catalogdocument_file_and_more",
|
||||
),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="MagazineIssueDocument",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("description", models.CharField(blank=True, max_length=128)),
|
||||
(
|
||||
"file",
|
||||
models.FileField(
|
||||
storage=ram.utils.DeduplicatedStorage, upload_to="files/"
|
||||
),
|
||||
),
|
||||
("creation_time", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_time", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"private",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="Document will be visible only to logged users",
|
||||
),
|
||||
),
|
||||
(
|
||||
"issue",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="document",
|
||||
to="bookshelf.magazineissue",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name_plural": "Magazines documents",
|
||||
"constraints": [
|
||||
models.UniqueConstraint(
|
||||
fields=("issue", "file"), name="unique_issue_file"
|
||||
)
|
||||
],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -5,7 +5,7 @@ from tinymce import models as tinymce
|
||||
from ram.models import PrivateDocument
|
||||
from metadata.models import Decoder, Shop, Tag
|
||||
from roster.models import RollingStock
|
||||
from bookshelf.models import Book, Catalog, Issue
|
||||
from bookshelf.models import Book, Catalog, MagazineIssue
|
||||
|
||||
|
||||
class GenericDocument(PrivateDocument):
|
||||
@@ -78,7 +78,7 @@ class CatalogDocument(PrivateDocument):
|
||||
|
||||
class MagazineIssueDocument(PrivateDocument):
|
||||
issue = models.ForeignKey(
|
||||
Issue, on_delete=models.CASCADE, related_name="document"
|
||||
MagazineIssue, on_delete=models.CASCADE, related_name="document"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
||||
Reference in New Issue
Block a user