From 13cc531c5d1ca09c71fe1170aec7b529ee6180c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Tue, 19 Apr 2022 14:17:26 +0200 Subject: [PATCH 1/3] Add search function and ui refactor --- ram/portal/templates/base.html | 174 +++++++++++++++++ ram/portal/templates/home.html | 181 +----------------- .../templates/{ => includes}/footer.html | 0 .../templates/{ => includes}/login.html | 0 ram/portal/templates/includes/search.html | 5 + ram/portal/templates/page.html | 108 ++--------- ram/portal/templates/search.html | 41 ++++ ram/portal/urls.py | 12 +- ram/portal/views.py | 68 ++++++- ram/ram/settings.py | 2 +- ram/ram/urls.py | 4 +- 11 files changed, 320 insertions(+), 275 deletions(-) create mode 100644 ram/portal/templates/base.html rename ram/portal/templates/{ => includes}/footer.html (100%) rename ram/portal/templates/{ => includes}/login.html (100%) create mode 100644 ram/portal/templates/includes/search.html create mode 100644 ram/portal/templates/search.html diff --git a/ram/portal/templates/base.html b/ram/portal/templates/base.html new file mode 100644 index 0000000..6693210 --- /dev/null +++ b/ram/portal/templates/base.html @@ -0,0 +1,174 @@ +{% load static %} +{% load solo_tags %} +{% load markdown %} +{% get_solo 'portal.SiteConfiguration' as site_conf %} + + + + + + + + + + {{ site_conf.site_name }} + + + + + + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ {% block header %}{% endblock %} +
+
+
+
+
+ +
+ {% block cards %} + {% for r in rolling_stock %} +
+
+ {% for i in r.image.all %} + {% if i.is_thumbnail %}Card image cap{% endif %} + {% endfor %} +
+

{{ r }}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data
Type{{ r.rolling_class.type }}
Company{{ r.rolling_class.company }}
Class{{ r.rolling_class.identifier }}
Road number{{ r.road_number }}
Era{{ r.era }}
Manufacturer{% if r.manufacturer.website %}{% endif %}{{ r.manufacturer }}{% if r.manufacturer.website %}{% endif %} +
Scale{{ r.scale }}
SKU{{ r.sku }}
+ {% if r.decoder %} + + + + + + + + + + + + + + + + +
DCC data
Decoder{{ r.decoder }}
Address{{ r.address }}
+ {% endif %} +
+ Show all data + {% if request.user.is_staff %}Edit{% endif %} +
+ {% if r.tags.all %} +

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

+ {% endif %} +
+ Updated {{ r.updated_time | date:"M d, Y H:m" }} +
+
+
+
+ {% endfor %} + {% endblock %} +
+
+
{% block pagination %}{% endblock %}
+
+ + + {% block extra_content %}{% endblock %} +
+{% include 'includes/footer.html' %} + + + + diff --git a/ram/portal/templates/home.html b/ram/portal/templates/home.html index a6316d0..f249b6d 100644 --- a/ram/portal/templates/home.html +++ b/ram/portal/templates/home.html @@ -1,175 +1,12 @@ -{% load static %} -{% load solo_tags %} +{% extends "base.html" %} {% load markdown %} -{% get_solo 'portal.SiteConfiguration' as site_conf %} - - - - - - - - - {{ site_conf.site_name }} - - - - - - - - - - -
- -
- -
-
-
-
+ {% block header %}

About

{{ site_conf.about | markdown | safe }}

-
-
-
+ {% endblock %} -
-
- -
- {% for r in rolling_stock %} -
-
- {% for i in r.image.all %} - {% if i.is_thumbnail %}Card image cap{% endif %} - {% endfor %} -
-

