diff --git a/ram/bookshelf/migrations/0028_alter_magazine_options_alter_magazineissue_options.py b/ram/bookshelf/migrations/0028_alter_magazine_options_alter_magazineissue_options.py new file mode 100644 index 0000000..688329b --- /dev/null +++ b/ram/bookshelf/migrations/0028_alter_magazine_options_alter_magazineissue_options.py @@ -0,0 +1,29 @@ +# Generated by Django 6.0 on 2025-12-21 21:56 + +import django.db.models.functions.text +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookshelf", "0027_magazine_website"), + ] + + operations = [ + migrations.AlterModelOptions( + name="magazine", + options={"ordering": [django.db.models.functions.text.Lower("name")]}, + ), + migrations.AlterModelOptions( + name="magazineissue", + options={ + "ordering": [ + "magazine", + "publication_year", + "publication_month", + "issue_number", + ] + }, + ), + ] diff --git a/ram/bookshelf/models.py b/ram/bookshelf/models.py index df556ce..f3b5f36 100644 --- a/ram/bookshelf/models.py +++ b/ram/bookshelf/models.py @@ -5,6 +5,7 @@ from django.db import models from django.conf import settings from django.urls import reverse from django.utils.dates import MONTHS +from django.db.models.functions import Lower from django.core.exceptions import ValidationError from django_countries.fields import CountryField @@ -59,36 +60,24 @@ class BaseBook(BaseModel): blank=True, ) purchase_date = models.DateField(null=True, blank=True) - tags = models.ManyToManyField( - Tag, related_name="bookshelf", blank=True - ) + tags = models.ManyToManyField(Tag, related_name="bookshelf", blank=True) def delete(self, *args, **kwargs): shutil.rmtree( os.path.join( settings.MEDIA_ROOT, "images", "books", str(self.uuid) ), - ignore_errors=True + ignore_errors=True, ) super(BaseBook, self).delete(*args, **kwargs) def book_image_upload(instance, filename): - return os.path.join( - "images", - "books", - str(instance.book.uuid), - filename - ) + return os.path.join("images", "books", str(instance.book.uuid), filename) def magazine_image_upload(instance, filename): - return os.path.join( - "images", - "magazines", - str(instance.uuid), - filename - ) + return os.path.join("images", "magazines", str(instance.uuid), filename) class BaseBookImage(Image): @@ -132,8 +121,7 @@ class Book(BaseBook): def get_absolute_url(self): return reverse( - "bookshelf_item", - kwargs={"selector": "book", "uuid": self.uuid} + "bookshelf_item", kwargs={"selector": "book", "uuid": self.uuid} ) @@ -158,12 +146,12 @@ class Catalog(BaseBook): def get_absolute_url(self): return reverse( - "bookshelf_item", - kwargs={"selector": "catalog", "uuid": self.uuid} + "bookshelf_item", kwargs={"selector": "catalog", "uuid": self.uuid} ) def get_scales(self): return "/".join([s.scale for s in self.scales.all()]) + get_scales.short_description = "Scales" @@ -180,32 +168,27 @@ class Magazine(BaseModel): language = models.CharField( max_length=7, choices=sorted(settings.LANGUAGES, key=lambda s: s[1]), - default='en' - ) - tags = models.ManyToManyField( - Tag, related_name="magazine", blank=True + default="en", ) + tags = models.ManyToManyField(Tag, related_name="magazine", blank=True) def delete(self, *args, **kwargs): shutil.rmtree( os.path.join( settings.MEDIA_ROOT, "images", "magazines", str(self.uuid) ), - ignore_errors=True + ignore_errors=True, ) super(Magazine, self).delete(*args, **kwargs) class Meta: - ordering = ["name"] + ordering = [Lower("name")] def __str__(self): return self.name def get_absolute_url(self): - return reverse( - "magazine", - kwargs={"uuid": self.uuid} - ) + return reverse("magazine", kwargs={"uuid": self.uuid}) def website_short(self): if self.website: @@ -218,14 +201,17 @@ class MagazineIssue(BaseBook): ) issue_number = models.CharField(max_length=100) publication_month = models.SmallIntegerField( - null=True, - blank=True, - choices=MONTHS.items() + null=True, blank=True, choices=MONTHS.items() ) class Meta: unique_together = ("magazine", "issue_number") - ordering = ["magazine", "issue_number"] + ordering = [ + "magazine", + "publication_year", + "publication_month", + "issue_number", + ] def __str__(self): return f"{self.magazine.name} - {self.issue_number}" @@ -246,9 +232,5 @@ class MagazineIssue(BaseBook): def get_absolute_url(self): return reverse( - "issue", - kwargs={ - "uuid": self.uuid, - "magazine": self.magazine.uuid - } + "issue", kwargs={"uuid": self.uuid, "magazine": self.magazine.uuid} ) diff --git a/ram/portal/templates/cards/book.html b/ram/portal/templates/cards/book.html index b425ba1..1421c61 100644 --- a/ram/portal/templates/cards/book.html +++ b/ram/portal/templates/cards/book.html @@ -13,13 +13,13 @@ {{ d.item }}

