Add basic spotify page
It currently doesn't handle pagination, or caching
This commit is contained in:
parent
9f2b2a81c9
commit
ace30f4dbd
11 changed files with 1100 additions and 0 deletions
9
static/src/scss/_spotify.scss
Normal file
9
static/src/scss/_spotify.scss
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
body.page-spotifyplaylistpage {
|
||||||
|
table {
|
||||||
|
img {
|
||||||
|
min-width: 55px;
|
||||||
|
width: 55px;
|
||||||
|
height: 55px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@
|
||||||
@import "blocks";
|
@import "blocks";
|
||||||
@import "shareon";
|
@import "shareon";
|
||||||
@import "search";
|
@import "search";
|
||||||
|
@import "spotify";
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
|
|
|
@ -9,6 +9,7 @@ env = environ.Env(
|
||||||
DEBUG=(bool, False),
|
DEBUG=(bool, False),
|
||||||
BASE_HOSTNAME=(str, "example.com"),
|
BASE_HOSTNAME=(str, "example.com"),
|
||||||
UNSPLASH_CLIENT_ID=(str, ""),
|
UNSPLASH_CLIENT_ID=(str, ""),
|
||||||
|
SPOTIFY_PROXY_HOST=(str, ""),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Read local secrets
|
# Read local secrets
|
||||||
|
@ -30,6 +31,7 @@ INSTALLED_APPS = [
|
||||||
"website.blog",
|
"website.blog",
|
||||||
"website.images",
|
"website.images",
|
||||||
"website.contact",
|
"website.contact",
|
||||||
|
"website.spotify",
|
||||||
"website.contrib.code_block",
|
"website.contrib.code_block",
|
||||||
"website.contrib.mermaid_block",
|
"website.contrib.mermaid_block",
|
||||||
"website.contrib.unsplash",
|
"website.contrib.unsplash",
|
||||||
|
@ -178,6 +180,7 @@ WAGTAILEMBEDS_FINDERS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
UNSPLASH_CLIENT_ID = env("UNSPLASH_CLIENT_ID")
|
UNSPLASH_CLIENT_ID = env("UNSPLASH_CLIENT_ID")
|
||||||
|
SPOTIFY_PROXY_HOST = env("SPOTIFY_PROXY_HOST")
|
||||||
|
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
|
|
0
website/spotify/__init__.py
Normal file
0
website/spotify/__init__.py
Normal file
16
website/spotify/client.py
Normal file
16
website/spotify/client.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import requests
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_playlist(playlist_id: str) -> bool:
|
||||||
|
return requests.get(
|
||||||
|
f"https://{settings.SPOTIFY_PROXY_HOST}/v1/playlists/{playlist_id}"
|
||||||
|
).ok
|
||||||
|
|
||||||
|
|
||||||
|
def get_playlist(playlist_id: str) -> dict:
|
||||||
|
response = requests.get(
|
||||||
|
f"https://{settings.SPOTIFY_PROXY_HOST}/v1/playlists/{playlist_id}"
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
989
website/spotify/migrations/0001_initial.py
Normal file
989
website/spotify/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,989 @@
|
||||||
|
# Generated by Django 4.0.6 on 2022-08-17 20:20
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.embeds.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import website.spotify.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("unsplash", "0002_unsplashphoto_created_and_more"),
|
||||||
|
("wagtailcore", "0069_log_entry_jsonfield"),
|
||||||
|
("images", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="SpotifyPlaylistPage",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"page_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="wagtailcore.page",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("subtitle", models.CharField(blank=True, max_length=255)),
|
||||||
|
(
|
||||||
|
"body",
|
||||||
|
wagtail.fields.StreamField(
|
||||||
|
[
|
||||||
|
("embed", wagtail.embeds.blocks.EmbedBlock()),
|
||||||
|
(
|
||||||
|
"rich_text",
|
||||||
|
wagtail.blocks.RichTextBlock(
|
||||||
|
features=[
|
||||||
|
"h2",
|
||||||
|
"h3",
|
||||||
|
"h4",
|
||||||
|
"h5",
|
||||||
|
"h6",
|
||||||
|
"bold",
|
||||||
|
"italic",
|
||||||
|
"ol",
|
||||||
|
"ul",
|
||||||
|
"link",
|
||||||
|
"document-link",
|
||||||
|
"code",
|
||||||
|
"strikethrough",
|
||||||
|
"snippet-link",
|
||||||
|
"snippet-embed",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"lorem",
|
||||||
|
wagtail.blocks.StructBlock(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"paragraphs",
|
||||||
|
wagtail.blocks.IntegerBlock(min_value=1),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("html", wagtail.blocks.RawHTMLBlock()),
|
||||||
|
(
|
||||||
|
"image",
|
||||||
|
wagtail.blocks.StructBlock(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"image",
|
||||||
|
wagtail.images.blocks.ImageChooserBlock(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"caption",
|
||||||
|
wagtail.blocks.RichTextBlock(
|
||||||
|
features=[
|
||||||
|
"bold",
|
||||||
|
"italic",
|
||||||
|
"link",
|
||||||
|
"document-link",
|
||||||
|
"code",
|
||||||
|
"strikethrough",
|
||||||
|
"snippet-link",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"code",
|
||||||
|
wagtail.blocks.StructBlock(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"language",
|
||||||
|
wagtail.blocks.ChoiceBlock(
|
||||||
|
choices=[
|
||||||
|
("ABAP", "ABAP"),
|
||||||
|
("ABNF", "ABNF"),
|
||||||
|
("ADL", "ADL"),
|
||||||
|
("AMDGPU", "AMDGPU"),
|
||||||
|
(
|
||||||
|
"ANSYS parametric design language",
|
||||||
|
"ANSYS parametric design language",
|
||||||
|
),
|
||||||
|
("ANTLR", "ANTLR"),
|
||||||
|
(
|
||||||
|
"ANTLR With ActionScript Target",
|
||||||
|
"ANTLR With ActionScript Target",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ANTLR With C# Target",
|
||||||
|
"ANTLR With C# Target",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ANTLR With CPP Target",
|
||||||
|
"ANTLR With CPP Target",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ANTLR With Java Target",
|
||||||
|
"ANTLR With Java Target",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ANTLR With ObjectiveC Target",
|
||||||
|
"ANTLR With ObjectiveC Target",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ANTLR With Perl Target",
|
||||||
|
"ANTLR With Perl Target",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ANTLR With Python Target",
|
||||||
|
"ANTLR With Python Target",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ANTLR With Ruby Target",
|
||||||
|
"ANTLR With Ruby Target",
|
||||||
|
),
|
||||||
|
("APL", "APL"),
|
||||||
|
("ASCII armored", "ASCII armored"),
|
||||||
|
("ActionScript", "ActionScript"),
|
||||||
|
(
|
||||||
|
"ActionScript 3",
|
||||||
|
"ActionScript 3",
|
||||||
|
),
|
||||||
|
("Ada", "Ada"),
|
||||||
|
("Agda", "Agda"),
|
||||||
|
("Aheui", "Aheui"),
|
||||||
|
("Alloy", "Alloy"),
|
||||||
|
("AmbientTalk", "AmbientTalk"),
|
||||||
|
("Ampl", "Ampl"),
|
||||||
|
("Angular2", "Angular2"),
|
||||||
|
("ApacheConf", "ApacheConf"),
|
||||||
|
("AppleScript", "AppleScript"),
|
||||||
|
("Arduino", "Arduino"),
|
||||||
|
("Arrow", "Arrow"),
|
||||||
|
("AspectJ", "AspectJ"),
|
||||||
|
("Asymptote", "Asymptote"),
|
||||||
|
("Augeas", "Augeas"),
|
||||||
|
("AutoIt", "AutoIt"),
|
||||||
|
("Awk", "Awk"),
|
||||||
|
("BARE", "BARE"),
|
||||||
|
("BBC Basic", "BBC Basic"),
|
||||||
|
("BBCode", "BBCode"),
|
||||||
|
("BC", "BC"),
|
||||||
|
("BNF", "BNF"),
|
||||||
|
("BST", "BST"),
|
||||||
|
("BUGS", "BUGS"),
|
||||||
|
("Base Makefile", "Base Makefile"),
|
||||||
|
("Bash", "Bash"),
|
||||||
|
("Bash Session", "Bash Session"),
|
||||||
|
("Batchfile", "Batchfile"),
|
||||||
|
("Bdd", "Bdd"),
|
||||||
|
("Befunge", "Befunge"),
|
||||||
|
("Berry", "Berry"),
|
||||||
|
("BibTeX", "BibTeX"),
|
||||||
|
("BlitzBasic", "BlitzBasic"),
|
||||||
|
("BlitzMax", "BlitzMax"),
|
||||||
|
("Boa", "Boa"),
|
||||||
|
("Boo", "Boo"),
|
||||||
|
("Boogie", "Boogie"),
|
||||||
|
("Brainfuck", "Brainfuck"),
|
||||||
|
("C", "C"),
|
||||||
|
("C#", "C#"),
|
||||||
|
("C++", "C++"),
|
||||||
|
("CAmkES", "CAmkES"),
|
||||||
|
("CBM BASIC V2", "CBM BASIC V2"),
|
||||||
|
("CDDL", "CDDL"),
|
||||||
|
("CFEngine3", "CFEngine3"),
|
||||||
|
("CMake", "CMake"),
|
||||||
|
("COBOL", "COBOL"),
|
||||||
|
("COBOLFree", "COBOLFree"),
|
||||||
|
("CPSA", "CPSA"),
|
||||||
|
("CSS", "CSS"),
|
||||||
|
(
|
||||||
|
"CSS+Django/Jinja",
|
||||||
|
"CSS+Django/Jinja",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"CSS+Genshi Text",
|
||||||
|
"CSS+Genshi Text",
|
||||||
|
),
|
||||||
|
("CSS+Lasso", "CSS+Lasso"),
|
||||||
|
("CSS+Mako", "CSS+Mako"),
|
||||||
|
("CSS+Myghty", "CSS+Myghty"),
|
||||||
|
("CSS+PHP", "CSS+PHP"),
|
||||||
|
("CSS+Ruby", "CSS+Ruby"),
|
||||||
|
("CSS+Smarty", "CSS+Smarty"),
|
||||||
|
("CSS+UL4", "CSS+UL4"),
|
||||||
|
(
|
||||||
|
"CSS+mozpreproc",
|
||||||
|
"CSS+mozpreproc",
|
||||||
|
),
|
||||||
|
("CUDA", "CUDA"),
|
||||||
|
("Cap'n Proto", "Cap'n Proto"),
|
||||||
|
("CapDL", "CapDL"),
|
||||||
|
("Ceylon", "Ceylon"),
|
||||||
|
("ChaiScript", "ChaiScript"),
|
||||||
|
("Chapel", "Chapel"),
|
||||||
|
("Charmci", "Charmci"),
|
||||||
|
("Cheetah", "Cheetah"),
|
||||||
|
("Cirru", "Cirru"),
|
||||||
|
("Clay", "Clay"),
|
||||||
|
("Clean", "Clean"),
|
||||||
|
("Clojure", "Clojure"),
|
||||||
|
("ClojureScript", "ClojureScript"),
|
||||||
|
("CoffeeScript", "CoffeeScript"),
|
||||||
|
(
|
||||||
|
"Coldfusion CFC",
|
||||||
|
"Coldfusion CFC",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Coldfusion HTML",
|
||||||
|
"Coldfusion HTML",
|
||||||
|
),
|
||||||
|
("Common Lisp", "Common Lisp"),
|
||||||
|
(
|
||||||
|
"Component Pascal",
|
||||||
|
"Component Pascal",
|
||||||
|
),
|
||||||
|
("Coq", "Coq"),
|
||||||
|
("Crmsh", "Crmsh"),
|
||||||
|
("Croc", "Croc"),
|
||||||
|
("Cryptol", "Cryptol"),
|
||||||
|
("Crystal", "Crystal"),
|
||||||
|
(
|
||||||
|
"Csound Document",
|
||||||
|
"Csound Document",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Csound Orchestra",
|
||||||
|
"Csound Orchestra",
|
||||||
|
),
|
||||||
|
("Csound Score", "Csound Score"),
|
||||||
|
("Cypher", "Cypher"),
|
||||||
|
("Cython", "Cython"),
|
||||||
|
("D", "D"),
|
||||||
|
("DASM16", "DASM16"),
|
||||||
|
("DTD", "DTD"),
|
||||||
|
("Darcs Patch", "Darcs Patch"),
|
||||||
|
("Dart", "Dart"),
|
||||||
|
(
|
||||||
|
"Debian Control file",
|
||||||
|
"Debian Control file",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Debian Sourcelist",
|
||||||
|
"Debian Sourcelist",
|
||||||
|
),
|
||||||
|
("Delphi", "Delphi"),
|
||||||
|
("Devicetree", "Devicetree"),
|
||||||
|
("Diff", "Diff"),
|
||||||
|
("Django/Jinja", "Django/Jinja"),
|
||||||
|
("Docker", "Docker"),
|
||||||
|
("Duel", "Duel"),
|
||||||
|
("Dylan", "Dylan"),
|
||||||
|
("Dylan session", "Dylan session"),
|
||||||
|
("DylanLID", "DylanLID"),
|
||||||
|
("E-mail", "E-mail"),
|
||||||
|
("EBNF", "EBNF"),
|
||||||
|
("ECL", "ECL"),
|
||||||
|
("ERB", "ERB"),
|
||||||
|
("Earl Grey", "Earl Grey"),
|
||||||
|
("Easytrieve", "Easytrieve"),
|
||||||
|
("Eiffel", "Eiffel"),
|
||||||
|
("Elixir", "Elixir"),
|
||||||
|
(
|
||||||
|
"Elixir iex session",
|
||||||
|
"Elixir iex session",
|
||||||
|
),
|
||||||
|
("Elm", "Elm"),
|
||||||
|
("Elpi", "Elpi"),
|
||||||
|
("EmacsLisp", "EmacsLisp"),
|
||||||
|
(
|
||||||
|
"Embedded Ragel",
|
||||||
|
"Embedded Ragel",
|
||||||
|
),
|
||||||
|
("Erlang", "Erlang"),
|
||||||
|
(
|
||||||
|
"Erlang erl session",
|
||||||
|
"Erlang erl session",
|
||||||
|
),
|
||||||
|
("Evoque", "Evoque"),
|
||||||
|
("Ezhil", "Ezhil"),
|
||||||
|
("F#", "F#"),
|
||||||
|
("FStar", "FStar"),
|
||||||
|
("Factor", "Factor"),
|
||||||
|
("Fancy", "Fancy"),
|
||||||
|
("Fantom", "Fantom"),
|
||||||
|
("Felix", "Felix"),
|
||||||
|
("Fennel", "Fennel"),
|
||||||
|
("Fish", "Fish"),
|
||||||
|
("Flatline", "Flatline"),
|
||||||
|
("FloScript", "FloScript"),
|
||||||
|
("Forth", "Forth"),
|
||||||
|
("Fortran", "Fortran"),
|
||||||
|
("FortranFixed", "FortranFixed"),
|
||||||
|
("FoxPro", "FoxPro"),
|
||||||
|
("Freefem", "Freefem"),
|
||||||
|
("Futhark", "Futhark"),
|
||||||
|
("GAP", "GAP"),
|
||||||
|
("GAS", "GAS"),
|
||||||
|
("GDScript", "GDScript"),
|
||||||
|
("GLSL", "GLSL"),
|
||||||
|
("GSQL", "GSQL"),
|
||||||
|
("Genshi", "Genshi"),
|
||||||
|
("Genshi Text", "Genshi Text"),
|
||||||
|
(
|
||||||
|
"Gettext Catalog",
|
||||||
|
"Gettext Catalog",
|
||||||
|
),
|
||||||
|
("Gherkin", "Gherkin"),
|
||||||
|
("Gnuplot", "Gnuplot"),
|
||||||
|
("Go", "Go"),
|
||||||
|
("Golo", "Golo"),
|
||||||
|
("GoodData-CL", "GoodData-CL"),
|
||||||
|
("Gosu", "Gosu"),
|
||||||
|
("Gosu Template", "Gosu Template"),
|
||||||
|
("Graphviz", "Graphviz"),
|
||||||
|
("Groff", "Groff"),
|
||||||
|
("Groovy", "Groovy"),
|
||||||
|
("HLSL", "HLSL"),
|
||||||
|
("HSAIL", "HSAIL"),
|
||||||
|
("HTML", "HTML"),
|
||||||
|
(
|
||||||
|
"HTML + Angular2",
|
||||||
|
"HTML + Angular2",
|
||||||
|
),
|
||||||
|
("HTML+Cheetah", "HTML+Cheetah"),
|
||||||
|
(
|
||||||
|
"HTML+Django/Jinja",
|
||||||
|
"HTML+Django/Jinja",
|
||||||
|
),
|
||||||
|
("HTML+Evoque", "HTML+Evoque"),
|
||||||
|
("HTML+Genshi", "HTML+Genshi"),
|
||||||
|
(
|
||||||
|
"HTML+Handlebars",
|
||||||
|
"HTML+Handlebars",
|
||||||
|
),
|
||||||
|
("HTML+Lasso", "HTML+Lasso"),
|
||||||
|
("HTML+Mako", "HTML+Mako"),
|
||||||
|
("HTML+Myghty", "HTML+Myghty"),
|
||||||
|
("HTML+PHP", "HTML+PHP"),
|
||||||
|
("HTML+Smarty", "HTML+Smarty"),
|
||||||
|
("HTML+Twig", "HTML+Twig"),
|
||||||
|
("HTML+UL4", "HTML+UL4"),
|
||||||
|
("HTML+Velocity", "HTML+Velocity"),
|
||||||
|
("HTTP", "HTTP"),
|
||||||
|
("Haml", "Haml"),
|
||||||
|
("Handlebars", "Handlebars"),
|
||||||
|
("Haskell", "Haskell"),
|
||||||
|
("Haxe", "Haxe"),
|
||||||
|
("Hexdump", "Hexdump"),
|
||||||
|
("Hspec", "Hspec"),
|
||||||
|
("Hxml", "Hxml"),
|
||||||
|
("Hy", "Hy"),
|
||||||
|
("Hybris", "Hybris"),
|
||||||
|
("IDL", "IDL"),
|
||||||
|
("INI", "INI"),
|
||||||
|
("IRC logs", "IRC logs"),
|
||||||
|
("Icon", "Icon"),
|
||||||
|
("Idris", "Idris"),
|
||||||
|
("Igor", "Igor"),
|
||||||
|
("Inform 6", "Inform 6"),
|
||||||
|
(
|
||||||
|
"Inform 6 template",
|
||||||
|
"Inform 6 template",
|
||||||
|
),
|
||||||
|
("Inform 7", "Inform 7"),
|
||||||
|
("Io", "Io"),
|
||||||
|
("Ioke", "Ioke"),
|
||||||
|
("Isabelle", "Isabelle"),
|
||||||
|
("J", "J"),
|
||||||
|
("JAGS", "JAGS"),
|
||||||
|
("JCL", "JCL"),
|
||||||
|
("JSGF", "JSGF"),
|
||||||
|
("JSLT", "JSLT"),
|
||||||
|
("JSON", "JSON"),
|
||||||
|
("JSON-LD", "JSON-LD"),
|
||||||
|
(
|
||||||
|
"JSONBareObject",
|
||||||
|
"JSONBareObject",
|
||||||
|
),
|
||||||
|
("Jasmin", "Jasmin"),
|
||||||
|
("Java", "Java"),
|
||||||
|
(
|
||||||
|
"Java Server Page",
|
||||||
|
"Java Server Page",
|
||||||
|
),
|
||||||
|
("JavaScript", "JavaScript"),
|
||||||
|
(
|
||||||
|
"JavaScript+Cheetah",
|
||||||
|
"JavaScript+Cheetah",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JavaScript+Django/Jinja",
|
||||||
|
"JavaScript+Django/Jinja",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JavaScript+Genshi Text",
|
||||||
|
"JavaScript+Genshi Text",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JavaScript+Lasso",
|
||||||
|
"JavaScript+Lasso",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JavaScript+Mako",
|
||||||
|
"JavaScript+Mako",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JavaScript+Myghty",
|
||||||
|
"JavaScript+Myghty",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JavaScript+PHP",
|
||||||
|
"JavaScript+PHP",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JavaScript+Ruby",
|
||||||
|
"JavaScript+Ruby",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JavaScript+Smarty",
|
||||||
|
"JavaScript+Smarty",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Javascript+UL4",
|
||||||
|
"Javascript+UL4",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Javascript+mozpreproc",
|
||||||
|
"Javascript+mozpreproc",
|
||||||
|
),
|
||||||
|
("Julia", "Julia"),
|
||||||
|
("Julia console", "Julia console"),
|
||||||
|
("Juttle", "Juttle"),
|
||||||
|
("K", "K"),
|
||||||
|
("Kal", "Kal"),
|
||||||
|
("Kconfig", "Kconfig"),
|
||||||
|
("Kernel log", "Kernel log"),
|
||||||
|
("Koka", "Koka"),
|
||||||
|
("Kotlin", "Kotlin"),
|
||||||
|
("Kuin", "Kuin"),
|
||||||
|
("LLVM", "LLVM"),
|
||||||
|
("LLVM-MIR", "LLVM-MIR"),
|
||||||
|
("LLVM-MIR Body", "LLVM-MIR Body"),
|
||||||
|
("LSL", "LSL"),
|
||||||
|
("Lasso", "Lasso"),
|
||||||
|
("Lean", "Lean"),
|
||||||
|
("LessCss", "LessCss"),
|
||||||
|
(
|
||||||
|
"Lighttpd configuration file",
|
||||||
|
"Lighttpd configuration file",
|
||||||
|
),
|
||||||
|
("LilyPond", "LilyPond"),
|
||||||
|
("Limbo", "Limbo"),
|
||||||
|
("Literate Agda", "Literate Agda"),
|
||||||
|
(
|
||||||
|
"Literate Cryptol",
|
||||||
|
"Literate Cryptol",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Literate Haskell",
|
||||||
|
"Literate Haskell",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Literate Idris",
|
||||||
|
"Literate Idris",
|
||||||
|
),
|
||||||
|
("LiveScript", "LiveScript"),
|
||||||
|
("Logos", "Logos"),
|
||||||
|
("Logtalk", "Logtalk"),
|
||||||
|
("Lua", "Lua"),
|
||||||
|
("MAQL", "MAQL"),
|
||||||
|
("MCFunction", "MCFunction"),
|
||||||
|
("MIME", "MIME"),
|
||||||
|
("MOOCode", "MOOCode"),
|
||||||
|
("MQL", "MQL"),
|
||||||
|
("MSDOS Session", "MSDOS Session"),
|
||||||
|
("MXML", "MXML"),
|
||||||
|
("Macaulay2", "Macaulay2"),
|
||||||
|
("Makefile", "Makefile"),
|
||||||
|
("Mako", "Mako"),
|
||||||
|
("Markdown", "Markdown"),
|
||||||
|
("Mask", "Mask"),
|
||||||
|
("Mason", "Mason"),
|
||||||
|
("Mathematica", "Mathematica"),
|
||||||
|
("Matlab", "Matlab"),
|
||||||
|
(
|
||||||
|
"Matlab session",
|
||||||
|
"Matlab session",
|
||||||
|
),
|
||||||
|
("Maxima", "Maxima"),
|
||||||
|
("Meson", "Meson"),
|
||||||
|
("MiniD", "MiniD"),
|
||||||
|
("MiniScript", "MiniScript"),
|
||||||
|
("Modelica", "Modelica"),
|
||||||
|
("Modula-2", "Modula-2"),
|
||||||
|
(
|
||||||
|
"MoinMoin/Trac Wiki markup",
|
||||||
|
"MoinMoin/Trac Wiki markup",
|
||||||
|
),
|
||||||
|
("Monkey", "Monkey"),
|
||||||
|
("Monte", "Monte"),
|
||||||
|
("MoonScript", "MoonScript"),
|
||||||
|
("Mosel", "Mosel"),
|
||||||
|
("Mscgen", "Mscgen"),
|
||||||
|
("MuPAD", "MuPAD"),
|
||||||
|
("MySQL", "MySQL"),
|
||||||
|
("Myghty", "Myghty"),
|
||||||
|
("NASM", "NASM"),
|
||||||
|
("NCL", "NCL"),
|
||||||
|
("NSIS", "NSIS"),
|
||||||
|
("Nemerle", "Nemerle"),
|
||||||
|
("NestedText", "NestedText"),
|
||||||
|
("NewLisp", "NewLisp"),
|
||||||
|
("Newspeak", "Newspeak"),
|
||||||
|
(
|
||||||
|
"Nginx configuration file",
|
||||||
|
"Nginx configuration file",
|
||||||
|
),
|
||||||
|
("Nimrod", "Nimrod"),
|
||||||
|
("Nit", "Nit"),
|
||||||
|
("Nix", "Nix"),
|
||||||
|
(
|
||||||
|
"Node.js REPL console session",
|
||||||
|
"Node.js REPL console session",
|
||||||
|
),
|
||||||
|
("Notmuch", "Notmuch"),
|
||||||
|
("NuSMV", "NuSMV"),
|
||||||
|
("NumPy", "NumPy"),
|
||||||
|
("OCaml", "OCaml"),
|
||||||
|
("ODIN", "ODIN"),
|
||||||
|
(
|
||||||
|
"OMG Interface Definition Language",
|
||||||
|
"OMG Interface Definition Language",
|
||||||
|
),
|
||||||
|
("Objective-C", "Objective-C"),
|
||||||
|
("Objective-C++", "Objective-C++"),
|
||||||
|
("Objective-J", "Objective-J"),
|
||||||
|
("Octave", "Octave"),
|
||||||
|
("Ooc", "Ooc"),
|
||||||
|
("Opa", "Opa"),
|
||||||
|
("OpenEdge ABL", "OpenEdge ABL"),
|
||||||
|
("PEG", "PEG"),
|
||||||
|
("PHP", "PHP"),
|
||||||
|
("PL/pgSQL", "PL/pgSQL"),
|
||||||
|
("POVRay", "POVRay"),
|
||||||
|
("PacmanConf", "PacmanConf"),
|
||||||
|
("Pan", "Pan"),
|
||||||
|
("ParaSail", "ParaSail"),
|
||||||
|
("Pawn", "Pawn"),
|
||||||
|
("Perl", "Perl"),
|
||||||
|
("Perl6", "Perl6"),
|
||||||
|
("Pig", "Pig"),
|
||||||
|
("Pike", "Pike"),
|
||||||
|
("PkgConfig", "PkgConfig"),
|
||||||
|
("Pointless", "Pointless"),
|
||||||
|
("Pony", "Pony"),
|
||||||
|
("PostScript", "PostScript"),
|
||||||
|
(
|
||||||
|
"PostgreSQL SQL dialect",
|
||||||
|
"PostgreSQL SQL dialect",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PostgreSQL console (psql)",
|
||||||
|
"PostgreSQL console (psql)",
|
||||||
|
),
|
||||||
|
("PowerShell", "PowerShell"),
|
||||||
|
(
|
||||||
|
"PowerShell Session",
|
||||||
|
"PowerShell Session",
|
||||||
|
),
|
||||||
|
("Praat", "Praat"),
|
||||||
|
("Procfile", "Procfile"),
|
||||||
|
("Prolog", "Prolog"),
|
||||||
|
("PromQL", "PromQL"),
|
||||||
|
("Properties", "Properties"),
|
||||||
|
(
|
||||||
|
"Protocol Buffer",
|
||||||
|
"Protocol Buffer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PsySH console session for PHP",
|
||||||
|
"PsySH console session for PHP",
|
||||||
|
),
|
||||||
|
("Pug", "Pug"),
|
||||||
|
("Puppet", "Puppet"),
|
||||||
|
("PyPy Log", "PyPy Log"),
|
||||||
|
("Python", "Python"),
|
||||||
|
("Python 2.x", "Python 2.x"),
|
||||||
|
(
|
||||||
|
"Python 2.x Traceback",
|
||||||
|
"Python 2.x Traceback",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Python Traceback",
|
||||||
|
"Python Traceback",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Python console session",
|
||||||
|
"Python console session",
|
||||||
|
),
|
||||||
|
("Python+UL4", "Python+UL4"),
|
||||||
|
("Q", "Q"),
|
||||||
|
("QBasic", "QBasic"),
|
||||||
|
("QML", "QML"),
|
||||||
|
("QVTO", "QVTO"),
|
||||||
|
("Qlik", "Qlik"),
|
||||||
|
("RConsole", "RConsole"),
|
||||||
|
("REBOL", "REBOL"),
|
||||||
|
("RHTML", "RHTML"),
|
||||||
|
("RPMSpec", "RPMSpec"),
|
||||||
|
("RQL", "RQL"),
|
||||||
|
("RSL", "RSL"),
|
||||||
|
("Racket", "Racket"),
|
||||||
|
("Ragel", "Ragel"),
|
||||||
|
(
|
||||||
|
"Ragel in C Host",
|
||||||
|
"Ragel in C Host",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Ragel in CPP Host",
|
||||||
|
"Ragel in CPP Host",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Ragel in D Host",
|
||||||
|
"Ragel in D Host",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Ragel in Java Host",
|
||||||
|
"Ragel in Java Host",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Ragel in Objective C Host",
|
||||||
|
"Ragel in Objective C Host",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Ragel in Ruby Host",
|
||||||
|
"Ragel in Ruby Host",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Raw token data",
|
||||||
|
"Raw token data",
|
||||||
|
),
|
||||||
|
("Rd", "Rd"),
|
||||||
|
("ReasonML", "ReasonML"),
|
||||||
|
("Red", "Red"),
|
||||||
|
("Redcode", "Redcode"),
|
||||||
|
(
|
||||||
|
"Relax-NG Compact",
|
||||||
|
"Relax-NG Compact",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ResourceBundle",
|
||||||
|
"ResourceBundle",
|
||||||
|
),
|
||||||
|
("Rexx", "Rexx"),
|
||||||
|
("Ride", "Ride"),
|
||||||
|
("Rita", "Rita"),
|
||||||
|
(
|
||||||
|
"Roboconf Graph",
|
||||||
|
"Roboconf Graph",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Roboconf Instances",
|
||||||
|
"Roboconf Instances",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"RobotFramework",
|
||||||
|
"RobotFramework",
|
||||||
|
),
|
||||||
|
("Ruby", "Ruby"),
|
||||||
|
(
|
||||||
|
"Ruby irb session",
|
||||||
|
"Ruby irb session",
|
||||||
|
),
|
||||||
|
("Rust", "Rust"),
|
||||||
|
("S", "S"),
|
||||||
|
("SARL", "SARL"),
|
||||||
|
("SAS", "SAS"),
|
||||||
|
("SCSS", "SCSS"),
|
||||||
|
("SNBT", "SNBT"),
|
||||||
|
("SPARQL", "SPARQL"),
|
||||||
|
("SQL", "SQL"),
|
||||||
|
("SWIG", "SWIG"),
|
||||||
|
("Sass", "Sass"),
|
||||||
|
("Savi", "Savi"),
|
||||||
|
("Scala", "Scala"),
|
||||||
|
(
|
||||||
|
"Scalate Server Page",
|
||||||
|
"Scalate Server Page",
|
||||||
|
),
|
||||||
|
("Scaml", "Scaml"),
|
||||||
|
("Scheme", "Scheme"),
|
||||||
|
("Scilab", "Scilab"),
|
||||||
|
("Sed", "Sed"),
|
||||||
|
("ShExC", "ShExC"),
|
||||||
|
("Shen", "Shen"),
|
||||||
|
("Sieve", "Sieve"),
|
||||||
|
("Silver", "Silver"),
|
||||||
|
("Singularity", "Singularity"),
|
||||||
|
("Slash", "Slash"),
|
||||||
|
("Slim", "Slim"),
|
||||||
|
("Slurm", "Slurm"),
|
||||||
|
("Smali", "Smali"),
|
||||||
|
("Smalltalk", "Smalltalk"),
|
||||||
|
(
|
||||||
|
"SmartGameFormat",
|
||||||
|
"SmartGameFormat",
|
||||||
|
),
|
||||||
|
("Smarty", "Smarty"),
|
||||||
|
("Smithy", "Smithy"),
|
||||||
|
("Snobol", "Snobol"),
|
||||||
|
("Snowball", "Snowball"),
|
||||||
|
("Solidity", "Solidity"),
|
||||||
|
("Sophia", "Sophia"),
|
||||||
|
("SourcePawn", "SourcePawn"),
|
||||||
|
("Spice", "Spice"),
|
||||||
|
("SquidConf", "SquidConf"),
|
||||||
|
("Srcinfo", "Srcinfo"),
|
||||||
|
("Stan", "Stan"),
|
||||||
|
("Standard ML", "Standard ML"),
|
||||||
|
("Stata", "Stata"),
|
||||||
|
("SuperCollider", "SuperCollider"),
|
||||||
|
("Swift", "Swift"),
|
||||||
|
("TADS 3", "TADS 3"),
|
||||||
|
("TAP", "TAP"),
|
||||||
|
("TASM", "TASM"),
|
||||||
|
("TOML", "TOML"),
|
||||||
|
("Tal", "Tal"),
|
||||||
|
("Tcl", "Tcl"),
|
||||||
|
("Tcsh", "Tcsh"),
|
||||||
|
("Tcsh Session", "Tcsh Session"),
|
||||||
|
("TeX", "TeX"),
|
||||||
|
("Tea", "Tea"),
|
||||||
|
(
|
||||||
|
"Tera Term macro",
|
||||||
|
"Tera Term macro",
|
||||||
|
),
|
||||||
|
("Termcap", "Termcap"),
|
||||||
|
("Terminfo", "Terminfo"),
|
||||||
|
("Terraform", "Terraform"),
|
||||||
|
("Text only", "Text only"),
|
||||||
|
("Text output", "Text output"),
|
||||||
|
("ThingsDB", "ThingsDB"),
|
||||||
|
("Thrift", "Thrift"),
|
||||||
|
("Todotxt", "Todotxt"),
|
||||||
|
("TrafficScript", "TrafficScript"),
|
||||||
|
("Transact-SQL", "Transact-SQL"),
|
||||||
|
("Treetop", "Treetop"),
|
||||||
|
("Turtle", "Turtle"),
|
||||||
|
("Twig", "Twig"),
|
||||||
|
("TypeScript", "TypeScript"),
|
||||||
|
("TypoScript", "TypoScript"),
|
||||||
|
(
|
||||||
|
"TypoScriptCssData",
|
||||||
|
"TypoScriptCssData",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"TypoScriptHtmlData",
|
||||||
|
"TypoScriptHtmlData",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Typographic Number Theory",
|
||||||
|
"Typographic Number Theory",
|
||||||
|
),
|
||||||
|
("UL4", "UL4"),
|
||||||
|
("USD", "USD"),
|
||||||
|
("Unicon", "Unicon"),
|
||||||
|
(
|
||||||
|
"Unix/Linux config files",
|
||||||
|
"Unix/Linux config files",
|
||||||
|
),
|
||||||
|
("UrbiScript", "UrbiScript"),
|
||||||
|
("VB.net", "VB.net"),
|
||||||
|
("VBScript", "VBScript"),
|
||||||
|
("VCL", "VCL"),
|
||||||
|
("VCLSnippets", "VCLSnippets"),
|
||||||
|
("VCTreeStatus", "VCTreeStatus"),
|
||||||
|
("VGL", "VGL"),
|
||||||
|
("Vala", "Vala"),
|
||||||
|
("Velocity", "Velocity"),
|
||||||
|
("VimL", "VimL"),
|
||||||
|
("WDiff", "WDiff"),
|
||||||
|
("Web IDL", "Web IDL"),
|
||||||
|
("WebAssembly", "WebAssembly"),
|
||||||
|
("Whiley", "Whiley"),
|
||||||
|
("X10", "X10"),
|
||||||
|
("XML", "XML"),
|
||||||
|
("XML+Cheetah", "XML+Cheetah"),
|
||||||
|
(
|
||||||
|
"XML+Django/Jinja",
|
||||||
|
"XML+Django/Jinja",
|
||||||
|
),
|
||||||
|
("XML+Evoque", "XML+Evoque"),
|
||||||
|
("XML+Lasso", "XML+Lasso"),
|
||||||
|
("XML+Mako", "XML+Mako"),
|
||||||
|
("XML+Myghty", "XML+Myghty"),
|
||||||
|
("XML+PHP", "XML+PHP"),
|
||||||
|
("XML+Ruby", "XML+Ruby"),
|
||||||
|
("XML+Smarty", "XML+Smarty"),
|
||||||
|
("XML+UL4", "XML+UL4"),
|
||||||
|
("XML+Velocity", "XML+Velocity"),
|
||||||
|
("XQuery", "XQuery"),
|
||||||
|
("XSLT", "XSLT"),
|
||||||
|
(
|
||||||
|
"XUL+mozpreproc",
|
||||||
|
"XUL+mozpreproc",
|
||||||
|
),
|
||||||
|
("Xorg", "Xorg"),
|
||||||
|
("Xtend", "Xtend"),
|
||||||
|
("YAML", "YAML"),
|
||||||
|
("YAML+Jinja", "YAML+Jinja"),
|
||||||
|
("YANG", "YANG"),
|
||||||
|
("Zeek", "Zeek"),
|
||||||
|
("Zephir", "Zephir"),
|
||||||
|
("Zig", "Zig"),
|
||||||
|
("aspx-cs", "aspx-cs"),
|
||||||
|
("aspx-vb", "aspx-vb"),
|
||||||
|
("autohotkey", "autohotkey"),
|
||||||
|
("c-objdump", "c-objdump"),
|
||||||
|
("cADL", "cADL"),
|
||||||
|
(
|
||||||
|
"ca65 assembler",
|
||||||
|
"ca65 assembler",
|
||||||
|
),
|
||||||
|
("cfstatement", "cfstatement"),
|
||||||
|
("cplint", "cplint"),
|
||||||
|
("cpp-objdump", "cpp-objdump"),
|
||||||
|
("d-objdump", "d-objdump"),
|
||||||
|
("dg", "dg"),
|
||||||
|
("eC", "eC"),
|
||||||
|
("execline", "execline"),
|
||||||
|
("g-code", "g-code"),
|
||||||
|
("liquid", "liquid"),
|
||||||
|
(
|
||||||
|
"mozhashpreproc",
|
||||||
|
"mozhashpreproc",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"mozpercentpreproc",
|
||||||
|
"mozpercentpreproc",
|
||||||
|
),
|
||||||
|
("nesC", "nesC"),
|
||||||
|
("objdump", "objdump"),
|
||||||
|
("objdump-nasm", "objdump-nasm"),
|
||||||
|
(
|
||||||
|
"reStructuredText",
|
||||||
|
"reStructuredText",
|
||||||
|
),
|
||||||
|
("reg", "reg"),
|
||||||
|
("scdoc", "scdoc"),
|
||||||
|
("sqlite3con", "sqlite3con"),
|
||||||
|
("systemverilog", "systemverilog"),
|
||||||
|
("teal", "teal"),
|
||||||
|
("tiddler", "tiddler"),
|
||||||
|
("ucode", "ucode"),
|
||||||
|
("verilog", "verilog"),
|
||||||
|
("vhdl", "vhdl"),
|
||||||
|
("xtlang", "xtlang"),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("source", wagtail.blocks.TextBlock()),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"tangent",
|
||||||
|
wagtail.blocks.StructBlock(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"name",
|
||||||
|
wagtail.blocks.CharBlock(max_length=64),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"content",
|
||||||
|
wagtail.blocks.RichTextBlock(
|
||||||
|
features=[
|
||||||
|
"bold",
|
||||||
|
"italic",
|
||||||
|
"ol",
|
||||||
|
"ul",
|
||||||
|
"link",
|
||||||
|
"document-link",
|
||||||
|
"code",
|
||||||
|
"strikethrough",
|
||||||
|
"snippet-link",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"mermaid",
|
||||||
|
wagtail.blocks.StructBlock(
|
||||||
|
[
|
||||||
|
("source", wagtail.blocks.TextBlock()),
|
||||||
|
(
|
||||||
|
"caption",
|
||||||
|
wagtail.blocks.RichTextBlock(
|
||||||
|
features=[
|
||||||
|
"bold",
|
||||||
|
"italic",
|
||||||
|
"link",
|
||||||
|
"document-link",
|
||||||
|
"code",
|
||||||
|
"strikethrough",
|
||||||
|
"snippet-link",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
blank=True,
|
||||||
|
use_json_field=True,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"spotify_playlist_id",
|
||||||
|
models.CharField(
|
||||||
|
max_length=32,
|
||||||
|
unique=True,
|
||||||
|
validators=[website.spotify.models.validate_playlist_id],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"hero_image",
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="images.customimage",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"hero_unsplash_photo",
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="unsplash.unsplashphoto",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
},
|
||||||
|
bases=("wagtailcore.page",),
|
||||||
|
),
|
||||||
|
]
|
0
website/spotify/migrations/__init__.py
Normal file
0
website/spotify/migrations/__init__.py
Normal file
38
website/spotify/models.py
Normal file
38
website/spotify/models.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.db import models
|
||||||
|
from django.http.request import HttpRequest
|
||||||
|
from wagtail.admin.panels import FieldPanel
|
||||||
|
|
||||||
|
from website.common.models import BaseContentPage
|
||||||
|
|
||||||
|
from . import client
|
||||||
|
|
||||||
|
|
||||||
|
def validate_playlist_id(playlist_id: str) -> None:
|
||||||
|
if not client.is_valid_playlist(playlist_id):
|
||||||
|
raise ValidationError("Unknown playlist id")
|
||||||
|
|
||||||
|
|
||||||
|
class SpotifyPlaylistPage(BaseContentPage):
|
||||||
|
subpage_types: list = []
|
||||||
|
|
||||||
|
spotify_playlist_id = models.CharField(
|
||||||
|
max_length=32, unique=True, validators=[validate_playlist_id]
|
||||||
|
)
|
||||||
|
|
||||||
|
content_panels = BaseContentPage.content_panels + [
|
||||||
|
FieldPanel("spotify_playlist_id")
|
||||||
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def table_of_contents(self) -> list:
|
||||||
|
return []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reading_time(self) -> int:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def get_context(self, request: HttpRequest) -> dict:
|
||||||
|
context = super().get_context(request)
|
||||||
|
context["playlist"] = client.get_playlist(self.spotify_playlist_id)
|
||||||
|
return context
|
17
website/spotify/templates/spotify/spotify-item.html
Normal file
17
website/spotify/templates/spotify/spotify-item.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{% with url=track.external_urls.spotify %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url }}">
|
||||||
|
<img src="{{ track.album.images.0.url }}" decoding="async" loading="lazy" referrerpolicy="no-referrer" class="image"/>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if track.preview_url %}
|
||||||
|
<a href="{{ track.preview_url }}"><i class="fas fa-play"></i></a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td><a href="{{ url }}">{{ track.name }}</a></td>
|
||||||
|
<td>{% for artist in track.artists %}{% if not forloop.first %}, {% endif %}{{ artist.name }}{% endfor %}</td>
|
||||||
|
<td>{{ track.album.name }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endwith %}
|
3
website/spotify/templates/spotify/spotify-items.html
Normal file
3
website/spotify/templates/spotify/spotify-items.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{% for track in tracks %}
|
||||||
|
{% include "spotify/spotify-item.html" with track=track.track %}
|
||||||
|
{% endfor %}
|
24
website/spotify/templates/spotify/spotify_playlist_page.html
Normal file
24
website/spotify/templates/spotify/spotify_playlist_page.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{% extends "common/content_page.html" %}
|
||||||
|
|
||||||
|
{% block post_content %}
|
||||||
|
<section class="container content">
|
||||||
|
<h3>{{ playlist.name }}</h3>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
<th>Track</th>
|
||||||
|
<th>Artist</th>
|
||||||
|
<th>Album</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% include "spotify/spotify-items.html" with tracks=playlist.tracks.items %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
<section class="container">
|
||||||
|
<a href="{{ playlist.external_urls.spotify }}"><i class="fab fa-spotify"></i> View on Spotify</a>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
Loading…
Reference in a new issue