diff options
-rw-r--r-- | app/media/migrations/0002_auto_20211030_1634.py | 38 | ||||
-rw-r--r-- | app/pages/admin.py | 2 | ||||
-rw-r--r-- | app/pages/migrations/0002_auto_20211030_1634.py | 44 | ||||
-rw-r--r-- | app/pages/models.py | 7 | ||||
-rw-r--r-- | app/pages/views.py | 2 | ||||
-rw-r--r-- | app/posts/admin.py | 10 | ||||
-rw-r--r-- | app/posts/migrations/0002_alter_post_id.py | 18 | ||||
-rw-r--r-- | app/posts/migrations/0003_auto_20211030_1955.py | 38 | ||||
-rw-r--r-- | app/posts/models.py | 63 | ||||
-rw-r--r-- | app/posts/templates/posts/podcast_detail.html | 108 | ||||
-rw-r--r-- | app/posts/templates/posts/podcast_list.html | 29 | ||||
-rw-r--r-- | app/posts/templates/posts/src_detail.html | 110 | ||||
-rw-r--r-- | app/posts/templates/posts/src_list.html | 30 | ||||
-rw-r--r-- | app/posts/urls/podcast_urls.py | 34 | ||||
-rw-r--r-- | app/posts/urls/src_urls.py | 49 | ||||
-rw-r--r-- | app/posts/views/podcast_views.py (renamed from app/posts/views/src_views.py) | 26 | ||||
-rw-r--r-- | config/base_urls.py | 3 |
17 files changed, 364 insertions, 247 deletions
diff --git a/app/media/migrations/0002_auto_20211030_1634.py b/app/media/migrations/0002_auto_20211030_1634.py new file mode 100644 index 0000000..abebed9 --- /dev/null +++ b/app/media/migrations/0002_auto_20211030_1634.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.8 on 2021-10-30 16:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('media', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='luxaudio', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='luxgallery', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='luximage', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='luximagesize', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='luxvideo', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/app/pages/admin.py b/app/pages/admin.py index 3c7d900..9ce93dc 100644 --- a/app/pages/admin.py +++ b/app/pages/admin.py @@ -46,7 +46,7 @@ class PageAdmin(admin.ModelAdmin): @admin.register(HomePage) class HomePageAdmin(admin.ModelAdmin): form = LGEntryForm - filter_horizontal = ('popular',) + #filter_horizontal = ('popular',) class Media: js = ('image-loader.js', 'next-prev-links.js') diff --git a/app/pages/migrations/0002_auto_20211030_1634.py b/app/pages/migrations/0002_auto_20211030_1634.py new file mode 100644 index 0000000..7a8649b --- /dev/null +++ b/app/pages/migrations/0002_auto_20211030_1634.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.8 on 2021-10-30 16:34 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('posts', '0002_alter_post_id'), + ('media', '0002_auto_20211030_1634'), + ('pages', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='homepage', + name='image_offset_vertical', + ), + migrations.RemoveField( + model_name='homepage', + name='popular', + ), + migrations.AlterField( + model_name='homepage', + name='featured', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='banner', to='posts.post'), + ), + migrations.AlterField( + model_name='homepage', + name='featured_image', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='media.luximage'), + ), + migrations.AlterField( + model_name='homepage', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='page', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/app/pages/models.py b/app/pages/models.py index 7cf90ba..862a35c 100644 --- a/app/pages/models.py +++ b/app/pages/models.py @@ -44,11 +44,10 @@ class HomePage(models.Model): simple model to control the featured article on the homepage also allows me to fudge the "popular" section to be what I want """ - image_offset_vertical = models.CharField(max_length=20, help_text="add negative top margin to shift image (include css unit)") - featured_image = models.ForeignKey(LuxImage, on_delete=models.CASCADE) + featured_image = models.ForeignKey(LuxImage, on_delete=models.CASCADE, null=True, blank=True) tag_line = models.CharField(max_length=200, null=True, blank=True) - featured = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="banner") - popular = models.ManyToManyField(Post, related_name="popular") + featured = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="banner", null=True, blank=True) + #popular = models.ManyToManyField(Post, related_name="popular") template_name = models.CharField(max_length=200, help_text="full path", null=True, blank=True) diff --git a/app/pages/views.py b/app/pages/views.py index cb91f9b..d876a49 100644 --- a/app/pages/views.py +++ b/app/pages/views.py @@ -34,7 +34,7 @@ class HomePageList(DetailView): def get_context_data(self, **kwargs): # Call the base implementation first to get a context context = super(HomePageList, self).get_context_data(**kwargs) - context['object_list'] = Post.objects.filter(post_type=PostType.JRNL).filter(status__exact=1).order_by('-pub_date').exclude().select_related('location').select_related('featured_image')[1:9] + #context['object_list'] = Post.objects.filter(post_type=PostType.JRNL).filter(status__exact=1).order_by('-pub_date').exclude().select_related('location').select_related('featured_image')[1:9] return context diff --git a/app/posts/admin.py b/app/posts/admin.py index cac3954..27ec145 100644 --- a/app/posts/admin.py +++ b/app/posts/admin.py @@ -33,10 +33,10 @@ class PostAdmin(OSMGeoAdmin): field = super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs) return field - list_display = ('title', 'site', 'post_type', 'pub_date', 'template_name', 'status',) + list_display = ('title', 'post_type', 'pub_date', 'status',) search_fields = ['title', 'body_markdown'] prepopulated_fields = {"slug": ('title',)} - list_filter = ('site', 'post_type', 'pub_date', 'enable_comments', 'status') + list_filter = ('post_type', 'pub_date', 'enable_comments', 'status') filter_horizontal = ('related', 'books',) fieldsets = ( ('Entry', { @@ -47,10 +47,8 @@ class PostAdmin(OSMGeoAdmin): ('pub_date', 'status', 'post_type'), ('slug', 'enable_comments',), 'dek', - 'meta_description', - 'template_name', - ('featured_image','related'), - 'site' + 'meta_description', 'issue', + ('featured_image', 'featured_audio', 'related'), ), 'classes': ( 'show', diff --git a/app/posts/migrations/0002_alter_post_id.py b/app/posts/migrations/0002_alter_post_id.py new file mode 100644 index 0000000..a41f999 --- /dev/null +++ b/app/posts/migrations/0002_alter_post_id.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.8 on 2021-10-30 16:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('posts', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='post', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/app/posts/migrations/0003_auto_20211030_1955.py b/app/posts/migrations/0003_auto_20211030_1955.py new file mode 100644 index 0000000..b54cdd8 --- /dev/null +++ b/app/posts/migrations/0003_auto_20211030_1955.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.8 on 2021-10-30 19:55 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('media', '0002_auto_20211030_1634'), + ('posts', '0002_alter_post_id'), + ] + + operations = [ + migrations.RemoveField( + model_name='post', + name='site', + ), + migrations.RemoveField( + model_name='post', + name='template_name', + ), + migrations.AddField( + model_name='post', + name='featured_audio', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='media.luxaudio'), + ), + migrations.AddField( + model_name='post', + name='issue', + field=models.PositiveIntegerField(null=True), + ), + migrations.AlterField( + model_name='post', + name='post_type', + field=models.IntegerField(choices=[(0, 'Podcast'), (1, 'jrnl'), (2, 'field note')], default=1), + ), + ] diff --git a/app/posts/models.py b/app/posts/models.py index 0d93482..37c4c9b 100644 --- a/app/posts/models.py +++ b/app/posts/models.py @@ -25,7 +25,7 @@ from django_comments.moderation import CommentModerator, moderator from taggit.managers import TaggableManager from normalize.models import RelatedPost -from media.models import LuxImage, LuxImageSize +from media.models import LuxImage, LuxImageSize, LuxAudio from books.models import Book #from fieldnotes.models import FieldNote from taxonomy.models import TaggedItems, Category @@ -37,16 +37,12 @@ def get_upload_path(self, filename): class PostType(models.IntegerChoices): - FIELD_TEST = 0, ('field test') - REVIEW = 1, ('review') - ESSAY = 2, ('essay') - SRC = 3, ('src') - JRNL = 4, ('jrnl') - FIELD_NOTE = 5, ('field note') + PODCAST = 0, ('Podcast') + JRNL = 1, ('jrnl') + FIELD_NOTE = 2, ('field note') class Post(models.Model): - site = models.ForeignKey(Site, on_delete=models.CASCADE) title = models.CharField(max_length=200) short_title = models.CharField(max_length=200, blank=True, null=True) subtitle = models.CharField(max_length=200, blank=True) @@ -68,16 +64,8 @@ class Post(models.Model): ) status = models.IntegerField(choices=PUB_STATUS, default=0) featured_image = models.ForeignKey(LuxImage, on_delete=models.CASCADE, null=True, blank=True) - TEMPLATES = ( - (0, 'single'), - (1, 'double'), - (2, 'single-dark'), - (3, 'double-dark'), - (4, 'single-black'), - (5, 'double-black'), - ) + featured_audio = models.ForeignKey(LuxAudio, on_delete=models.CASCADE, null=True, blank=True) post_type = models.IntegerField(choices=PostType.choices, default=PostType.JRNL) - template_name = models.IntegerField(choices=TEMPLATES, default=0) has_video = models.BooleanField(blank=True, default=False) has_code = models.BooleanField(blank=True, default=False) disclaimer = models.BooleanField(blank=True, default=False) @@ -86,6 +74,7 @@ class Post(models.Model): topics = models.ManyToManyField(Category, blank=True) originally_published_by = models.CharField(max_length=400, null=True, blank=True) originally_published_by_url = models.CharField(max_length=400, null=True, blank=True) + issue = models.PositiveIntegerField(null=True) class Meta: ordering = ('-pub_date',) @@ -95,8 +84,10 @@ class Post(models.Model): return self.title def get_absolute_url(self): - if self.post_type == 0: - return reverse('guides:reviews:review-detail', kwargs={"slug": self.slug}) + if self.post_type == PostType.JRNL: + return reverse('jrnl:detail', kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) + if self.post_type == PostType.PODCAST: + return reverse('podcasts:detail', kwargs={"episode": self.get_issue_str(), "slug": self.slug}) if self.post_type == 1: return reverse('guides:reviews:review-detail', kwargs={"slug": self.slug}) if self.post_type == 2: @@ -105,8 +96,6 @@ class Post(models.Model): return reverse('src:detail', kwargs={"slug": self.slug}) if self.post_type == 5: return reverse('fieldnote:detail', kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) - if self.post_type == PostType.JRNL: - return reverse('jrnl:detail', kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) def comment_period_open(self): return self.enable_comments and datetime.datetime.today() - datetime.timedelta(30) <= self.pub_date @@ -117,6 +106,14 @@ class Post(models.Model): def get_content_type(self): return ContentType.objects.get(app_label="posts", model="post") + def get_issue_str(self): + issue = self.issue + if self.issue < 100: + issue = "0%s" % self.issue + if self.issue < 10: + issue = "00%s" % self.issue + return issue + @property def get_previous_published(self): return self.get_previous_by_pub_date(status__exact=1,post_type=self.post_type) @@ -179,19 +176,19 @@ class Post(models.Model): if self.prologue_html: self.prologue_html = markdown_to_html(self.prologue_markdown) self.has_video = parse_video(self.body_html) - if created and not self.featured_image: - if self.post_type == PostType.FIELD_NOTE: - self.featured_image = extract_main_image(self.body_markdown) - else: - self.featured_image = LuxImage.objects.latest() + #if created and not self.featured_image: + # if self.post_type == PostType.FIELD_NOTE: + # self.featured_image = extract_main_image(self.body_markdown) + # else: + # self.featured_image = LuxImage.objects.latest() old = type(self).objects.get(pk=self.pk) if self.pk else None - if old and old.featured_image != self.featured_image: # Field has changed - if self.featured_image: - s = LuxImageSize.objects.get(name="featured_jrnl") - ss = LuxImageSize.objects.get(name="picwide-med") - self.featured_image.sizes.add(s) - self.featured_image.sizes.add(ss) - self.featured_image.save() + #if old and old.featured_image != self.featured_image: # Field has changed + # if self.featured_image: + # s = LuxImageSize.objects.get(name="featured_jrnl") + # ss = LuxImageSize.objects.get(name="picwide-med") + # self.featured_image.sizes.add(s) + # self.featured_image.sizes.add(ss) + # self.featured_image.save() if old and old.title != self.title or old and old.slug != self.slug: related, c = RelatedPost.objects.get_or_create(model_name=self.get_content_type(), entry_id = self.id, pub_date=self.pub_date) related.title = self.title diff --git a/app/posts/templates/posts/podcast_detail.html b/app/posts/templates/posts/podcast_detail.html new file mode 100644 index 0000000..4fec3b1 --- /dev/null +++ b/app/posts/templates/posts/podcast_detail.html @@ -0,0 +1,108 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load comments %} +{% block pagetitle %}{{object.title|striptags}} - by Scott Gilbertson{% endblock %} +{% block metadescription %}{% autoescape on %}{{object.meta_description|striptags|safe}}{% endautoescape %}{% endblock %} +{%block extrahead%} + <link rel="stylesheet" href="/media/src/solarized.css" type="text/css" media="screen"/> +{%endblock%} + +{% block bodyid %}class="detail single"{% endblock %} +{% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} +{% block primary %}<main role="main"> + <article class="h-entry hentry entry-content content" itemscope itemType="http://schema.org/BlogPosting"> + <header id="header" class="post-header"> + <h1 class="p-name post-title" itemprop="headline">{{object.title|smartypants|safe}}</h1> + <h2 class="post-subtitle">{% if object.subtitle %}{{object.subtitle|smartypants|safe}}{%else%}{{object.meta_description|safe|smartypants|widont}}{%endif%}</h2> + <div class="post-dateline"> + {% if object.originally_published_by %}<h4 class="post-source">Originally Published By: <a href="{{object.originally_published_by_url}}" title="View {{object.title}} on {{object.originally_published_by}}">{{object.originally_published_by}}</a></h4>{%endif%} + <time class="dt-published published dt-updated post-date" datetime="{{object.pub_date|date:'c'}}" itemprop="datePublished">{{object.pub_date|date:"F"}} <span>{{object.pub_date|date:"j, Y"}}</span></time> + <span class="hide" itemprop="author" itemscope itemtype="http://schema.org/Person">by <a class="p-author h-card" href="/about"><span itemprop="name">Scott Gilbertson</span></a></span> + </div> + </header> + + + <div id="article" class="e-content entry-content post-article post-body-{% with object.template_name as t %}{%if t == 0 or t == 2 %}single{%endif%}{%if t == 1 or t == 3 %}double{%endif%}{%endwith%}" itemprop="articleBody"> + {{object.body_html|safe|smartypants|widont}} + </div> + </article> + <div class="entry-footer"> + <aside class="narrow donate"> + <h3>Support</h3> + <p>Want to help support Lulu and Birdie? You can buy the book, or you can donate a few dollars.</p> + <div class="donate-btn"> + <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top"> + <input type="hidden" name="cmd" value="_s-xclick"> + <input type="hidden" name="hosted_button_id" value="HYJFZQSBGJ8QQ"> + <input type="submit" name="submit" title="Donate to luxagraf via PayPal"> + </form> + </div> + <div class="donate-btn"> + <a class="liberapay-btn" href="https://liberapay.com/luxagraf/donate"><span>Donate</span></a> + </div> + </aside> + {% comment %}<aside class="narrow join"> + <h3>Subscribe</h3> + <p>You're reading <code>/src/</code>, a collection of infrequent postings about open source software, linux tools, and other nerdry. If you'd like to join us, drop your email in the form below: </p> + <iframe target='_parent' style="border:none !important; background:white; width:100% !important;" title="embedded form for subscribing the the src newsletter" src="{% url 'lttr:subscribe' slug='range' %}"></iframe> + <p>Unsubscribing is easy. It's <a href="/src/building-your-own-mailing-list-software">self-hosted</a> and <a href="/privacy" title="My privacy policy">respects your privacy</a>. If you don't want an email, there's also <a href="/src/feed.xml">an RSS feed</a>, and it's all archived <a href="/src/">here</a>.</p> + </aside>{% endcomment%} + </div> + {% with object.get_next_published as next %} + {% with object.get_previous_published as prev %} + <nav class="page-navigation"> + <div>{% if prev%} + <span class="label">Previous:</span> + <a href="{{ prev.get_absolute_url }}" rel="prev" title=" {{prev.title}}">{{prev.title|safe}}</a> + </div>{%endif%}{% if next%} + <div> + <span class="label">Next:</span> + <a href="{{ next.get_absolute_url }}" rel="next" title=" {{next.title}}">{{next.title|safe}}</a> + </div>{%endif%} + </nav>{%endwith%}{%endwith%} + {% if object.related.all %}<div class="article-afterward related"> + <div class="related-bottom"> + <h6 class="hedtinycaps">You might also enjoy</h6> + <div class="archive-grid-quad">{% for object in related %} + <div class="archive-grid-card archive-grid-card-simple"> + <a href="{{object.get_absolute_url}}" title="{{object.title}}"> + <div class="card-image-tiny"> + {% if object.featured_image %} + {% include "lib/img_archive.html" with image=object.featured_image nolightbox=True %} + {%endif%} + </div> + <h4 class="p-name card-hed" itemprop="headline">{% if object.title %}{{object.title|safe|smartypants|widont}}{% else %}{{object.common_name}}{%endif%}</h4> + <p class="p-author author hide" itemprop="author"><span class="byline-author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Scott Gilbertson</span></span></p> + <span class="card-smcaps"> + {% if object.location %}<span class="p-location h-adr adr card-location" itemprop="contentLocation" itemscope itemtype="http://schema.org/Place"> + {% if object.location.country_name == "United States" %}{{object.location.state_name}}{%else%}{{object.location.country_name}}{%endif%} + </span>{%endif%} + {% if object.location and object.model_name.model != 'page' %}–{%endif%} + {% if object.model_name.model != 'page' %}<time class="dt-published published dt-updated" datetime="{{object.pub_date|date:'c'}}"><span>{{object.pub_date|date:" Y"}}</span></time>{%endif%} + </span> + </a> + </div> + {% endfor %}</div> + </div> + </div>{%endif%} + </main> + {% if object.enable_comments %} +{% get_comment_count for object as comment_count %} +{%if comment_count > 0 %} +<div class="comment-wrapper"> +<p class="comments-header">{{comment_count}} Comment{{ comment_count|pluralize }}</p> +{% render_comment_list for object %} +{%endif%} +<div class="comment-form-wrapper {%if comment_count > 0%}comment-form-border{%endif%}"> +{% render_comment_form for object %} +</div> +{% else %} +<p class="comments--header" style="text-align: center">Sorry, comments have been disabled for this post.</p> +{%endif%} +</div> +</main> +{% endblock %} +{% block js %} +<script src="/media/js/leaflet-master/leaflet-mod.js"></script> +<script src="/media/js/detail.min.js"></script> +{%endblock%} diff --git a/app/posts/templates/posts/podcast_list.html b/app/posts/templates/posts/podcast_list.html new file mode 100644 index 0000000..8c73db4 --- /dev/null +++ b/app/posts/templates/posts/podcast_list.html @@ -0,0 +1,29 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load pagination_tags %} +{% load comments %} + +{% block pagetitle %}The Lulu and Birdie Podcast{% endblock %} +{% block metadescription %}The Adventures of Lulu, Birdie, and Henry in podcast form - by Scott Gilbertson.{% endblock %} +{% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} +{% block primary %}<main role="main" class="archive-wrapper"> + <div class="archive-intro"> + <h1 class="archive-hed">The Adventures of Lulu, Birdie, and Henry: The Podcast.</h1> + <h2 class="list-subhed">Let's see what happens.</h2> + </div> + + <h1 class="archive-sans">Episodes</h1>{% autopaginate object_list 24 %} + <ul class="archive-list">{% for object in object_list %} + <li class="h-entry hentry archive-list-card archive-list-card-sm" itemscope itemType="http://schema.org/Article"> + <span class="date dt-published card-smcaps">{{object.pub_date|date:"F Y"}}</span> + <a href="{{object.get_absolute_url}}"> + <h2 class="card-hed">{{object.title|safe|smartypants|widont}}</h2> + <p class="p-summary card-lede">{% if object.subtitle %}{{object.subtitle}}{%else%}{{object.meta_description|safe|smartypants|widont}}{%endif%}</p> + </a> + </li> + {%endfor%}</ul> + + + + </main> +{%endblock%} diff --git a/app/posts/templates/posts/src_detail.html b/app/posts/templates/posts/src_detail.html deleted file mode 100644 index 664db36..0000000 --- a/app/posts/templates/posts/src_detail.html +++ /dev/null @@ -1,110 +0,0 @@ -{% extends 'base.html' %} -{% load typogrify_tags %} -{% load comments %} -{% block pagetitle %}{{object.title|striptags}} - by Scott Gilbertson{% endblock %} -{% block metadescription %}{% autoescape on %}{{object.meta_description|striptags|safe}}{% endautoescape %}{% endblock %} -{%block extrahead%} - <meta property="og:type" content="article" /> - <meta property="og:site_name" content="luxagraf:src"/> - <meta property="og:title" content="{{object.title|safe}}" /> - <meta property="og:url" content="https://luxagraf.net{{object.get_absolute_url}}" /> - <meta property="og:image" content=""> - <meta property="og:description" content="{{object.meta_description}}" /> - <meta property="article:published_time" content="{{object.pub_date|date:'c'}}" /> - <meta property="article:author" content="Luxagraf" /> - <meta property="og:site_name" content="Luxagraf:src" /> - <meta property="og:locale" content="en_US" /> - <meta name="twitter:card" content="summary_large_image"/> - <meta name="twitter:site" content="@luxagraf"/> - <meta name="twitter:creator" content="@luxagraf"/> - <link rel="stylesheet" href="/media/src/solarized.css" type="text/css" media="screen"/> -{%endblock%} - -{% block bodyid %}class="src detail single"{% endblock %} -{%block sitesubtitle %}Code Slowly{% endblock%} -{% block breadcrumbs %}<ol class="bl" id="breadcrumbs" itemscope itemtype="http://schema.org/BreadcrumbList"> - <li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> - <a itemprop="item" href="/"> - <span itemprop="name">Home</span> - </a> → - <meta itemprop="position" content="1" /> - </li> - <li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> - <a href="/src/" itemprop="item"> - <span itemprop="name">Src</span> - </a> - <meta itemprop="position" content="2" /> - </li> - </ol>{% endblock %} -{% block primary %}<main role="main"> - <article class="hentry post-article{% with object.get_template_name_display as t %}{%if t == "double" or t == "double-dark" %} post--article--double{%endif%}{%endwith%}" itemscope itemType="http://schema.org/Article"> - <header id="header" class="post-header {% with object.get_template_name_display as t %}{%if t == "double" or t == "double-dark" %}post--header--double{%endif%}{%endwith%}"> - <h1 class="p-name entry-title post--title" itemprop="headline">{%if object.template_name == 1 or object.template_name == 3 %}{{object.title|safe|smartypants}}{%else%}{{object.title|safe|smartypants|widont}}{%endif%}</h1> - <h2 class="post-subtitle">{% if object.subtitle %}{{object.subtitle|smartypants|safe}}{%else%}{{object.meta_description|safe|smartypants|widont}}{%endif%}</h2> - <div class="post-linewrapper"> - {% if object.originally_published_by %}<h4 class="post-source">Originally Published By: <a href="{{object.originally_published_by_url}}" title="View {{object.title}} on {{object.originally_published_by}}">{{object.originally_published_by}}</a></h4>{%endif%} - <time class="dt-published published dt-updated post-date" datetime="{{object.pub_date|date:'c'}}" itemprop="datePublished">{{object.pub_date|date:"F"}} <span>{{object.pub_date|date:"j, Y"}}</span></time> - <span class="hide" itemprop="author" itemscope itemtype="http://schema.org/Person">by <a class="p-author h-card" href="/about"><span itemprop="name">Scott Gilbertson</span></a></span> - </div> - </header> - - - <div id="article" class="e-content entry-content post-body post-body-{% with object.template_name as t %}{%if t == 0 or t == 2 %}single{%endif%}{%if t == 1 or t == 3 %}double{%endif%}{%endwith%}" itemprop="articleBody"> - {{object.body_html|safe|smartypants|widont}} - </div> - </article> - {% if object.slug != 'about' %} - {% with object.get_next_published as next %} - {% with object.get_previous_published as prev %} - <nav id="page-navigation"> - <ul>{% if prev%} - <li id="prev"><span class="bl">Previous:</span> - <a href="{{ prev.get_absolute_url }}" rel="prev" title=" {{prev.title}}">{{prev.title|safe}}</a> - </li>{%endif%}{% if next%} - <li id="next"><span class="bl">Next:</span> - <a href="{{ next.get_absolute_url }}" rel="next" title=" {{next.title}}">{{next.title|safe}}</a> - </li>{%endif%} - </ul> - </nav>{%endwith%}{%endwith%} - {%endif%} - </main> - {% if object.slug != 'about' %} - {% if object.enable_comments %} -{% get_comment_count for object as comment_count %} -{%if comment_count > 0 %} -<p class="comments--header">{{comment_count}} Comment{{ comment_count|pluralize }}</p> -{% render_comment_list for object %} -{%endif%} -<div class="comment--form--wrapper {%if comment_count > 0%}comment-form-border{%endif%}"> -{% render_comment_form for object %} -</div> -{% else %} -<p class="comments--header" style="text-align: center">Sorry, comments have been disabled for this post.</p> -{%endif%} -{%endif%} -{% endblock %} -{% block js %} -<script type="text/javascript"> -window.onload = function() { - {% if object.enable_comments %} -{%if comment_count > 0 %} - //delay loading of gravatar images using noscript data-hash attribute - dataattr = document.getElementsByClassName("datahashloader"); - for(var i=0; i<dataattr.length; i++) { - var c = dataattr[i].parentNode; - var img = document.createElement("img"); - img.src = 'https://images.luxagraf.net/gravcache/' + dataattr[i].getAttribute('data-hash') + '.jpg'; - img.className += "gravatar"; - c.insertBefore(img, c.childNodes[3]); - } -{%endif%} -{%endif%} - {% with object.get_template_name_display as t %}{%if t == "single" or t == "single-dark" %} - createMap(); - var open = false; - {%endif%}{%endwith%} -} -</script> -{% if object.has_code %} -{%endif %} -{% endblock %} diff --git a/app/posts/templates/posts/src_list.html b/app/posts/templates/posts/src_list.html deleted file mode 100644 index 21a8c4e..0000000 --- a/app/posts/templates/posts/src_list.html +++ /dev/null @@ -1,30 +0,0 @@ -{% extends 'base.html' %} -{% load typogrify_tags %} -{% load comments %} - -{% block pagetitle %}Tutorials and tools for building great things{% endblock %} -{% block metadescription %}Tutorials and tools for building great things on the web - by Scott Gilbertson.{% endblock %} -{%block sitesubtitle %}Code Slowly{% endblock%} -{% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} -{% block primary %}<main role="main" id="essay-archive" class="essay-archive archive-list"> - <div class="essay-intro"> - <h2>Tutorials and tools for building great things on the web.</h2> - <p>The indie web is an amazing democratic publishing platform unlike anything in history. The catch is, to avoid serving at the pleasure of the corporate king, you need to know <em>how</em> to publish. That's what these articles are here for, to help you learn how to use independent, community supported open source tools. The web won't last forever, let's build something cool while we can.</p> - <p>Topics include HTML, CSS, Django, Linux, Nginx, Python, Postgresql, free software, and, once, the evil that is Google AMP.</p> - <p>A few of the articles below were previously published in: <em><a href="https://arstechnica.com/">Ars Technica</a></em>, <em><a href="https://www.wired.com/author/scott-gilbertson/">Wired</a></em>, and <em><a href="https://www.theregister.co.uk/Author/Scott-Gilbertson/">The Register</a></em></p> - </div> - <h1 class="topic-hed">Articles</h1> - <ul class="fancy-archive-list">{% for object in object_list %}{% if object.slug != 'about' %} - <li class="h-entry hentry" itemscope itemType="http://schema.org/Article"> - <span class="date dt-published">{{object.pub_date|date:"F Y"}}</span> - <a href="{{object.get_absolute_url}}"> - <h2>{{object.title|safe|smartypants|widont}}</h2> - <p class="p-summary">{% if object.subtitle %}{{object.subtitle}}{%else%}{{object.meta_description|safe|smartypants|widont}}{%endif%}</p> - </a> - </li> - {%endif%}{%endfor%}</ul> - - - - </main> -{%endblock%} diff --git a/app/posts/urls/podcast_urls.py b/app/posts/urls/podcast_urls.py new file mode 100644 index 0000000..9139b55 --- /dev/null +++ b/app/posts/urls/podcast_urls.py @@ -0,0 +1,34 @@ +from django.urls import path, re_path + +from ..views import podcast_views as views + +app_name = "podcasts" + +urlpatterns = [ + path( + r'feed.xml', + views.PodcastRSSFeedView(), + name="feed" + ), + path( + r'topic/<str:slug>', + views.TopicListView.as_view(), + name="list_topics" + ), + path( + r'<str:episode>/<str:slug>', + views.PodcastDetailView.as_view(), + name="detail" + ), + re_path( + r'<int:page>', + views.PodcastListView.as_view(), + name="list" + ), + path( + r'', + views.PodcastListView.as_view(), + {'page':1}, + name="list" + ), +] diff --git a/app/posts/urls/src_urls.py b/app/posts/urls/src_urls.py deleted file mode 100644 index 637d9a6..0000000 --- a/app/posts/urls/src_urls.py +++ /dev/null @@ -1,49 +0,0 @@ -from django.urls import path, re_path - -from ..views import src_views as views - -app_name = "src" - -urlpatterns = [ - path( - r'feed.xml', - views.SrcRSSFeedView(), - name="feed" - ), - path( - r'topic/<str:slug>', - views.TopicListView.as_view(), - name="list_topics" - ), - #path( - # r'books/<str:slug>', - # views.BookDetailView.as_view(), - # name='detail_book' - #), - #path( - # r'books/', - # views.BookListView.as_view(), - # name='list_books' - #), - path( - r'<str:slug>.txt', - views.SrcDetailViewTXT.as_view(), - name="detail-txt" - ), - path( - r'<str:slug>', - views.SrcDetailView.as_view(), - name="detail" - ), - re_path( - r'<int:page>', - views.SrcListView.as_view(), - name="list" - ), - path( - r'', - views.SrcListView.as_view(), - {'page':1}, - name="list" - ), -] diff --git a/app/posts/views/src_views.py b/app/posts/views/podcast_views.py index 990088f..49e25d9 100644 --- a/app/posts/views/src_views.py +++ b/app/posts/views/podcast_views.py @@ -10,29 +10,29 @@ from ..models import Post, PostType from taxonomy.models import Category -class SrcListView(PaginatedListView): +class PodcastListView(PaginatedListView): model = Post - template_name="posts/src_list.html" + template_name="posts/podcast_list.html" def get_queryset(self): - queryset = super(SrcListView, self).get_queryset() - return queryset.filter(post_type=PostType.SRC).filter(status__exact=1).order_by('-pub_date') + queryset = super(PodcastListView, self).get_queryset() + return queryset.filter(post_type=PostType.PODCAST).filter(status__exact=1).order_by('-pub_date') def get_context_data(self, **kwargs): # Call the base implementation first to get a context - context = super(SrcListView, self).get_context_data(**kwargs) + context = super(PodcastListView, self).get_context_data(**kwargs) #context['topics'] = Topic.objects.all() - context['breadcrumbs'] = ['src',] + context['breadcrumbs'] = ['podcast',] return context -class SrcDetailView(DetailView): +class PodcastDetailView(DetailView): model = Post slug_field = "slug" - template_name="posts/src_detail.html" + template_name="posts/podcast_detail.html" -class SrcDetailViewTXT(SrcDetailView): +class PodcastDetailViewTXT(PodcastDetailView): template_name = "posts/jrnl_detail.txt" @@ -49,14 +49,14 @@ class TopicListView(ListView): return context -class SrcRSSFeedView(Feed): - title = "luxagraf:src Code and Technology" - link = "/src/" +class PodcastRSSFeedView(Feed): + title = "The Lulu and Birdie Podcast" + link = "/podcasts/" description = "Latest postings to luxagraf.net/src" description_template = 'feeds/blog_description.html' def items(self): - return SrcPost.objects.filter(status__exact=1).order_by('-pub_date')[:10] + return Post.objects.filter(post_type=PostType.PODCAST).filter(status__exact=1).order_by('-pub_date')[:10] """ diff --git a/config/base_urls.py b/config/base_urls.py index 8a9c3ef..f06651a 100644 --- a/config/base_urls.py +++ b/config/base_urls.py @@ -33,6 +33,9 @@ urlpatterns = [ path(r'feed.xml', PostRSSFeedView(),name="feed"), path(r'sitemap.xml', sitemap, {'sitemaps': sitemaps}), #path(r'newsletter/', include('lttr.urls')), + path(r'podcast/', include('posts.urls.podcast_urls')), + re_path(r'^podcast/$', RedirectView.as_view(url='/reviews/')), + path(r'podcasts/', include('posts.urls.podcast_urls')), path(r'book-notes/', include('books.urls')), path(r'<slug>.txt', PageDetailTXTView.as_view()), path(r'<slug>', include('pages.urls', namespace='pages')), |