Files
django-ram/ram/roster/models.py
Daniele Viganò e4ad98fa38 Implement support for sets and other improvements (#34)
* Add a boolean to define item as part of a set
* Add contextual help in admin
* Introduce support to sets and to item code lookup
Also review the url path for pagination
2024-04-21 00:31:52 +02:00

212 lines
5.9 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",
)
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