mirror of
https://github.com/daniviga/django-ram.git
synced 2025-08-04 13:17:50 +02:00
Add support for manufacturer filters
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
from urllib.parse import quote_plus
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.dispatch.dispatcher import receiver
|
from django.dispatch.dispatcher import receiver
|
||||||
@@ -34,6 +36,9 @@ class Manufacturer(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def safe_name(self):
|
||||||
|
return quote_plus(self.name, safe="&")
|
||||||
|
|
||||||
def logo_thumbnail(self):
|
def logo_thumbnail(self):
|
||||||
return get_image_preview(self.logo.url)
|
return get_image_preview(self.logo.url)
|
||||||
|
|
||||||
@@ -56,6 +61,9 @@ class Company(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def safe_name(self):
|
||||||
|
return quote_plus(self.name, safe="&")
|
||||||
|
|
||||||
def logo_thumbnail(self):
|
def logo_thumbnail(self):
|
||||||
return get_image_preview(self.logo.url)
|
return get_image_preview(self.logo.url)
|
||||||
|
|
||||||
|
@@ -88,6 +88,15 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{% url 'scales' %}">Scales</a>
|
<a class="nav-link" href="{% url 'scales' %}">Scales</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
Manufacturers
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
||||||
|
<li><a class="dropdown-item" href="{% url 'manufacturers' category='model' %}">Models</a></li>
|
||||||
|
<li><a class="dropdown-item" href="{% url 'manufacturers' category='real' %}">Real</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
{% show_menu %}
|
{% show_menu %}
|
||||||
</ul>
|
</ul>
|
||||||
{% include 'includes/search.html' %}
|
{% include 'includes/search.html' %}
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Company</th>
|
<th scope="row">Company</th>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'filtered' _filter="company" search=r.rolling_class.company %}"><abbr title="{{ r.rolling_class.company.extended_name }}">{{ r.rolling_class.company }}</abbr></a>
|
<a href="{% url 'filtered' _filter="company" search=r.rolling_class.company.safe_name %}"><abbr title="{{ r.rolling_class.company.extended_name }}">{{ r.rolling_class.company }}</abbr></a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -52,7 +52,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="35%" scope="row">Manufacturer</th>
|
<th width="35%" scope="row">Manufacturer</th>
|
||||||
<td>{{ r.manufacturer|default_if_none:"" }}{% if r.manufacturer.website %} <a href="{{ r.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}</td>
|
<td>{%if r.manufacturer %}
|
||||||
|
<a href="{% url 'filtered' _filter="manufacturer" search=r.manufacturer.safe_name %}">{{ r.manufacturer }}{% if r.manufacturer.website %}</a> <a href="{{ r.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}
|
||||||
|
{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Scale</th>
|
<th scope="row">Scale</th>
|
||||||
|
@@ -73,7 +73,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="35%" scope="row">Manufacturer</th>
|
<th width="35%" scope="row">Manufacturer</th>
|
||||||
<td>{{ r.rolling_stock.manufacturer|default_if_none:"" }}{% if r.rolling_stock.manufacturer.website %} <a href="{{ r.rolling_stock.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}</td>
|
<td>{%if r.rolling_stock.manufacturer %}
|
||||||
|
<a href="{% url 'filtered' _filter="manufacturer" search=r.rolling_stock.manufacturer.safe_name %}">{{ r.rolling_stock.manufacturer }}{% if r.rolling_stock.manufacturer.website %}</a> <a href="{{ r.rolling_stock.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}
|
||||||
|
{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Scale</th>
|
<th scope="row">Scale</th>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{% if menu %}
|
{% if menu %}
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
More ...
|
Articles
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
<ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
|
||||||
{% for m in menu %}
|
{% for m in menu %}
|
||||||
|
83
ram/portal/templates/manufacturers.html
Normal file
83
ram/portal/templates/manufacturers.html
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
{% extends "cards.html" %}
|
||||||
|
|
||||||
|
{% block cards %}
|
||||||
|
{% for m in manufacturers %}
|
||||||
|
<div class="col">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text" style="position: relative;">
|
||||||
|
<strong>{{ m.name }}</strong>
|
||||||
|
</p>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" scope="row">Manufacturer</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% if m.logo %}
|
||||||
|
<tr>
|
||||||
|
<th width="35%" scope="row">Logo</th>
|
||||||
|
<td><img style="max-height: 48px" src="{{ m.logo.url }}" /></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if m.website %}
|
||||||
|
<tr>
|
||||||
|
<th width="35%" scope="row">Website</th>
|
||||||
|
<td><a href="{{ m.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
<tr>
|
||||||
|
<th width="35%" scope="row">Category</th>
|
||||||
|
<td>{{ m.category | title }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-grid gap-2 mb-1 d-md-block">
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="manufacturer" search=m.safe_name %}">Show all rolling stock</a>
|
||||||
|
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_manufacturer_change' m.pk %}">Edit</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block pagination %}
|
||||||
|
{% if manufacturers.has_other_pages %}
|
||||||
|
<nav aria-label="Page navigation example">
|
||||||
|
<ul class="pagination justify-content-center mt-4 mb-0">
|
||||||
|
{% if manufacturers.has_previous %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{% url 'manufacturers_pagination' category=category page=manufacturers.previous_page_number %}#rolling-stock" tabindex="-1">Previous</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="page-item disabled">
|
||||||
|
<span class="page-link">Previous</span>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% for i in page_range %}
|
||||||
|
{% if manufacturers.number == i %}
|
||||||
|
<li class="page-item active">
|
||||||
|
<span class="page-link">{{ i }}</span></span>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
{% if i == manufacturers.paginator.ELLIPSIS %}
|
||||||
|
<li class="page-item"><span class="page-link">{{ i }}</span></li>
|
||||||
|
{% else %}
|
||||||
|
<li class="page-item"><a class="page-link" href="{% url 'manufacturers_pagination' category=category page=i %}#rolling-stock">{{ i }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% if manufacturers.has_next %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{% url 'manufacturers_pagination' category=category page=manufacturers.next_page_number %}#rolling-stock" tabindex="-1">Next</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="page-item disabled">
|
||||||
|
<span class="page-link">Next</span>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
@@ -70,7 +70,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Company</th>
|
<th scope="row">Company</th>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'filtered' _filter="company" search=rolling_stock.rolling_class.company %}"><abbr title="{{ rolling_stock.rolling_class.company.extended_name }}">{{ rolling_stock.rolling_class.company }}</abbr></a>
|
<a href="{% url 'filtered' _filter="company" search=rolling_stock.rolling_class.company.safe_name %}"><abbr title="{{ rolling_stock.rolling_class.company.extended_name }}">{{ rolling_stock.rolling_class.company }}</abbr></a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -96,7 +96,9 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="35%" scope="row">Manufacturer</th>
|
<th width="35%" scope="row">Manufacturer</th>
|
||||||
<td>{{ rolling_stock.manufacturer|default_if_none:"" }}{% if rolling_stock.manufacturer.website %} <a href="{{ rolling_stock.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}</td>
|
<td>{%if rolling_stock.manufacturer %}
|
||||||
|
<a href="{% url 'filtered' _filter="manufacturer" search=rolling_stock.manufacturer.safe_name %}">{{ rolling_stock.manufacturer }}{% if rolling_stock.manufacturer.website %}</a> <a href="{{ rolling_stock.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}
|
||||||
|
{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Scale</th>
|
<th scope="row">Scale</th>
|
||||||
@@ -144,11 +146,13 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="35%" scope="row">Manufacturer</th>
|
<th width="35%" scope="row">Manufacturer</th>
|
||||||
<td>{{ rolling_stock.manufacturer|default_if_none:"" }}{% if rolling_stock.manufacturer.website %} <a href="{{ rolling_stock.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}</td>
|
<td>{%if rolling_stock.manufacturer %}
|
||||||
|
<a href="{% url 'filtered' _filter="manufacturer" search=rolling_stock.manufacturer.safe_name %}">{{ rolling_stock.manufacturer }}{% if rolling_stock.manufacturer.website %}</a> <a href="{{ rolling_stock.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}
|
||||||
|
{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Scale</th>
|
<th scope="row">Scale</th>
|
||||||
<td><abbr title="{{ rolling_stock.scale.ratio }} - {{ rolling_stock.scale.tracks }}">{{ rolling_stock.scale }}</abbr></td>
|
<td><a href="{% url 'filtered' _filter="scale" search=rolling_stock.scale %}"><abbr title="{{ rolling_stock.scale.ratio }} - {{ rolling_stock.scale.tracks }}">{{ rolling_stock.scale }}</abbr></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">SKU</th>
|
<th scope="row">SKU</th>
|
||||||
@@ -204,7 +208,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Company</th>
|
<th scope="row">Company</th>
|
||||||
<td>{{ rolling_stock.rolling_class.company }} ({{ rolling_stock.rolling_class.company.extended_name }})</td>
|
<td>
|
||||||
|
<a href="{% url 'filtered' _filter="company" search=rolling_stock.rolling_class.company.safe_name %}">{{ rolling_stock.rolling_class.company }}</a> ({{ rolling_stock.rolling_class.company.extended_name }})
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Country</th>
|
<th scope="row">Country</th>
|
||||||
@@ -212,7 +218,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Manufacturer</th>
|
<th scope="row">Manufacturer</th>
|
||||||
<td>{{ rolling_stock.rolling_class.manufacturer|default_if_none:"" }}</td>
|
<td>{%if rolling_stock.rolling_class.manufacturer %}
|
||||||
|
<a href="{% url 'filtered' _filter="manufacturer" search=rolling_stock.rolling_class.manufacturer.safe_name %}">{{ rolling_stock.rolling_class.manufacturer }}{% if rolling_stock.rolling_class.manufacturer.website %}</a> <a href="{{ rolling_stock.rolling_class.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}
|
||||||
|
{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -8,6 +8,7 @@ from portal.views import (
|
|||||||
GetConsist,
|
GetConsist,
|
||||||
Consists,
|
Consists,
|
||||||
Companies,
|
Companies,
|
||||||
|
Manufacturers,
|
||||||
Scales,
|
Scales,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,6 +41,16 @@ urlpatterns = [
|
|||||||
Companies.as_view(),
|
Companies.as_view(),
|
||||||
name="companies_pagination",
|
name="companies_pagination",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"manufacturers/<str:category>",
|
||||||
|
Manufacturers.as_view(),
|
||||||
|
name="manufacturers"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"manufacturers/<str:category>/<int:page>",
|
||||||
|
Manufacturers.as_view(),
|
||||||
|
name="manufacturers_pagination",
|
||||||
|
),
|
||||||
path("scales", Scales.as_view(), name="scales"),
|
path("scales", Scales.as_view(), name="scales"),
|
||||||
path("scales/<int:page>", Scales.as_view(), name="scales_pagination"),
|
path("scales/<int:page>", Scales.as_view(), name="scales_pagination"),
|
||||||
path(
|
path(
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import operator
|
import operator
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
from urllib.parse import quote_plus, unquote_plus
|
||||||
|
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
@@ -12,7 +13,7 @@ from portal.utils import get_site_conf
|
|||||||
from portal.models import Flatpage
|
from portal.models import Flatpage
|
||||||
from roster.models import RollingStock
|
from roster.models import RollingStock
|
||||||
from consist.models import Consist
|
from consist.models import Consist
|
||||||
from metadata.models import Company, Scale
|
from metadata.models import Company, Manufacturer, Scale
|
||||||
|
|
||||||
|
|
||||||
def order_by_fields():
|
def order_by_fields():
|
||||||
@@ -81,6 +82,11 @@ class GetHomeFiltered(View):
|
|||||||
Q(rolling_class__company__name__icontains=search)
|
Q(rolling_class__company__name__icontains=search)
|
||||||
| Q(rolling_class__company__extended_name__icontains=search)
|
| Q(rolling_class__company__extended_name__icontains=search)
|
||||||
)
|
)
|
||||||
|
elif _filter == "manufacturer":
|
||||||
|
query = Q(
|
||||||
|
Q(manufacturer__name__iexact=search)
|
||||||
|
| Q(rolling_class__manufacturer__name__icontains=search)
|
||||||
|
)
|
||||||
elif _filter == "scale":
|
elif _filter == "scale":
|
||||||
query = Q(scale__scale__iexact=search)
|
query = Q(scale__scale__iexact=search)
|
||||||
elif _filter == "tag":
|
elif _filter == "tag":
|
||||||
@@ -103,16 +109,19 @@ class GetHomeFiltered(View):
|
|||||||
return rolling_stock, matches, page_range
|
return rolling_stock, matches, page_range
|
||||||
|
|
||||||
def get(self, request, search, _filter="search", page=1):
|
def get(self, request, search, _filter="search", page=1):
|
||||||
|
search_unsafe = unquote_plus(search) # expected to be encoded
|
||||||
rolling_stock, matches, page_range = self.run_search(
|
rolling_stock, matches, page_range = self.run_search(
|
||||||
request, search, _filter, page
|
request, search_unsafe, _filter, page
|
||||||
)
|
)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"search.html",
|
"search.html",
|
||||||
{
|
{
|
||||||
"title": "{0}: {1}".format(_filter.capitalize(), search),
|
"title": "{0}: {1}".format(
|
||||||
|
_filter.capitalize(), search_unsafe),
|
||||||
"search": search,
|
"search": search,
|
||||||
|
"search_unsafe": search_unsafe,
|
||||||
"filter": _filter,
|
"filter": _filter,
|
||||||
"matches": matches,
|
"matches": matches,
|
||||||
"rolling_stock": rolling_stock,
|
"rolling_stock": rolling_stock,
|
||||||
@@ -122,6 +131,8 @@ class GetHomeFiltered(View):
|
|||||||
|
|
||||||
def post(self, request, _filter="search", page=1):
|
def post(self, request, _filter="search", page=1):
|
||||||
search = request.POST.get("search")
|
search = request.POST.get("search")
|
||||||
|
# search = quote_plus(request.POST.get("search"), safe="&")
|
||||||
|
# search_unsafe = unquote_plus(search)
|
||||||
if not search:
|
if not search:
|
||||||
raise Http404
|
raise Http404
|
||||||
rolling_stock, matches, page_range = self.run_search(
|
rolling_stock, matches, page_range = self.run_search(
|
||||||
@@ -134,6 +145,7 @@ class GetHomeFiltered(View):
|
|||||||
{
|
{
|
||||||
"title": "{0}: {1}".format(_filter.capitalize(), search),
|
"title": "{0}: {1}".format(_filter.capitalize(), search),
|
||||||
"search": search,
|
"search": search,
|
||||||
|
# "search_unsafe": search_unsafe,
|
||||||
"filter": _filter,
|
"filter": _filter,
|
||||||
"matches": matches,
|
"matches": matches,
|
||||||
"rolling_stock": rolling_stock,
|
"rolling_stock": rolling_stock,
|
||||||
@@ -230,6 +242,31 @@ class GetConsist(View):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Manufacturers(View):
|
||||||
|
def get(self, request, category, page=1):
|
||||||
|
site_conf = get_site_conf()
|
||||||
|
if category not in ("real", "model"):
|
||||||
|
raise Http404
|
||||||
|
manufacturers = Manufacturer.objects.filter(category=category)
|
||||||
|
|
||||||
|
paginator = Paginator(manufacturers, site_conf.items_per_page)
|
||||||
|
manufacturers = paginator.get_page(page)
|
||||||
|
page_range = paginator.get_elided_page_range(
|
||||||
|
manufacturers.number, on_each_side=2, on_ends=1
|
||||||
|
)
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"manufacturers.html",
|
||||||
|
{
|
||||||
|
"title": "Manufacturers",
|
||||||
|
"category": category,
|
||||||
|
"manufacturers": manufacturers,
|
||||||
|
"page_range": page_range,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Companies(View):
|
class Companies(View):
|
||||||
def get(self, request, page=1):
|
def get(self, request, page=1):
|
||||||
site_conf = get_site_conf()
|
site_conf = get_site_conf()
|
||||||
|
Reference in New Issue
Block a user