Add podcast pages
This commit is contained in:
@ -7,6 +7,7 @@ from django.apps import apps
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django_extensions.db.models import TimeStampedModel
|
from django_extensions.db.models import TimeStampedModel
|
||||||
from podcasts.scrapers import scrape_data_from_google_podcasts
|
from podcasts.scrapers import scrape_data_from_google_podcasts
|
||||||
@ -39,11 +40,14 @@ class Podcast(TimeStampedModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name}"
|
return f"{self.name}"
|
||||||
|
|
||||||
def scrobbles(self):
|
def get_absolute_url(self):
|
||||||
|
return reverse("podcasts:podcast_detail", kwargs={"slug": self.uuid})
|
||||||
|
|
||||||
|
def scrobbles(self, user):
|
||||||
Scrobble = apps.get_model("scrobbles", "Scrobble")
|
Scrobble = apps.get_model("scrobbles", "Scrobble")
|
||||||
return Scrobble.objects.filter(podcast_episode__podcast=self).order_by(
|
return Scrobble.objects.filter(
|
||||||
"-timestamp"
|
user=user, podcast_episode__podcast=self
|
||||||
)
|
).order_by("-timestamp")
|
||||||
|
|
||||||
def scrape_google_podcasts(self, force=False):
|
def scrape_google_podcasts(self, force=False):
|
||||||
podcast_dict = {}
|
podcast_dict = {}
|
||||||
|
|||||||
14
vrobbler/apps/podcasts/urls.py
Normal file
14
vrobbler/apps/podcasts/urls.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from django.urls import path
|
||||||
|
from podcasts import views
|
||||||
|
|
||||||
|
app_name = "podcasts"
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("podcasts/", views.PodcastListView.as_view(), name="podcast_list"),
|
||||||
|
path(
|
||||||
|
"podcasts/<slug:slug>/",
|
||||||
|
views.PodcastDetailView.as_view(),
|
||||||
|
name="podcast_detail",
|
||||||
|
),
|
||||||
|
]
|
||||||
18
vrobbler/apps/podcasts/views.py
Normal file
18
vrobbler/apps/podcasts/views.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from django.views import generic
|
||||||
|
from podcasts.models import Podcast
|
||||||
|
|
||||||
|
|
||||||
|
class PodcastListView(generic.ListView):
|
||||||
|
model = Podcast
|
||||||
|
paginate_by = 20
|
||||||
|
|
||||||
|
|
||||||
|
class PodcastDetailView(generic.DetailView):
|
||||||
|
model = Podcast
|
||||||
|
slug_field = "uuid"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
user = self.request.user
|
||||||
|
context_data = super().get_context_data(**kwargs)
|
||||||
|
context_data["scrobbles"] = self.object.scrobbles(user)
|
||||||
|
return context_data
|
||||||
57
vrobbler/templates/podcasts/podcast_detail.html
Normal file
57
vrobbler/templates/podcasts/podcast_detail.html
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{% extends "base_list.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block title %}{{object.name}}{% endblock %}
|
||||||
|
|
||||||
|
{% block head_extra %}
|
||||||
|
<style>
|
||||||
|
.cover {float:left; width:412px; margin-right:10px; padding-bottom:15px;}
|
||||||
|
.summary {float:left; width:600px; margin-left:10px;}
|
||||||
|
.header {padding-bottom:15px;}
|
||||||
|
.image-wrapper { contain: content; }
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block lists %}
|
||||||
|
|
||||||
|
<div class="row header">
|
||||||
|
<div class="cover image-wrapper">
|
||||||
|
<img src="{% if object.cover_image %}{{object.cover_image.url}}{% else %}{% static 'images/no-video-cover.jpg' %}{% endif %}" width="400px" />
|
||||||
|
</div>
|
||||||
|
<div class="summary">
|
||||||
|
{% if object.description %}<p>{{object.description|safe|linebreaks|truncatewords:160}}</p>{% endif %}
|
||||||
|
<hr />
|
||||||
|
{% if object.google_podcast_url %}
|
||||||
|
<p style="float:right;">
|
||||||
|
<a href="{{object.google_podcast_url}}"><img src="{% static " images/google-logo.png" %}" width=35></a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="deets">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md">
|
||||||
|
<h3>Last scrobbles</h3>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Date</th>
|
||||||
|
<th scope="col">Episode</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for scrobble in scrobbles.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{scrobble.timestamp}}</td>
|
||||||
|
<td>{{scrobble.podcast_episode}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
32
vrobbler/templates/podcasts/podcast_list.html
Normal file
32
vrobbler/templates/podcasts/podcast_list.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{% extends "base_list.html" %}
|
||||||
|
|
||||||
|
{% block lists %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Series</th>
|
||||||
|
<th scope="col">Episode</th>
|
||||||
|
<th scope="col">Scrobbles</th>
|
||||||
|
<th scope="col">All time</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for obj in object_list %}
|
||||||
|
{% for episode in obj.episode_set.all %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{{episode.get_absolute_url}}">{{episode}}</a></td>
|
||||||
|
<td><a href="{{obj.get_absolute_url}}">{{obj}}</a></td>
|
||||||
|
<td>{{episode.scrobble_set.count}}</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@ -7,6 +7,7 @@ from vrobbler.apps.books.api.views import AuthorViewSet, BookViewSet
|
|||||||
from vrobbler.apps.music import urls as music_urls
|
from vrobbler.apps.music import urls as music_urls
|
||||||
from vrobbler.apps.books import urls as book_urls
|
from vrobbler.apps.books import urls as book_urls
|
||||||
from vrobbler.apps.sports import urls as sports_urls
|
from vrobbler.apps.sports import urls as sports_urls
|
||||||
|
from vrobbler.apps.podcasts import urls as podcast_urls
|
||||||
from vrobbler.apps.videogames import urls as videogame_urls
|
from vrobbler.apps.videogames import urls as videogame_urls
|
||||||
from vrobbler.apps.music.api.views import (
|
from vrobbler.apps.music.api.views import (
|
||||||
AlbumViewSet,
|
AlbumViewSet,
|
||||||
@ -63,6 +64,7 @@ urlpatterns = [
|
|||||||
path("", include(video_urls, namespace="videos")),
|
path("", include(video_urls, namespace="videos")),
|
||||||
path("", include(videogame_urls, namespace="videogames")),
|
path("", include(videogame_urls, namespace="videogames")),
|
||||||
path("", include(sports_urls, namespace="sports")),
|
path("", include(sports_urls, namespace="sports")),
|
||||||
|
path("", include(podcast_urls, namespace="podcasts")),
|
||||||
path("", include(scrobble_urls, namespace="scrobbles")),
|
path("", include(scrobble_urls, namespace="scrobbles")),
|
||||||
path(
|
path(
|
||||||
"", scrobbles_views.RecentScrobbleList.as_view(), name="vrobbler-home"
|
"", scrobbles_views.RecentScrobbleList.as_view(), name="vrobbler-home"
|
||||||
|
|||||||
Reference in New Issue
Block a user