Files
django-ram/ram/roster/models.py
Daniele Viganò 6a9f37ca05 Add a 404 page and improve manufacturer lookup (#36)
* Add a custom 404 page
* Better manufacturer and item lookup
* Add migration to populate new field
* Version bump
2024-04-24 00:33:41 +02:00

217 lines
6.0 KiB
Python

import os
import re
import shutil
from uuid import uuid4
from django.db import models
from django.urls import reverse
from django.conf import settings
from django.dispatch import receiver
from tinymce import models as tinymce
from ram.models import Document, Image, PropertyInstance
from ram.utils import DeduplicatedStorage
from metadata.models import (
Scale,
Manufacturer,
Decoder,
Company,
Tag,
RollingStockType,
)
class RollingClass(models.Model):
identifier = models.CharField(max_length=128, unique=False)
type = models.ForeignKey(RollingStockType, on_delete=models.CASCADE)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
description = tinymce.HTMLField(blank=True)
manufacturer = models.ForeignKey(
Manufacturer,
on_delete=models.CASCADE,
null=True,
blank=True,
limit_choices_to={"category": "real"},
)
class Meta:
ordering = ["company", "identifier"]
verbose_name = "Class"
verbose_name_plural = "Classes"
def __str__(self):
return "{0} {1}".format(self.company, self.identifier)
class RollingClassProperty(PropertyInstance):
rolling_class = models.ForeignKey(
RollingClass,
on_delete=models.CASCADE,
null=False,
blank=False,
related_name="property",
verbose_name="Class",
)
class RollingStock(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid4, editable=False)
rolling_class = models.ForeignKey(
RollingClass,
on_delete=models.CASCADE,
null=False,
blank=False,
related_name="rolling_class",
verbose_name="Class",
)
road_number = models.CharField(max_length=128, unique=False)
road_number_int = models.PositiveSmallIntegerField(default=0, unique=False)
manufacturer = models.ForeignKey(
Manufacturer,
on_delete=models.CASCADE,
null=True,
blank=True,
limit_choices_to={"category": "model"},
)
scale = models.ForeignKey(Scale, on_delete=models.CASCADE)
item_number = models.CharField(
max_length=32,
blank=True,
help_text="Catalog item number or code",
)
item_number_slug = models.CharField(
max_length=32,
blank=True,
editable=False
)
set = models.BooleanField(
default=False,
help_text="Part of a set",
)
decoder_interface = models.PositiveSmallIntegerField(
choices=settings.DECODER_INTERFACES, null=True, blank=True
)
decoder = models.ForeignKey(
Decoder, on_delete=models.CASCADE, null=True, blank=True
)
address = models.SmallIntegerField(default=None, null=True, blank=True)
era = models.CharField(
max_length=32,
blank=True,
help_text="Era or epoch of the model",
)
production_year = models.SmallIntegerField(null=True, blank=True)
purchase_date = models.DateField(null=True, blank=True)
description = tinymce.HTMLField(blank=True)
tags = models.ManyToManyField(
Tag, related_name="rolling_stock", blank=True
)
notes = tinymce.HTMLField(blank=True)
creation_time = models.DateTimeField(auto_now_add=True)
updated_time = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["rolling_class", "road_number_int"]
verbose_name_plural = "Rolling stock"
def __str__(self):
return "{0} {1}".format(self.rolling_class, self.road_number)
def get_absolute_url(self):
return reverse("rolling_stock", kwargs={"uuid": self.uuid})
def country(self):
return str(self.rolling_class.company.country)
def company(self):
return str(self.rolling_class.company)
def delete(self, *args, **kwargs):
shutil.rmtree(
os.path.join(
settings.MEDIA_ROOT, "images", "rollingstock", str(self.uuid)
),
ignore_errors=True
)
super(RollingStock, self).delete(*args, **kwargs)
@receiver(models.signals.pre_save, sender=RollingStock)
def pre_save_running_number(sender, instance, *args, **kwargs):
try:
instance.road_number_int = int(
re.findall(r"\d+", instance.road_number)[0]
)
except IndexError:
pass
class RollingStockDocument(Document):
rolling_stock = models.ForeignKey(
RollingStock, on_delete=models.CASCADE, related_name="document"
)
class Meta(object):
unique_together = ("rolling_stock", "file")
def rolling_stock_image_upload(instance, filename):
return os.path.join(
"images",
"rollingstock",
str(instance.rolling_stock.uuid),
filename
)
class RollingStockImage(Image):
rolling_stock = models.ForeignKey(
RollingStock, on_delete=models.CASCADE, related_name="image"
)
image = models.ImageField(
upload_to=rolling_stock_image_upload,
storage=DeduplicatedStorage,
)
class RollingStockProperty(PropertyInstance):
rolling_stock = models.ForeignKey(
RollingStock,
on_delete=models.CASCADE,
related_name="property",
null=False,
blank=False,
)
class RollingStockJournal(models.Model):
rolling_stock = models.ForeignKey(
RollingStock,
on_delete=models.CASCADE,
related_name="journal",
null=False,
blank=False,
)
date = models.DateField()
log = tinymce.HTMLField()
private = models.BooleanField(
default=False,
help_text="Journal log will be visible only to logged users",
)
creation_time = models.DateTimeField(auto_now_add=True)
updated_time = models.DateTimeField(auto_now=True)
def __str__(self):
return "{0} - {1}".format(self.rolling_stock, self.date)
class Meta:
ordering = ["date", "rolling_stock"]
# @receiver(models.signals.post_delete, sender=Cab)
# def post_save_image(sender, instance, *args, **kwargs):
# try:
# instance.image.delete(save=False)
# except Exception:
# pass