{{ r }}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Data
Type{{ r.rolling_class.type }}
Company{{ r.rolling_class.company }}
Class{{ r.rolling_class.identifier }}
Road number{{ r.road_number }}
Era{{ r.era }}
-
- - - - - - - - - - - - - - - - - - - -
Model data
Manufacturer{% if r.manufacturer.website %}{% endif %}{{ r.manufacturer }}{% if r.manufacturer.website %}{% endif %} -
Scale{{ r.scale }}
SKU{{ r.sku }}
-
- {% if r.decoder %} -
- - - - - - - - - - - - - - - - -
DCC data
Decoder{{ r.decoder }}
Address{{ r.address }}
-
- {% endif %} -
- - {% if r.decoder %} - - {% endif %} - Show all data - {% if request.user.is_staff %}Edit{% endif %} -
- {% if r.tags.all %} -

Tags: - {% for t in r.tags.all %} - {{ t.name }}{# new line is required #} - {% endfor %} -

- {% endif %} -
- Updated {{ r.updated_time | date:"M d, Y H:m" }} -
-
-
-
- {% endfor %} -
-
-
+ {% block pagination %} {% if rolling_stock.has_other_pages %} {% endif %} -
-
- - -
-{% include 'footer.html' %} - - - + {% endblock %} diff --git a/ram/portal/templates/footer.html b/ram/portal/templates/includes/footer.html similarity index 100% rename from ram/portal/templates/footer.html rename to ram/portal/templates/includes/footer.html diff --git a/ram/portal/templates/login.html b/ram/portal/templates/includes/login.html similarity index 100% rename from ram/portal/templates/login.html rename to ram/portal/templates/includes/login.html diff --git a/ram/portal/templates/includes/search.html b/ram/portal/templates/includes/search.html new file mode 100644 index 0000000..37baf01 --- /dev/null +++ b/ram/portal/templates/includes/search.html @@ -0,0 +1,5 @@ +
+ + +
+ diff --git a/ram/portal/templates/page.html b/ram/portal/templates/page.html index 7a501d1..f36c62d 100644 --- a/ram/portal/templates/page.html +++ b/ram/portal/templates/page.html @@ -1,78 +1,26 @@ -{% load static %} -{% load solo_tags %} +{% extends 'base.html' %} {% load markdown %} -{% get_solo 'portal.SiteConfiguration' as site_conf %} - - - - - - - - - {{ site_conf.site_name }} - - - - - - - - - - -
- -
- -
-
-
-
- + {% block header %}

{{ rolling_stock }}

- {% if rolling_stock.tags.all %} -

Tags: - {% for t in rolling_stock.tags.all %} - {{ t.name }}{# new line is required #} + {% if rolling_stock.tags.all %} +

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

+ {% endif %} + {% endblock %} + {% block cards %} + {% for t in rolling_stock.image.all %} +
+ Rolling stock image +
{% endfor %} -

- {% endif %} -
-
-
-
-
+ {% endblock %} + {% block extra_content %} +
+
-
-
- -
- {% for t in rolling_stock.image.all %} -
- Rolling stock image -
- {% endfor %} -
-
-
-
-{% include 'footer.html' %} - - - + {% endblock %} diff --git a/ram/portal/templates/search.html b/ram/portal/templates/search.html new file mode 100644 index 0000000..bda6965 --- /dev/null +++ b/ram/portal/templates/search.html @@ -0,0 +1,41 @@ +{% extends "base.html" %} + + {% block header %} +

Search: {{ search }}

+

Results found: {{ rolling_stock | length }}

+ {% endblock %} + {% block pagination %} + {% if rolling_stock.has_other_pages %} + + {% endif %} + {% endblock %} diff --git a/ram/portal/urls.py b/ram/portal/urls.py index 9991f27..636f70c 100644 --- a/ram/portal/urls.py +++ b/ram/portal/urls.py @@ -1,8 +1,18 @@ from django.urls import path -from portal.views import GetHome, GetRollingStock +from portal.views import GetHome, GetHomeFiltered, GetRollingStock urlpatterns = [ + path("", GetHome.as_view(), name='index'), path("", GetHome.as_view(), name='index_pagination'), + path( + "search", + GetHomeFiltered.as_view(http_method_names=['post']), + name='index_filtered' + ), + path("search/", + GetHomeFiltered.as_view(), name='index_filtered'), + path("search//", + GetHomeFiltered.as_view(), name='index_filtered_pagination'), path("", GetRollingStock.as_view(), name='rolling_stock'), ] diff --git a/ram/portal/views.py b/ram/portal/views.py index 94b34e6..7c8fef1 100644 --- a/ram/portal/views.py +++ b/ram/portal/views.py @@ -1,16 +1,20 @@ +import operator +from functools import reduce + from django.views import View +from django.http import Http404 +from django.db.models import Q from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from portal.utils import get_site_conf -from roster.models import RollingStock, RollingStockImage +from roster.models import RollingStock class GetHome(View): def get(self, request, page=1): site_conf = get_site_conf() rolling_stock = RollingStock.objects.all() - thumbnails = RollingStockImage.objects.filter(is_thumbnail=True) paginator = Paginator(rolling_stock, site_conf.items_per_page) try: @@ -20,9 +24,59 @@ class GetHome(View): except EmptyPage: rolling_stock = paginator.page(paginator.num_pages) - return render(request, 'home.html', { - 'rolling_stock': rolling_stock, - 'thumbnails': thumbnails + return render(request, "home.html", { + "rolling_stock": rolling_stock + }) + + +class GetHomeFiltered(View): + def run_search(self, request, search, page=1): + # if not hasattr(RollingStock, _filter): + # raise Http404 + site_conf = get_site_conf() + # query = { + # _filter: _value + # } + query = reduce(operator.or_, (Q( + Q(rolling_class__identifier__icontains=s) | + Q(rolling_class__description__icontains=s) | + Q(rolling_class__type__type__icontains=s) | + Q(road_number__icontains=s) | + Q(rolling_class__company__name__icontains=s) | + Q(rolling_class__company__country__icontains=s) | + Q(manufacturer__name__icontains=s) | + Q(scale__scale__icontains=s) | + Q(tags__name__icontains=s) + ) for s in search.split())) + rolling_stock = RollingStock.objects.filter(query) + paginator = Paginator(rolling_stock, site_conf.items_per_page) + + try: + rolling_stock = paginator.page(page) + except PageNotAnInteger: + rolling_stock = paginator.page(1) + except EmptyPage: + rolling_stock = paginator.page(paginator.num_pages) + + return rolling_stock + + def get(self, request, search, page=1): + rolling_stock = self.run_search(request, search, page) + + return render(request, "search.html", { + "search": search, + "rolling_stock": rolling_stock + }) + + def post(self, request, page=1): + search = request.POST.get("search") + if not search: + raise Http404 + rolling_stock = self.run_search(request, search, page) + + return render(request, "search.html", { + "search": search, + "rolling_stock": rolling_stock }) @@ -30,6 +84,6 @@ class GetRollingStock(View): def get(self, request, uuid): rolling_stock = RollingStock.objects.get(uuid=uuid) - return render(request, 'page.html', { - 'rolling_stock': rolling_stock, + return render(request, "page.html", { + "rolling_stock": rolling_stock, }) diff --git a/ram/ram/settings.py b/ram/ram/settings.py index e2fdf24..308b02b 100644 --- a/ram/ram/settings.py +++ b/ram/ram/settings.py @@ -28,7 +28,7 @@ SECRET_KEY = ( # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ["*"] # Application definition diff --git a/ram/ram/urls.py b/ram/ram/urls.py index 493a099..3f27eab 100644 --- a/ram/ram/urls.py +++ b/ram/ram/urls.py @@ -14,18 +14,18 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.conf import settings +from django.shortcuts import redirect from django.conf.urls.static import static from django.contrib import admin from django.urls import include, path from portal.utils import get_site_conf -from portal.views import GetHome site_conf = get_site_conf() admin.site.site_header = site_conf.site_name urlpatterns = [ - path("", GetHome.as_view(), name="index"), + path("", lambda r: redirect("/portal/")), path("portal/", include("portal.urls")), path("ht/", include("health_check.urls")), path("admin/", admin.site.urls), From b925af1e7acc753bf89f0420d77b3ff4880a8b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Tue, 19 Apr 2022 14:25:29 +0200 Subject: [PATCH 2/3] Run black on py --- ram/consist/models.py | 4 +- ram/driver/models.py | 16 ++------ ram/driver/views.py | 17 ++++---- ram/portal/apps.py | 4 +- ram/portal/models.py | 10 ++--- ram/portal/templatetags/markdown.py | 2 +- ram/portal/urls.py | 22 ++++++----- ram/portal/utils.py | 2 +- ram/portal/views.py | 60 +++++++++++++++++------------ ram/ram/__init__.py | 2 +- ram/ram/settings.py | 5 +-- ram/ram/utils.py | 9 +++-- ram/roster/models.py | 28 ++++++++------ 13 files changed, 95 insertions(+), 86 deletions(-) diff --git a/ram/consist/models.py b/ram/consist/models.py index 4db824b..bb9b7ab 100644 --- a/ram/consist/models.py +++ b/ram/consist/models.py @@ -26,9 +26,7 @@ class Consist(models.Model): class ConsistItem(models.Model): consist = models.ForeignKey( - Consist, - on_delete=models.CASCADE, - related_name="consist_item" + Consist, on_delete=models.CASCADE, related_name="consist_item" ) rolling_stock = models.ForeignKey(RollingStock, on_delete=models.CASCADE) order = models.PositiveIntegerField(default=0, blank=False, null=False) diff --git a/ram/driver/models.py b/ram/driver/models.py index ddb7838..18fd6eb 100644 --- a/ram/driver/models.py +++ b/ram/driver/models.py @@ -6,23 +6,16 @@ from solo.models import SingletonModel class DriverConfiguration(SingletonModel): remote_host = models.GenericIPAddressField( - protocol="IPv4", - default="192.168.4.1" + protocol="IPv4", default="192.168.4.1" ) remote_port = models.SmallIntegerField(default=2560) timeout = models.SmallIntegerField(default=250) network = models.GenericIPAddressField( - protocol="IPv4", - default="192.168.4.0", - blank=True, - null=True + protocol="IPv4", default="192.168.4.0", blank=True, null=True ) subnet_mask = models.GenericIPAddressField( - protocol="IPv4", - default="255.255.255.0", - blank=True, - null=True + protocol="IPv4", default="255.255.255.0", blank=True, null=True ) def __str__(self): @@ -31,8 +24,7 @@ class DriverConfiguration(SingletonModel): def clean(self, *args, **kwargs): if self.network: try: - IPv4Network( - "{0}/{1}".format(self.network, self.subnet_mask)) + IPv4Network("{0}/{1}".format(self.network, self.subnet_mask)) except ValueError as e: raise ValidationError(e) super().clean(*args, **kwargs) diff --git a/ram/driver/views.py b/ram/driver/views.py index 1e8cfdc..a23133b 100644 --- a/ram/driver/views.py +++ b/ram/driver/views.py @@ -7,7 +7,7 @@ from rest_framework.response import Response from rest_framework.permissions import ( IsAuthenticated, BasePermission, - SAFE_METHODS + SAFE_METHODS, ) from ram.parsers import PlainTextParser @@ -40,16 +40,15 @@ class Firewall(BasePermission): if not config.network: return request.method in SAFE_METHODS - x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') + x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR") if x_forwarded_for: - ip = IPv4Address(x_forwarded_for.split(',')[0]) + ip = IPv4Address(x_forwarded_for.split(",")[0]) else: ip = IPv4Address(request.META.get("REMOTE_ADDR")) - network = IPv4Network("{0}/{1}".format( - config.network, - config.subnet_mask - )) + network = IPv4Network( + "{0}/{1}".format(config.network, config.subnet_mask) + ) # accept IP configured is settings or localhost if ip in network or ip in IPv4Network("127.0.0.0/8"): @@ -101,6 +100,7 @@ class Function(APIView): """ Send "Function" commands to a valid DCC address """ + permission_classes = [IsAuthenticated | Firewall] def put(self, request, address): @@ -117,6 +117,7 @@ class Cab(APIView): """ Send "Cab" commands to a valid DCC address """ + permission_classes = [IsAuthenticated | Firewall] def put(self, request, address): @@ -132,6 +133,7 @@ class Infra(APIView): """ Send "Infra" commands to a valid DCC address """ + permission_classes = [IsAuthenticated | Firewall] def put(self, request): @@ -147,6 +149,7 @@ class Emergency(APIView): """ Send an "Emergency" stop, no matter the HTTP method used """ + permission_classes = [IsAuthenticated | Firewall] def put(self, request): diff --git a/ram/portal/apps.py b/ram/portal/apps.py index 781ac2f..d912bf9 100644 --- a/ram/portal/apps.py +++ b/ram/portal/apps.py @@ -2,5 +2,5 @@ from django.apps import AppConfig class PortalConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'portal' + default_auto_field = "django.db.models.BigAutoField" + name = "portal" diff --git a/ram/portal/models.py b/ram/portal/models.py index 583e911..8732a33 100644 --- a/ram/portal/models.py +++ b/ram/portal/models.py @@ -7,14 +7,14 @@ from solo.models import SingletonModel class SiteConfiguration(SingletonModel): site_name = models.CharField( - max_length=256, - default="Railroad Assets Manager") + max_length=256, default="Railroad Assets Manager" + ) site_author = models.CharField(max_length=256, blank=True) about = models.TextField(blank=True) items_per_page = models.CharField( - max_length=2, choices=[ - (str(x * 3), str(x * 3)) for x in range(2, 11)], - default='6' + max_length=2, + choices=[(str(x * 3), str(x * 3)) for x in range(2, 11)], + default="6", ) footer = models.TextField(blank=True) footer_extended = models.TextField(blank=True) diff --git a/ram/portal/templatetags/markdown.py b/ram/portal/templatetags/markdown.py index 690b818..00dcee6 100644 --- a/ram/portal/templatetags/markdown.py +++ b/ram/portal/templatetags/markdown.py @@ -9,4 +9,4 @@ register = template.Library() @register.filter @stringfilter def markdown(value): - return md.markdown(value, extensions=['markdown.extensions.fenced_code']) + return md.markdown(value, extensions=["markdown.extensions.fenced_code"]) diff --git a/ram/portal/urls.py b/ram/portal/urls.py index 636f70c..c106df8 100644 --- a/ram/portal/urls.py +++ b/ram/portal/urls.py @@ -3,16 +3,20 @@ from django.urls import path from portal.views import GetHome, GetHomeFiltered, GetRollingStock urlpatterns = [ - path("", GetHome.as_view(), name='index'), - path("", GetHome.as_view(), name='index_pagination'), + path("", GetHome.as_view(), name="index"), + path("", GetHome.as_view(), name="index_pagination"), path( "search", - GetHomeFiltered.as_view(http_method_names=['post']), - name='index_filtered' + GetHomeFiltered.as_view(http_method_names=["post"]), + name="index_filtered", ), - path("search/", - GetHomeFiltered.as_view(), name='index_filtered'), - path("search//", - GetHomeFiltered.as_view(), name='index_filtered_pagination'), - path("", GetRollingStock.as_view(), name='rolling_stock'), + path( + "search/", GetHomeFiltered.as_view(), name="index_filtered" + ), + path( + "search//", + GetHomeFiltered.as_view(), + name="index_filtered_pagination", + ), + path("", GetRollingStock.as_view(), name="rolling_stock"), ] diff --git a/ram/portal/utils.py b/ram/portal/utils.py index b14b91b..0c2b6cb 100644 --- a/ram/portal/utils.py +++ b/ram/portal/utils.py @@ -2,5 +2,5 @@ from django.apps import apps def get_site_conf(): - SiteConfiguration = apps.get_model('portal', 'SiteConfiguration') + SiteConfiguration = apps.get_model("portal", "SiteConfiguration") return SiteConfiguration.get_solo() diff --git a/ram/portal/views.py b/ram/portal/views.py index 7c8fef1..5f393af 100644 --- a/ram/portal/views.py +++ b/ram/portal/views.py @@ -24,9 +24,7 @@ class GetHome(View): except EmptyPage: rolling_stock = paginator.page(paginator.num_pages) - return render(request, "home.html", { - "rolling_stock": rolling_stock - }) + return render(request, "home.html", {"rolling_stock": rolling_stock}) class GetHomeFiltered(View): @@ -37,17 +35,23 @@ class GetHomeFiltered(View): # query = { # _filter: _value # } - query = reduce(operator.or_, (Q( - Q(rolling_class__identifier__icontains=s) | - Q(rolling_class__description__icontains=s) | - Q(rolling_class__type__type__icontains=s) | - Q(road_number__icontains=s) | - Q(rolling_class__company__name__icontains=s) | - Q(rolling_class__company__country__icontains=s) | - Q(manufacturer__name__icontains=s) | - Q(scale__scale__icontains=s) | - Q(tags__name__icontains=s) - ) for s in search.split())) + query = reduce( + operator.or_, + ( + Q( + Q(rolling_class__identifier__icontains=s) + | Q(rolling_class__description__icontains=s) + | Q(rolling_class__type__type__icontains=s) + | Q(road_number__icontains=s) + | Q(rolling_class__company__name__icontains=s) + | Q(rolling_class__company__country__icontains=s) + | Q(manufacturer__name__icontains=s) + | Q(scale__scale__icontains=s) + | Q(tags__name__icontains=s) + ) + for s in search.split() + ), + ) rolling_stock = RollingStock.objects.filter(query) paginator = Paginator(rolling_stock, site_conf.items_per_page) @@ -63,10 +67,11 @@ class GetHomeFiltered(View): def get(self, request, search, page=1): rolling_stock = self.run_search(request, search, page) - return render(request, "search.html", { - "search": search, - "rolling_stock": rolling_stock - }) + return render( + request, + "search.html", + {"search": search, "rolling_stock": rolling_stock}, + ) def post(self, request, page=1): search = request.POST.get("search") @@ -74,16 +79,21 @@ class GetHomeFiltered(View): raise Http404 rolling_stock = self.run_search(request, search, page) - return render(request, "search.html", { - "search": search, - "rolling_stock": rolling_stock - }) + return render( + request, + "search.html", + {"search": search, "rolling_stock": rolling_stock}, + ) class GetRollingStock(View): def get(self, request, uuid): rolling_stock = RollingStock.objects.get(uuid=uuid) - return render(request, "page.html", { - "rolling_stock": rolling_stock, - }) + return render( + request, + "page.html", + { + "rolling_stock": rolling_stock, + }, + ) diff --git a/ram/ram/__init__.py b/ram/ram/__init__.py index 9db4f2e..d7eb4b5 100644 --- a/ram/ram/__init__.py +++ b/ram/ram/__init__.py @@ -1,4 +1,4 @@ from ram.utils import git_suffix -__version__ = '0.0.1' +__version__ = "0.0.1" __version__ += git_suffix(__file__) diff --git a/ram/ram/settings.py b/ram/ram/settings.py index 308b02b..74dd8bf 100644 --- a/ram/ram/settings.py +++ b/ram/ram/settings.py @@ -152,10 +152,7 @@ DECODER_INTERFACES = [ (5, "Next18/Next18S"), ] -MANUFACTURER_TYPES = [ - ("model", "Model"), - ("real", "Real") -] +MANUFACTURER_TYPES = [("model", "Model"), ("real", "Real")] ROLLING_STOCK_TYPES = [ ("engine", "Engine"), diff --git a/ram/ram/utils.py b/ram/ram/utils.py index 47266fb..98a9fb9 100644 --- a/ram/ram/utils.py +++ b/ram/ram/utils.py @@ -11,13 +11,14 @@ def git_suffix(fname): """ try: gh = subprocess.check_output( - ['git', 'rev-parse', '--short', 'HEAD'], - stderr=open(os.devnull, 'w')).strip() - gh = "-git" + gh.decode() if gh else '' + ["git", "rev-parse", "--short", "HEAD"], + stderr=open(os.devnull, "w"), + ).strip() + gh = "-git" + gh.decode() if gh else "" except Exception: # trapping everything on purpose; git may not be installed or it # may not work properly - gh = '' + gh = "" return gh diff --git a/ram/roster/models.py b/ram/roster/models.py index 15cea70..27fc471 100644 --- a/ram/roster/models.py +++ b/ram/roster/models.py @@ -2,6 +2,7 @@ import os from uuid import uuid4 from django.db import models from django.urls import reverse + # from django.core.files.storage import FileSystemStorage # from django.dispatch import receiver @@ -32,8 +33,11 @@ class RollingClass(models.Model): ) description = models.CharField(max_length=256, blank=True) manufacturer = models.ForeignKey( - Manufacturer, on_delete=models.CASCADE, null=True, blank=True, - limit_choices_to={"category": "real"} + Manufacturer, + on_delete=models.CASCADE, + null=True, + blank=True, + limit_choices_to={"category": "real"}, ) class Meta: @@ -74,8 +78,11 @@ class RollingStock(models.Model): ) road_number = models.CharField(max_length=128, unique=False) manufacturer = models.ForeignKey( - Manufacturer, on_delete=models.CASCADE, null=True, blank=True, - limit_choices_to={"category": "model"} + Manufacturer, + on_delete=models.CASCADE, + null=True, + blank=True, + limit_choices_to={"category": "model"}, ) scale = models.ForeignKey(Scale, on_delete=models.CASCADE) sku = models.CharField(max_length=32, blank=True) @@ -112,9 +119,7 @@ class RollingStock(models.Model): class RollingStockDocument(models.Model): rolling_stock = models.ForeignKey( - RollingStock, - on_delete=models.CASCADE, - related_name="document" + RollingStock, on_delete=models.CASCADE, related_name="document" ) description = models.CharField(max_length=128, blank=True) file = models.FileField(upload_to="files/", null=True, blank=True) @@ -131,9 +136,7 @@ class RollingStockDocument(models.Model): class RollingStockImage(models.Model): rolling_stock = models.ForeignKey( - RollingStock, - on_delete=models.CASCADE, - related_name="image" + RollingStock, on_delete=models.CASCADE, related_name="image" ) image = models.ImageField(upload_to="images/", null=True, blank=True) is_thumbnail = models.BooleanField() @@ -149,7 +152,8 @@ class RollingStockImage(models.Model): def save(self, **kwargs): if self.is_thumbnail: RollingStockImage.objects.filter( - rolling_stock=self.rolling_stock).update(is_thumbnail=False) + rolling_stock=self.rolling_stock + ).update(is_thumbnail=False) super().save(**kwargs) @@ -159,7 +163,7 @@ class RollingStockProperty(models.Model): on_delete=models.CASCADE, related_name="property", null=False, - blank=False + blank=False, ) property = models.ForeignKey(Property, on_delete=models.CASCADE) value = models.CharField(max_length=256) From 4326582ef6700e69ba071e31a4d0ea7903d52919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Tue, 19 Apr 2022 14:38:44 +0200 Subject: [PATCH 3/3] Fix html indentation --- ram/portal/templates/base.html | 264 ++++++------- ram/portal/templates/includes/footer.html | 32 +- ram/portal/templates/page.html | 458 +++++++++++----------- 3 files changed, 373 insertions(+), 381 deletions(-) diff --git a/ram/portal/templates/base.html b/ram/portal/templates/base.html index 6693210..8b62c38 100644 --- a/ram/portal/templates/base.html +++ b/ram/portal/templates/base.html @@ -9,15 +9,11 @@ - - + + {{ site_conf.site_name }} - - - - - -
- -
- -
-
- -
-
-
-
- {% block header %}{% endblock %} -
-
-
-
-
- -
- {% block cards %} - {% for r in rolling_stock %} -
-
- {% for i in r.image.all %} - {% if i.is_thumbnail %}Card image cap{% endif %} - {% endfor %} -
-

{{ r }}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Data
Type{{ r.rolling_class.type }}
Company{{ r.rolling_class.company }}
Class{{ r.rolling_class.identifier }}
Road number{{ r.road_number }}
Era{{ r.era }}
Manufacturer{% if r.manufacturer.website %}{% endif %}{{ r.manufacturer }}{% if r.manufacturer.website %}{% endif %} -
Scale{{ r.scale }}
SKU{{ r.sku }}
- {% if r.decoder %} - - - - - - - - - - - - - - - - -
DCC data
Decoder{{ r.decoder }}
Address{{ r.address }}
- {% endif %} -
- Show all data - {% if request.user.is_staff %}Edit{% endif %} -
- {% if r.tags.all %} -

Tags: - {% for t in r.tags.all %} - {{ t.name }}{# new line is required #} - {% endfor %} -

- {% endif %} -
- Updated {{ r.updated_time | date:"M d, Y H:m" }} -
+ +
+
+
-
- {% endfor %} - {% endblock %} +
-
-
{% block pagination %}{% endblock %}
-
-
-
- {% block extra_content %}{% endblock %} -
-{% include 'includes/footer.html' %} - - +
+
+
+ {% block header %}{% endblock %} +
+
+
+
+
+ +
+ {% block cards %} + {% for r in rolling_stock %} +
+
+ {% for i in r.image.all %} + {% if i.is_thumbnail %}Card image cap{% endif %} + {% endfor %} +
+

{{ r }}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data
Type{{ r.rolling_class.type }}
Company{{ r.rolling_class.company }}
Class{{ r.rolling_class.identifier }}
Road number{{ r.road_number }}
Era{{ r.era }}
Manufacturer{% if r.manufacturer.website %}{% endif %}{{ r.manufacturer }}{% if r.manufacturer.website %}{% endif %} +
Scale{{ r.scale }}
SKU{{ r.sku }}
+ {% if r.decoder %} + + + + + + + + + + + + + + + + +
DCC data
Decoder{{ r.decoder }}
Address{{ r.address }}
+ {% endif %} +
+ Show all data + {% if request.user.is_staff %}Edit{% endif %} +
+ {% if r.tags.all %} +

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

+ {% endif %} +
+ Updated {{ r.updated_time | date:"M d, Y H:m" }} +
+
+
+
+ {% endfor %} + {% endblock %} +
+
+
{% block pagination %}{% endblock %}
+
+ {% block extra_content %}{% endblock %} + + {% include 'includes/footer.html' %} + + diff --git a/ram/portal/templates/includes/footer.html b/ram/portal/templates/includes/footer.html index 18301f1..2334d13 100644 --- a/ram/portal/templates/includes/footer.html +++ b/ram/portal/templates/includes/footer.html @@ -1,20 +1,20 @@ {% load markdown %} -
-
-

- Back to top -

-
diff --git a/ram/portal/templates/page.html b/ram/portal/templates/page.html index f36c62d..4e2c054 100644 --- a/ram/portal/templates/page.html +++ b/ram/portal/templates/page.html @@ -18,233 +18,233 @@ {% endfor %} {% endblock %} - {% block extra_content %} -
-
-
- - -
-
- {% endblock %} + + {% endblock %}