[templates] Clean up how str and subtitles work
This commit is contained in:
@ -61,9 +61,7 @@ class BirdSightingLogData(BaseLogData, WithPeopleLogData):
|
||||
@cached_property
|
||||
def bird_list(self) -> str:
|
||||
if self.birds:
|
||||
return ", ".join(
|
||||
[BirdSightingEntry(**b).__str__() for b in self.birds]
|
||||
)
|
||||
return ", ".join([BirdSightingEntry(**b).__str__() for b in self.birds])
|
||||
return ""
|
||||
|
||||
def as_html(self) -> str:
|
||||
@ -80,9 +78,7 @@ class BirdSightingLogData(BaseLogData, WithPeopleLogData):
|
||||
)
|
||||
|
||||
if self.area:
|
||||
html_parts.append(
|
||||
f'<div class="birding-area">Area: {self.area}</div>'
|
||||
)
|
||||
html_parts.append(f'<div class="birding-area">Area: {self.area}</div>')
|
||||
|
||||
if self.party_size:
|
||||
html_parts.append(
|
||||
@ -105,9 +101,7 @@ class BirdSightingLogData(BaseLogData, WithPeopleLogData):
|
||||
)
|
||||
|
||||
if self.guide:
|
||||
html_parts.append(
|
||||
f'<div class="birding-guide">Guide: {self.guide}</div>'
|
||||
)
|
||||
html_parts.append(f'<div class="birding-guide">Guide: {self.guide}</div>')
|
||||
|
||||
if self.duration_minutes:
|
||||
html_parts.append(
|
||||
@ -183,9 +177,7 @@ class Bird(TimeStampedModel):
|
||||
|
||||
class BirdingLocation(ScrobblableMixin):
|
||||
description = models.TextField(**BNULL)
|
||||
geo_location = models.ForeignKey(
|
||||
GeoLocation, **BNULL, on_delete=models.DO_NOTHING
|
||||
)
|
||||
geo_location = models.ForeignKey(GeoLocation, **BNULL, on_delete=models.DO_NOTHING)
|
||||
ebird_hotspot_id = models.CharField(max_length=255, **BNULL)
|
||||
|
||||
def get_absolute_url(self):
|
||||
@ -193,7 +185,7 @@ class BirdingLocation(ScrobblableMixin):
|
||||
|
||||
@property
|
||||
def subtitle(self):
|
||||
return ""
|
||||
return self.geo_location
|
||||
|
||||
@property
|
||||
def strings(self) -> ScrobblableConstants:
|
||||
@ -269,9 +261,7 @@ class BirdingCSVImport(TimeStampedModel):
|
||||
self.save(update_fields=["process_log", "process_count"])
|
||||
return
|
||||
for count, scrobble in enumerate(scrobbles):
|
||||
scrobble_str = (
|
||||
f"{scrobble.id}\t{scrobble.timestamp}\t{scrobble.media_obj}"
|
||||
)
|
||||
scrobble_str = f"{scrobble.id}\t{scrobble.timestamp}\t{scrobble.media_obj}"
|
||||
log_line = f"{scrobble_str}"
|
||||
if count > 0:
|
||||
log_line = "\n" + log_line
|
||||
|
||||
@ -266,8 +266,9 @@ class BoardGame(ScrobblableMixin):
|
||||
"self", **BNULL, on_delete=models.DO_NOTHING
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
@property
|
||||
def subtitle(self) -> str:
|
||||
return self.publisher
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("boardgames:boardgame_detail", kwargs={"slug": self.uuid})
|
||||
|
||||
@ -173,11 +173,7 @@ class Book(LongPlayScrobblableMixin):
|
||||
genre = TaggableManager(through=ObjectWithGenres, blank=True, verbose_name="Genre")
|
||||
|
||||
def __str__(self) -> str:
|
||||
if self.issue_number and "Issue" not in str(self.title):
|
||||
return f"{self.title} - Issue {self.issue_number}"
|
||||
if self.volume_number and "Volume" not in str(self.title):
|
||||
return f"{self.title} - Volume {self.volume_number}"
|
||||
return f"{self.title}"
|
||||
return f"{self.title} - {self.subtitle}"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.pages:
|
||||
@ -188,7 +184,12 @@ class Book(LongPlayScrobblableMixin):
|
||||
|
||||
@property
|
||||
def subtitle(self):
|
||||
return f" by {self.author}"
|
||||
subtitle = self.author
|
||||
if self.issue_number and "Issue" not in str(self.title):
|
||||
subtitle += " - Issue {self.issue_number}"
|
||||
if self.volume_number and "Volume" not in str(self.title):
|
||||
subtitle += " - Volume {self.volume_number}"
|
||||
return subtitle
|
||||
|
||||
@property
|
||||
def strings(self) -> ScrobblableConstants:
|
||||
|
||||
@ -20,6 +20,7 @@ class ScrobbleInline(admin.TabularInline):
|
||||
extra = 0
|
||||
raw_id_fields = (
|
||||
"video",
|
||||
"channel",
|
||||
"podcast_episode",
|
||||
"track",
|
||||
"video_game",
|
||||
@ -30,6 +31,7 @@ class ScrobbleInline(admin.TabularInline):
|
||||
"board_game",
|
||||
"geo_location",
|
||||
"task",
|
||||
"puzzle",
|
||||
"mood",
|
||||
"brick_set",
|
||||
"trail",
|
||||
@ -59,47 +61,38 @@ class ImportBaseAdmin(admin.ModelAdmin):
|
||||
|
||||
|
||||
@admin.register(AudioScrobblerTSVImport)
|
||||
class AudioScrobblerTSVImportAdmin(ImportBaseAdmin):
|
||||
...
|
||||
class AudioScrobblerTSVImportAdmin(ImportBaseAdmin): ...
|
||||
|
||||
|
||||
@admin.register(LastFmImport)
|
||||
class LastFmImportAdmin(ImportBaseAdmin):
|
||||
...
|
||||
class LastFmImportAdmin(ImportBaseAdmin): ...
|
||||
|
||||
|
||||
@admin.register(KoReaderImport)
|
||||
class KoReaderImportAdmin(ImportBaseAdmin):
|
||||
...
|
||||
class KoReaderImportAdmin(ImportBaseAdmin): ...
|
||||
|
||||
|
||||
@admin.register(RetroarchImport)
|
||||
class RetroarchImportAdmin(ImportBaseAdmin):
|
||||
...
|
||||
class RetroarchImportAdmin(ImportBaseAdmin): ...
|
||||
|
||||
|
||||
class RetroarchImportAdmin(ImportBaseAdmin):
|
||||
...
|
||||
class RetroarchImportAdmin(ImportBaseAdmin): ...
|
||||
|
||||
|
||||
@admin.register(BGStatsImport)
|
||||
class BGStatsImportAdmin(ImportBaseAdmin):
|
||||
...
|
||||
class BGStatsImportAdmin(ImportBaseAdmin): ...
|
||||
|
||||
|
||||
@admin.register(EBirdCSVImport)
|
||||
class EBirdCSVImportAdmin(ImportBaseAdmin):
|
||||
...
|
||||
class EBirdCSVImportAdmin(ImportBaseAdmin): ...
|
||||
|
||||
|
||||
@admin.register(ScaleCSVImport)
|
||||
class ScaleCSVImportAdmin(ImportBaseAdmin):
|
||||
...
|
||||
class ScaleCSVImportAdmin(ImportBaseAdmin): ...
|
||||
|
||||
|
||||
@admin.register(TrailGPXImport)
|
||||
class TrailGPXImportAdmin(ImportBaseAdmin):
|
||||
...
|
||||
class TrailGPXImportAdmin(ImportBaseAdmin): ...
|
||||
|
||||
|
||||
@admin.register(Genre)
|
||||
|
||||
@ -65,6 +65,9 @@ class ScrobblableMixin(TimeStampedModel):
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.title} - {self.subtitle}"
|
||||
|
||||
@property
|
||||
def run_time_seconds(self) -> int:
|
||||
run_time = 900
|
||||
|
||||
@ -184,7 +184,7 @@ class ScrobbleableDetailView(ChartContextMixin, DetailView):
|
||||
def get_context_data(self, **kwargs):
|
||||
context_data = super().get_context_data(**kwargs)
|
||||
scrobbles = []
|
||||
if not self.request.user.is_anonymous:
|
||||
if not self.request.user.is_anonymous and hasattr(self.object, "scrobble_set"):
|
||||
scrobbles = self.object.scrobble_set.filter(
|
||||
user=self.request.user
|
||||
).order_by("-timestamp")
|
||||
@ -439,8 +439,7 @@ class ScrobbleListView(LoginRequiredMixin, ListView):
|
||||
full_qs = getattr(self, "_full_queryset", None)
|
||||
if full_qs is not None and getattr(self, "tag_list", []):
|
||||
total = (
|
||||
full_qs.aggregate(total=Sum("playback_position_seconds"))["total"]
|
||||
or 0
|
||||
full_qs.aggregate(total=Sum("playback_position_seconds"))["total"] or 0
|
||||
)
|
||||
ctx["total_time_seconds"] = total
|
||||
return ctx
|
||||
@ -1245,8 +1244,7 @@ class ScrobbleDetailView(DetailView):
|
||||
track=media_obj, user=self.object.user
|
||||
).order_by("-timestamp")[:20]
|
||||
context["has_mopidy_uri"] = any(
|
||||
(s.log or {}).get("raw_data", {}).get("mopidy_uri")
|
||||
for s in scrobbles
|
||||
(s.log or {}).get("raw_data", {}).get("mopidy_uri") for s in scrobbles
|
||||
)
|
||||
else:
|
||||
context["has_mopidy_uri"] = False
|
||||
|
||||
@ -123,17 +123,17 @@ class SportEvent(ScrobblableMixin):
|
||||
super(SportEvent, self).save(*args, **kwargs)
|
||||
|
||||
def __str__(self) -> str:
|
||||
league = self.league
|
||||
if self.league and self.league.abbreviation_str:
|
||||
league = self.league.abbreviation_str
|
||||
return f"{self.title} - {league}"
|
||||
return f"{self.title} - {self.subtitle}"
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("sports:event_detail", kwargs={"slug": self.uuid})
|
||||
|
||||
@property
|
||||
def subtitle(self) -> str:
|
||||
return self.comp_str
|
||||
league = self.league
|
||||
if self.league and self.league.abbreviation_str:
|
||||
league = self.league.abbreviation_str
|
||||
return f"{league} {self.get_event_type_display()}"
|
||||
|
||||
@property
|
||||
def comp_str(self) -> str:
|
||||
|
||||
@ -163,12 +163,9 @@ class VideoGame(LongPlayScrobblableMixin):
|
||||
platforms = models.ManyToManyField(VideoGamePlatform)
|
||||
retroarch_name = models.CharField(max_length=255, **BNULL)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
@property
|
||||
def subtitle(self):
|
||||
return f" On {self.platforms.first()}"
|
||||
return f"{self.platforms.first()}"
|
||||
|
||||
@property
|
||||
def strings(self) -> ScrobblableConstants:
|
||||
|
||||
@ -50,7 +50,11 @@
|
||||
|
||||
<h1 class="d-flex align-items-center gap-2">
|
||||
{% if object.media_type == "Video" %}🎬{% elif object.media_type == "Track" %}🎵{% elif object.media_type == "PodcastEpisode" %}🎙️{% elif object.media_type == "SportEvent" %}⚽{% elif object.media_type == "Book" %}📚{% elif object.media_type == "Paper" %}📄{% elif object.media_type == "VideoGame" %}🎮{% elif object.media_type == "BoardGame" %}🎲{% elif object.media_type == "GeoLocation" %}📍{% elif object.media_type == "Trail" %}🥾{% elif object.media_type == "Beer" %}🍺{% elif object.media_type == "Puzzle" %}🧩{% elif object.media_type == "Food" %}🍔{% elif object.media_type == "Task" %}✅{% elif object.media_type == "WebPage" %}🌐{% elif object.media_type == "LifeEvent" %}🎉{% elif object.media_type == "Mood" %}😊{% elif object.media_type == "BrickSet" %}🧱{% elif object.media_type == "Channel" %}📺{% endif %}
|
||||
{% if object.media_obj.get_absolute_url %}<a href="{{ object.media_obj.get_absolute_url }}">{% endif %}{{ object.media_obj }}{% if object.media_obj.get_absolute_url %}</a>{% endif %}
|
||||
{% if object.media_obj.get_absolute_url %}
|
||||
<a href="{{ object.media_obj.get_absolute_url }}">{% endif %}
|
||||
{{ object.media_obj.title }}
|
||||
{% if object.media_obj.get_absolute_url %}</a>
|
||||
{% endif %}
|
||||
{% if user.is_authenticated and object.media_obj %}
|
||||
<button id="favorite-btn"
|
||||
data-url="{% url 'scrobbles:toggle-favorite' object.media_type object.media_obj.id %}"
|
||||
@ -62,7 +66,15 @@
|
||||
</button>
|
||||
{% endif %}
|
||||
</h1>
|
||||
<h2>{{ object.media_obj.subtitle }}</h2>
|
||||
<p>
|
||||
{% if object.media_type == "SportEvent" %}
|
||||
{% for team in object.media_obj.teams.all %}
|
||||
<img src="{{team.logo.url}}" width=150 />
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if object.media_type == "Task" and object.logdata.title %}
|
||||
</p>
|
||||
<h2>{{ object.logdata.title }}</h2>
|
||||
{% endif %}
|
||||
<h3 class="text-muted">{{ object.local_timestamp }}</h3>
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
{% extends "base_detail.html" %}
|
||||
|
||||
{% block title %}{{object}}{% endblock %}
|
||||
{% block title %}{{object.title}}{% endblock %}
|
||||
|
||||
{% block details %}
|
||||
<h2>{{object.subtitle}}</h2>
|
||||
<h2>{{object.league}} {{object.get_event_type_display}}</h2>
|
||||
|
||||
<div class="row">
|
||||
<h2>{{object.tv_series}}</h2>
|
||||
<div class="col-md">
|
||||
{% for team in object.teams.all %}
|
||||
<img src="{{team.logo.url}}" width=150 />
|
||||
{% endfor %}
|
||||
<hr />
|
||||
<h3>Last scrobbles</h3>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
|
||||
Reference in New Issue
Block a user