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/templates/base.html b/ram/portal/templates/base.html
new file mode 100644
index 0000000..8b62c38
--- /dev/null
+++ b/ram/portal/templates/base.html
@@ -0,0 +1,166 @@
+{% 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 %}

{% 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 %}
+
+ {% 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/footer.html b/ram/portal/templates/footer.html
deleted file mode 100644
index 18301f1..0000000
--- a/ram/portal/templates/footer.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% load markdown %}
-
-
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 %}

{% 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 }} |
-
-
-
-
- {% 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/includes/footer.html b/ram/portal/templates/includes/footer.html
new file mode 100644
index 0000000..2334d13
--- /dev/null
+++ b/ram/portal/templates/includes/footer.html
@@ -0,0 +1,20 @@
+{% load markdown %}
+
+
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..4e2c054 100644
--- a/ram/portal/templates/page.html
+++ b/ram/portal/templates/page.html
@@ -1,318 +1,250 @@
-{% 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 #}
- {% endfor %}
-
- {% endif %}
-
-
-
-
-
-
-
-
-
-
-
-
- Data |
-
-
-
-
- Type |
- {{ rolling_stock.rolling_class.type }} |
-
-
- Company |
- {{ rolling_stock.rolling_class.company }} |
-
-
- Class |
- {{ rolling_stock.rolling_class.identifier }} |
-
-
- Road number |
- {{ rolling_stock.road_number }} |
-
-
- Era |
- {{ rolling_stock.era }} |
-
-
-
-
- {% if rolling_stock.decoder %}
-
-
-
- DCC data |
-
-
-
-
- Decoder |
- {{ rolling_stock.decoder }} |
-
-
- Address |
- {{ rolling_stock.address }} |
-
-
-
- {% endif %}
-
-
-
-
-
- Model data |
-
-
-
-
- Manufacturer |
- {% if rolling_stock.manufacturer.website %}{% endif %}{{ rolling_stock.manufacturer }}{% if rolling_stock.manufacturer.website %}{% endif %}
- |
-
- Scale |
- {{ rolling_stock.scale }} |
-
-
- SKU |
- {{ rolling_stock.sku }} |
-
-
- ERA |
- {{ rolling_stock.era }} |
-
-
- Production year |
- {{ rolling_stock.production_year | default_if_none:"" }} |
-
-
- Purchase date |
- {{ rolling_stock.purchase_date | default_if_none:"" }} |
-
-
-
-
-
-
-
-
- Class data |
-
-
-
-
- Class |
- {{ rolling_stock.rolling_class }} |
-
-
- Type |
- {{ rolling_stock.rolling_class.type }} |
-
-
- Company |
- {{ rolling_stock.rolling_class.company }} ({{ rolling_stock.rolling_class.company.extended_name }}) |
-
-
- Country |
- {{ rolling_stock.rolling_class.company.country.name }} |
-
-
- Manufacturer |
- {{ rolling_stock.rolling_class.manufacturer }} |
-
-
-
-
-
-
-
-
- DCC data |
-
-
-
-
- Name |
- {{ rolling_stock.decoder.name }} |
-
-
- Manufacturer |
- {{ rolling_stock.decoder.manufacturer }} |
-
-
- Version |
- {{ rolling_stock.decoder.version }} |
-
-
- Interface |
- {{ rolling_stock.decoder.get_interface_display }} |
-
-
- Sound |
- {{ rolling_stock.decoder.sound | yesno:"Yes,No" }} |
-
-
-
-
-
- {{ rolling_stock.notes | markdown | safe }}
-
-
-
-
-
- Properties |
-
-
-
- {% for p in rolling_stock.property.all %}
-
- {{ p.property }} |
- {{ p.value }} |
-
- {% endfor %}
-
-
-
-
-
-
-
- Documents |
-
-
-
- {% for d in rolling_stock.document.all %}
-
- {{ d.description }} |
- {{ d.filename }} |
- {{ d.file.size | filesizeformat }} |
-
- {% endfor %}
-
-
-
-
-
- {% if request.user.is_staff %}
Edit{% endif %}
-
-
-
-
-
-
-
-
+ {% 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 %}
{% endfor %}
-
-
-
-
-{% include 'footer.html' %}
-
-
-
+ {% endblock %}
+ {% block extra_content %}
+
+
+
+
+
+
+
+
+
+ Data |
+
+
+
+
+ Type |
+ {{ rolling_stock.rolling_class.type }} |
+
+
+ Company |
+ {{ rolling_stock.rolling_class.company }} |
+
+
+ Class |
+ {{ rolling_stock.rolling_class.identifier }} |
+
+
+ Road number |
+ {{ rolling_stock.road_number }} |
+
+
+ Era |
+ {{ rolling_stock.era }} |
+
+
+
+
+ {% if rolling_stock.decoder %}
+
+
+
+ DCC data |
+
+
+
+
+ Decoder |
+ {{ rolling_stock.decoder }} |
+
+
+ Address |
+ {{ rolling_stock.address }} |
+
+
+
+ {% endif %}
+
+
+
+
+
+ Model data |
+
+
+
+
+ Manufacturer |
+ {% if rolling_stock.manufacturer.website %}{% endif %}{{ rolling_stock.manufacturer }}{% if rolling_stock.manufacturer.website %}{% endif %}
+ |
+
+ Scale |
+ {{ rolling_stock.scale }} |
+
+
+ SKU |
+ {{ rolling_stock.sku }} |
+
+
+ ERA |
+ {{ rolling_stock.era }} |
+
+
+ Production year |
+ {{ rolling_stock.production_year | default_if_none:"" }} |
+
+
+ Purchase date |
+ {{ rolling_stock.purchase_date | default_if_none:"" }} |
+
+
+
+
+
+
+
+
+ Class data |
+
+
+
+
+ Class |
+ {{ rolling_stock.rolling_class }} |
+
+
+ Type |
+ {{ rolling_stock.rolling_class.type }} |
+
+
+ Company |
+ {{ rolling_stock.rolling_class.company }} ({{ rolling_stock.rolling_class.company.extended_name }}) |
+
+
+ Country |
+ {{ rolling_stock.rolling_class.company.country.name }} |
+
+
+ Manufacturer |
+ {{ rolling_stock.rolling_class.manufacturer }} |
+
+
+
+
+
+
+
+
+ DCC data |
+
+
+
+
+ Name |
+ {{ rolling_stock.decoder.name }} |
+
+
+ Manufacturer |
+ {{ rolling_stock.decoder.manufacturer }} |
+
+
+ Version |
+ {{ rolling_stock.decoder.version }} |
+
+
+ Interface |
+ {{ rolling_stock.decoder.get_interface_display }} |
+
+
+ Sound |
+ {{ rolling_stock.decoder.sound | yesno:"Yes,No" }} |
+
+
+
+
+
+ {{ rolling_stock.notes | markdown | safe }}
+
+
+
+
+
+ Properties |
+
+
+
+ {% for p in rolling_stock.property.all %}
+
+ {{ p.property }} |
+ {{ p.value }} |
+
+ {% endfor %}
+
+
+
+
+
+
+
+ Documents |
+
+
+
+ {% for d in rolling_stock.document.all %}
+
+ {{ d.description }} |
+ {{ d.filename }} |
+ {{ d.file.size | filesizeformat }} |
+
+ {% endfor %}
+
+
+
+
+
+ {% if request.user.is_staff %}
Edit{% endif %}
+
+
+
+
+ {% 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/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 9991f27..c106df8 100644
--- a/ram/portal/urls.py
+++ b/ram/portal/urls.py
@@ -1,8 +1,22 @@
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_pagination'),
- path("", GetRollingStock.as_view(), name='rolling_stock'),
+ 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/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 94b34e6..5f393af 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,16 +24,76 @@ 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},
+ )
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 e2fdf24..74dd8bf 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
@@ -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/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),
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)