6 Commits

10 changed files with 60 additions and 21 deletions

View File

@@ -137,6 +137,10 @@ class Catalog(BaseBook):
ordering = ["manufacturer", "publication_year"] ordering = ["manufacturer", "publication_year"]
def __str__(self): def __str__(self):
# if the object is new, return an empty string to avoid
# calling self.scales.all() which would raise a infinite recursion
if self.pk is None:
return str() # empty string
scales = self.get_scales() scales = self.get_scales()
return "%s %s %s" % (self.manufacturer.name, self.years, scales) return "%s %s %s" % (self.manufacturer.name, self.years, scales)

View File

@@ -28,7 +28,7 @@ class ConsistAdmin(SortableAdminBase, admin.ModelAdmin):
"creation_time", "creation_time",
"updated_time", "updated_time",
) )
list_filter = ("company", "era", "published") list_filter = ("company__name", "era", "published")
list_display = ("__str__",) + list_filter + ("country_flag",) list_display = ("__str__",) + list_filter + ("country_flag",)
search_fields = ("identifier",) + list_filter search_fields = ("identifier",) + list_filter
save_as = True save_as = True

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.1.4 on 2025-04-27 19:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("consist", "0015_consist_description"),
]
operations = [
migrations.AlterField(
model_name="consistitem",
name="order",
field=models.PositiveIntegerField(),
),
]

View File

@@ -39,16 +39,25 @@ class Consist(BaseModel):
def get_absolute_url(self): def get_absolute_url(self):
return reverse("consist", kwargs={"uuid": self.uuid}) return reverse("consist", kwargs={"uuid": self.uuid})
@property
def length(self):
return self.consist_item.count()
def get_type_count(self):
return self.consist_item.annotate(
type=models.F("rolling_stock__rolling_class__type__type")
).values(
"type"
).annotate(
count=models.Count("rolling_stock"),
category=models.F("rolling_stock__rolling_class__type__category"),
order=models.Max("order"),
).order_by("order")
@property @property
def country(self): def country(self):
return self.company.country return self.company.country
def clean(self):
if self.consist_item.filter(rolling_stock__published=False).exists():
raise ValidationError(
"You must publish all items in the consist before publishing the consist." # noqa: E501
)
class Meta: class Meta:
ordering = ["company", "-creation_time"] ordering = ["company", "-creation_time"]
@@ -58,11 +67,7 @@ class ConsistItem(models.Model):
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) rolling_stock = models.ForeignKey(RollingStock, on_delete=models.CASCADE)
order = models.PositiveIntegerField( order = models.PositiveIntegerField(blank=False, null=False)
default=1000, # make sure it is always added at the end
blank=False,
null=False
)
class Meta: class Meta:
ordering = ["order"] ordering = ["order"]
@@ -76,6 +81,12 @@ class ConsistItem(models.Model):
def __str__(self): def __str__(self):
return "{0}".format(self.rolling_stock) return "{0}".format(self.rolling_stock)
def clean(self):
if self.consist.published and not self.rolling_stock.published:
raise ValidationError(
"You must unpublish the the consist before using this item."
)
def published(self): def published(self):
return self.rolling_stock.published return self.rolling_stock.published
published.boolean = True published.boolean = True

View File

@@ -46,7 +46,10 @@
{% endif %} {% endif %}
<tr> <tr>
<th class="w-33" scope="row">Company</th> <th class="w-33" scope="row">Company</th>
<td><abbr title="{{ d.item.company.extended_name }}">{{ d.item.company }}</abbr></td> <td>
<img src="{{ d.item.company.country.flag }}" alt="{{ d.item.company.country }}">
<abbr title="{{ d.item.company.extended_name }}">{{ d.item.company }}</abbr>
</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Era</th> <th scope="row">Era</th>
@@ -54,7 +57,7 @@
</tr> </tr>
<tr> <tr>
<th scope="row">Length</th> <th scope="row">Length</th>
<td>{{ d.item.consist_item.count }}</td> <td>{{ d.item.length }}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@@ -43,6 +43,7 @@
<tr> <tr>
<th scope="row">Company</th> <th scope="row">Company</th>
<td> <td>
<img src="{{ d.item.company.country.flag }}" alt="{{ d.item.company.country }}">
<a href="{% url 'filtered' _filter="company" search=d.item.company.slug %}"><abbr title="{{ d.item.company.extended_name }}">{{ d.item.company }}</abbr></a> <a href="{% url 'filtered' _filter="company" search=d.item.company.slug %}"><abbr title="{{ d.item.company.extended_name }}">{{ d.item.company }}</abbr></a>
</td> </td>
</tr> </tr>

View File

@@ -109,7 +109,7 @@
{% endif %} {% endif %}
<tr> <tr>
<th scope="row">Length</th> <th scope="row">Length</th>
<td>{{ data | length }}</td> <td>{{ consist.length }}: {% for t in consist.get_type_count %}{{ t.count }}x {{ t.type }} {{t.category }}{% if not forloop.last %} + {% endif %}{% endfor %}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@@ -12,9 +12,11 @@
<div class="container d-flex text-body-secondary"> <div class="container d-flex text-body-secondary">
<p class="flex-fill small">Made with ❤️ for 🚂 and <i class="bi bi-github"></i> <a href="https://github.com/daniviga/django-ram">django-ram</a> <p class="flex-fill small">Made with ❤️ for 🚂 and <i class="bi bi-github"></i> <a href="https://github.com/daniviga/django-ram">django-ram</a>
{% if site_conf.show_version %}<br>Version {{ site_conf.version }}{% endif %}</p> {% if site_conf.show_version %}<br>Version {{ site_conf.version }}{% endif %}</p>
<p class="text-end fs-5"> <p class="text-end">
{% if site_conf.disclaimer %}<a class="text-reset" title="Disclaimer" href="" data-bs-toggle="modal" data-bs-target="#disclaimerModal"><i class="bi bi-info-square-fill"></i></a> {% endif %} {% if site_conf.disclaimer %}
<a class="text-reset" title="Back to top" href="#"><i class="bi bi-arrow-up-left-square-fill"></i></a> <a title="Disclaimer" href="" data-bs-toggle="modal" data-bs-target="#disclaimerModal"><i class="text-muted d-lg-none fs-5 bi bi-info-square-fill"></i><span class="d-none d-lg-inline small">Disclaimer</span></a><span class="d-none d-lg-inline small"> | </span>
{% endif %}
<a title="Back to top" href="#"><i class="text-muted d-lg-none fs-5 bi bi-arrow-up-left-square-fill"></i><span class="d-none d-lg-inline small">Back to top</span></a>
</p> </p>
</div> </div>
<!-- Modal --> <!-- Modal -->

View File

@@ -1,4 +1,4 @@
from ram.utils import git_suffix from ram.utils import git_suffix
__version__ = "0.17.1" __version__ = "0.17.5"
__version__ += git_suffix(__file__) __version__ += git_suffix(__file__)

View File

@@ -273,11 +273,11 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
settings.CSV_SEPARATOR_ALT.join( settings.CSV_SEPARATOR_ALT.join(
t.name for t in obj.tags.all() t.name for t in obj.tags.all()
), ),
obj.decoder_interface, obj.get_decoder_interface_display(),
obj.decoder, obj.decoder,
obj.address, obj.address,
obj.purchase_date,
obj.shop, obj.shop,
obj.purchase_date,
obj.price, obj.price,
properties, properties,
] ]