- {% if d.item.tags.all %}

Tags: {% for t in d.item.tags.all %} {{ t.name }}{# new line is required #} + {% empty %} + {% endfor %}

- {% endif %} diff --git a/ram/portal/templates/cards/consist.html b/ram/portal/templates/cards/consist.html index e3da341..1fc8ce6 100644 --- a/ram/portal/templates/cards/consist.html +++ b/ram/portal/templates/cards/consist.html @@ -14,13 +14,13 @@ {{ d.item }}

- {% if d.item.tags.all %}

Tags: {% for t in d.item.tags.all %} {{ t.name }}{# new line is required #} + {% empty %} + {% endfor %}

- {% endif %}
diff --git a/ram/portal/templates/cards/magazine.html b/ram/portal/templates/cards/magazine.html index c86a5a6..25832b5 100644 --- a/ram/portal/templates/cards/magazine.html +++ b/ram/portal/templates/cards/magazine.html @@ -31,13 +31,13 @@ {{ d.item }}

- {% if d.item.tags.all %}

Tags: {% for t in d.item.tags.all %} {{ t.name }}{# new line is required #} + {% empty %} + {% endfor %}

- {% endif %}
diff --git a/ram/portal/templates/cards/roster.html b/ram/portal/templates/cards/roster.html index 4519c05..0d79921 100644 --- a/ram/portal/templates/cards/roster.html +++ b/ram/portal/templates/cards/roster.html @@ -14,13 +14,13 @@ {{ d.item }}

- {% if d.item.tags.all %}

Tags: {% for t in d.item.tags.all %} {{ t.name }}{# new line is required #} + {% empty %} + {% endfor %}

- {% endif %}
diff --git a/ram/portal/views.py b/ram/portal/views.py index 588f212..5e059a5 100644 --- a/ram/portal/views.py +++ b/ram/portal/views.py @@ -8,6 +8,7 @@ from django.views import View from django.http import Http404, HttpResponseBadRequest from django.db.utils import OperationalError, ProgrammingError from django.db.models import F, Q, Count +from django.db.models.functions import Lower from django.shortcuts import render, get_object_or_404, get_list_or_404 from django.core.exceptions import ObjectDoesNotExist from django.core.paginator import Paginator @@ -76,11 +77,13 @@ class GetData(View): def get(self, request, page=1): data = [] for item in self.get_data(request): - data.append({ - "type": self.item_type, - "label": self.item_type.capitalize(), - "item": item - }) + data.append( + { + "type": self.item_type, + "label": self.item_type.capitalize(), + "item": item, + } + ) paginator = Paginator(data, get_items_per_page()) data = paginator.get_page(page) @@ -180,16 +183,50 @@ class SearchObjects(View): data.append({"type": "consist", "item": item}) books = ( Book.objects.get_published(request.user) - .filter(title__icontains=search) + .filter( + Q( + Q(title__icontains=search) + | Q(description__icontains=search) + ) + ) .distinct() ) catalogs = ( Catalog.objects.get_published(request.user) - .filter(manufacturer__name__icontains=search) + .filter( + Q( + Q(manufacturer__name__icontains=search) + | Q(description__icontains=search) + ) + ) .distinct() ) for item in list(chain(books, catalogs)): - data.append({"type": "book", "item": item}) + data.append( + { + "type": "book", + "label": item._meta.object_name, + "item": item, + } + ) + magazine_issues = ( + MagazineIssue.objects.get_published(request.user) + .filter( + Q( + Q(magazine__name__icontains=search) + | Q(description__icontains=search) + ) + ) + .distinct() + ) + for item in magazine_issues: + data.append( + { + "type": "book", + "label": "Magazine Issue", + "item": item, + } + ) paginator = Paginator(data, get_items_per_page()) data = paginator.get_page(page) @@ -347,15 +384,32 @@ class GetObjectsFiltered(View): .filter(query_2nd) .distinct() ) - for item in books: - data.append({"type": "book", "item": item}) catalogs = ( Catalog.objects.get_published(request.user) .filter(query_2nd) .distinct() ) - for item in catalogs: - data.append({"type": "catalog", "item": item}) + for item in list(chain(books, catalogs)): + data.append( + { + "type": "book", + "label": item._meta.object_name, + "item": item, + } + ) + magazine_issues = ( + MagazineIssue.objects.get_published(request.user) + .filter(query_2nd) + .distinct() + ) + for item in magazine_issues: + data.append( + { + "type": "book", + "label": "Magazine Issue", + "item": item, + } + ) except NameError: pass @@ -647,7 +701,7 @@ class Magazines(GetData): def get_data(self, request): return ( Magazine.objects.get_published(request.user) - .all() + .order_by(Lower("name")) .annotate( issues=Count( "issue", diff --git a/ram/ram/__init__.py b/ram/ram/__init__.py index 0f17a7e..35e25c3 100644 --- a/ram/ram/__init__.py +++ b/ram/ram/__init__.py @@ -1,4 +1,4 @@ from ram.utils import git_suffix -__version__ = "0.18.5" +__version__ = "0.18.6" __version__ += git_suffix(__file__)