Improve sorting and extend search to magazines

This commit is contained in:
2025-12-21 22:56:45 +01:00
parent c539255bf9
commit 5a71dc36fa
8 changed files with 126 additions and 61 deletions

View File

@@ -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",
]
},
),
]

View File

@@ -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}
)

View File

@@ -13,13 +13,13 @@
<strong>{{ d.item }}</strong>
<a class="stretched-link" href="{{ d.item.get_absolute_url }}"></a>
</p>
{% if d.item.tags.all %}
<p class="card-text"><small>Tags:</small>
{% for t in d.item.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
{{ t.name }}</a>{# new line is required #}
{% empty %}
<span class="badge rounded-pill bg-secondary"><i class="bi bi-ban"></i></span>
{% endfor %}
</p>
{% endif %}
<table class="table table-striped">
<thead>
<tr>

View File

@@ -14,13 +14,13 @@
<strong>{{ d.item }}</strong>
<a class="stretched-link" href="{{ d.item.get_absolute_url }}"></a>
</p>
{% if d.item.tags.all %}
<p class="card-text"><small>Tags:</small>
{% for t in d.item.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
{{ t.name }}</a>{# new line is required #}
{% empty %}
<span class="badge rounded-pill bg-secondary"><i class="bi bi-ban"></i></span>
{% endfor %}
</p>
{% endif %}
<table class="table table-striped">
<thead>
<tr>

View File

@@ -31,13 +31,13 @@
<strong>{{ d.item }}</strong>
<a class="stretched-link" href="{{ d.item.get_absolute_url }}"></a>
</p>
{% if d.item.tags.all %}
<p class="card-text"><small>Tags:</small>
{% for t in d.item.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
{{ t.name }}</a>{# new line is required #}
{% empty %}
<span class="badge rounded-pill bg-secondary"><i class="bi bi-ban"></i></span>
{% endfor %}
</p>
{% endif %}
<table class="table table-striped">
<thead>
<tr>

View File

@@ -14,13 +14,13 @@
<strong>{{ d.item }}</strong>
<a class="stretched-link" href="{{ d.item.get_absolute_url }}"></a>
</p>
{% if d.item.tags.all %}
<p class="card-text"><small>Tags:</small>
{% for t in d.item.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
{{ t.name }}</a>{# new line is required #}
{% empty %}
<span class="badge rounded-pill bg-secondary"><i class="bi bi-ban"></i></span>
{% endfor %}
</p>
{% endif %}
<table class="table table-striped">
<thead>
<tr>

View File

@@ -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",

View File

@@ -1,4 +1,4 @@
from ram.utils import git_suffix
__version__ = "0.18.5"
__version__ = "0.18.6"
__version__ += git_suffix(__file__)