From 164eee8075761c46add169fe5631f45f1ec8746d Mon Sep 17 00:00:00 2001 From: luxagraf Date: Sun, 25 Feb 2024 16:43:51 -0600 Subject: jrnl: re-arranged to make Range a repository for everything. --- app/posts/admin.py | 42 +++++++- app/posts/migrations/0025_guide.py | 38 +++++++ app/posts/migrations/0026_guide_related.py | 19 ++++ ...27_remove_post_template_name_post_post_topic.py | 22 ++++ app/posts/models.py | 53 +++++++--- app/posts/templates/posts/essay_detail.html | 8 +- app/posts/templates/posts/essay_list.html | 7 +- app/posts/templates/posts/guide_base.html | 18 ++-- app/posts/templates/posts/guide_detail.html | 83 ++------------- app/posts/templates/posts/guide_post_detail.html | 115 +++++++++++++++++++++ app/posts/templates/posts/jrnl_list.html | 17 ++- app/posts/templates/posts/range_detail.html | 2 +- app/posts/templates/posts/range_list.html | 42 +++----- app/posts/templates/posts/range_listold.html | 43 ++++++++ app/posts/templates/posts/review_list.html | 21 ++++ app/posts/urls/guide_urls.py | 14 ++- app/posts/urls/range_urls.py | 10 +- app/posts/urls/review_urls.py | 10 +- app/posts/views/essay_views.py | 3 + app/posts/views/film_views.py | 3 + app/posts/views/guide_views.py | 48 +++------ app/posts/views/range_views.py | 18 +--- app/posts/views/repair_views.py | 53 ++++++++++ app/posts/views/review_views.py | 53 ++++++++++ 24 files changed, 539 insertions(+), 203 deletions(-) create mode 100644 app/posts/migrations/0025_guide.py create mode 100644 app/posts/migrations/0026_guide_related.py create mode 100644 app/posts/migrations/0027_remove_post_template_name_post_post_topic.py create mode 100644 app/posts/templates/posts/guide_post_detail.html create mode 100644 app/posts/templates/posts/range_listold.html create mode 100644 app/posts/templates/posts/review_list.html create mode 100644 app/posts/views/repair_views.py create mode 100644 app/posts/views/review_views.py (limited to 'app/posts') diff --git a/app/posts/admin.py b/app/posts/admin.py index 5a51f44..1153e81 100644 --- a/app/posts/admin.py +++ b/app/posts/admin.py @@ -4,7 +4,7 @@ from django.contrib.gis.admin import OSMGeoAdmin from django.contrib.contenttypes.admin import GenericStackedInline from utils.widgets import AdminImageWidget, LGEntryForm -from .models import Post, Trip +from .models import Post, Trip, Guide from media.models import LuxImage from utils.util import get_latlon @@ -34,7 +34,7 @@ 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', 'site', 'post_type', 'pub_date', 'status',) search_fields = ['title', 'body_markdown'] prepopulated_fields = {"slug": ('title',)} list_filter = ('site', 'post_type', 'pub_date', 'enable_comments', 'status') @@ -45,12 +45,11 @@ class PostAdmin(OSMGeoAdmin): ('title', 'short_title'), ('subtitle', 'trip'), 'body_markdown', - ('pub_date', 'status', 'post_type'), + ('pub_date', 'status', 'post_type', 'post_topic'), ('slug', 'enable_comments',), 'point', 'dek', 'meta_description', - 'template_name', ('featured_image','related'), 'site' ), @@ -126,3 +125,38 @@ class TripAdmin(OSMGeoAdmin): css = { "all": ("my_styles.css",) } + + +@admin.register(Guide) +class GuideAdmin(OSMGeoAdmin): + form = LGEntryForm + list_display = ('title', 'is_featured', 'slug' ) + prepopulated_fields = {'slug': ('title',)} + search_fields = ('title',) + filter_horizontal = ('posts',) + fieldsets = ( + ('', { + 'fields': ( + 'title', + 'subtitle', + 'seo_title', + 'body_markdown', + 'posts', + ('slug', 'status'), + 'dek', + 'meta_description', + 'featured_image', + ('is_featured', 'related') + ), + 'classes': ( + 'show', + 'extrapretty' + ) + }), + ) + + class Media: + js = ('image-loader.js', 'next-prev-links.js') + css = { + "all": ("my_styles.css",) + } diff --git a/app/posts/migrations/0025_guide.py b/app/posts/migrations/0025_guide.py new file mode 100644 index 0000000..636e2cd --- /dev/null +++ b/app/posts/migrations/0025_guide.py @@ -0,0 +1,38 @@ +# Generated by Django 4.2.7 on 2024-02-25 10:20 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('media', '0008_auto_20201202_1155'), + ('posts', '0024_alter_trip_options_trip_dek'), + ] + + operations = [ + migrations.CreateModel( + name='Guide', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('subtitle', models.CharField(blank=True, max_length=200)), + ('seo_title', models.CharField(blank=True, max_length=200)), + ('slug', models.SlugField()), + ('body_markdown', models.TextField()), + ('body_html', models.TextField(blank=True)), + ('dek', models.TextField(blank=True, null=True)), + ('meta_description', models.CharField(blank=True, max_length=256)), + ('last_updated', models.DateTimeField(auto_now=True)), + ('is_featured', models.BooleanField(blank=True, default=False)), + ('status', models.IntegerField(choices=[(0, 'Draft'), (1, 'Published')], default=0)), + ('featured_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='media.luximage')), + ('posts', models.ManyToManyField(blank=True, to='posts.post')), + ], + options={ + 'ordering': ('-last_updated',), + 'get_latest_by': 'last_updated', + }, + ), + ] diff --git a/app/posts/migrations/0026_guide_related.py b/app/posts/migrations/0026_guide_related.py new file mode 100644 index 0000000..11f0e56 --- /dev/null +++ b/app/posts/migrations/0026_guide_related.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.7 on 2024-02-25 10:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('normalize', '0004_relatedpost_post_type'), + ('posts', '0025_guide'), + ] + + operations = [ + migrations.AddField( + model_name='guide', + name='related', + field=models.ManyToManyField(blank=True, to='normalize.relatedpost'), + ), + ] diff --git a/app/posts/migrations/0027_remove_post_template_name_post_post_topic.py b/app/posts/migrations/0027_remove_post_template_name_post_post_topic.py new file mode 100644 index 0000000..43dda71 --- /dev/null +++ b/app/posts/migrations/0027_remove_post_template_name_post_post_topic.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.7 on 2024-02-25 11:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('posts', '0026_guide_related'), + ] + + operations = [ + migrations.RemoveField( + model_name='post', + name='template_name', + ), + migrations.AddField( + model_name='post', + name='post_topic', + field=models.IntegerField(choices=[(0, 'spirit'), (1, 'craft'), (2, 'tools')], default=0), + ), + ] diff --git a/app/posts/models.py b/app/posts/models.py index 2ad995d..2726949 100644 --- a/app/posts/models.py +++ b/app/posts/models.py @@ -76,6 +76,12 @@ class PostType(models.IntegerChoices): FIELD_NOTE = 5, ('field note') GUIDE = 6, ('guide') FILM = 7, ('film') + HOWTO = 8, ('how to') + +class PostTopic(models.IntegerChoices): + SPIRIT = 0, ('spirit') + CRAFT = 1, ('craft') + TOOLS = 2, ('tools') class Post(models.Model): @@ -101,16 +107,8 @@ class Post(models.Model): ) status = models.IntegerField(choices=PUB_STATUS, default=0) featured_image = models.ForeignKey(LuxImage, on_delete=models.SET_NULL, null=True, blank=True) - TEMPLATES = ( - (0, 'single'), - (1, 'double'), - (2, 'single-dark'), - (3, 'double-dark'), - (4, 'single-black'), - (5, 'double-black'), - ) post_type = models.IntegerField(choices=PostType.choices, default=PostType.JRNL) - template_name = models.IntegerField(choices=TEMPLATES, default=0) + post_topic = models.IntegerField(choices=PostTopic.choices, default=PostTopic.SPIRIT) has_video = models.BooleanField(blank=True, default=False) has_code = models.BooleanField(blank=True, default=False) disclaimer = models.BooleanField(blank=True, default=False) @@ -138,15 +136,12 @@ class Post(models.Model): return reverse('film:detail', kwargs={"slug": self.slug}) if self.post_type == PostType.ESSAY: return reverse('essays:detail', kwargs={"slug": self.slug}) - if self.post_type == PostType.RANGE: - m = NewsletterMailing.objects.get(post__id=self.pk) - return reverse('range:range-detail', kwargs={"issue": m.get_issue_str(), "slug": self.slug}) if self.post_type == PostType.SRC: return reverse('src:detail', kwargs={"slug": self.slug}) if self.post_type == PostType.FIELD_NOTE: return reverse('fieldnote:detail', kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) if self.post_type == PostType.GUIDE: - return reverse('guides:guide-detail', kwargs={"topic": str(self.topics.all()[0]).lower(), "slug": self.slug}) + return reverse('guides:guide-post-detail', kwargs={"topic": self.guide_set.all()[0].slug, "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}) @@ -264,6 +259,38 @@ class PostModerator(CommentModerator): return True moderator.register(Post, PostModerator) + +class Guide(models.Model): + title = models.CharField(max_length=200) + subtitle = models.CharField(max_length=200, blank=True) + seo_title = models.CharField(max_length=200, blank=True) + slug = models.SlugField() + body_markdown = models.TextField() + body_html = models.TextField(blank=True) + dek = models.TextField(null=True, blank=True) + meta_description = models.CharField(max_length=256, blank=True) + last_updated = models.DateTimeField(auto_now=True) + is_featured = models.BooleanField(blank=True, default=False) + PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) + status = models.IntegerField(choices=PUB_STATUS, default=0) + featured_image = models.ForeignKey(LuxImage, on_delete=models.SET_NULL, null=True, blank=True) + posts = models.ManyToManyField(Post, blank=True) + related = models.ManyToManyField(RelatedPost, blank=True) + + class Meta: + ordering = ('-last_updated',) + get_latest_by = 'last_updated' + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse('guides:guide-detail', kwargs={"slug": self.slug}) + + @receiver(comment_was_posted, sender=Comment) def cache_gravatar(sender, comment, **kwargs): gravatar_exists = has_gravatar(comment.email) diff --git a/app/posts/templates/posts/essay_detail.html b/app/posts/templates/posts/essay_detail.html index 42d06a2..7380c7e 100644 --- a/app/posts/templates/posts/essay_detail.html +++ b/app/posts/templates/posts/essay_detail.html @@ -14,15 +14,15 @@

{{object.title|smartypants|safe}}

{% if object.subtitle %}

{{object.subtitle|smartypants|safe}}

{%endif%} -
diff --git a/app/posts/templates/posts/essay_list.html b/app/posts/templates/posts/essay_list.html index 6c9820d..0b516a6 100644 --- a/app/posts/templates/posts/essay_list.html +++ b/app/posts/templates/posts/essay_list.html @@ -3,11 +3,10 @@ {% block pagetitle %}Notes and Essays On Living - By Scott Gilbertson {% endblock %} {% block metadescription %}Essays and stories on self-reliance, DIY, repair, tools, birding, walking, living well, and other ephemera.{% endblock %} {% block breadcrumbs %}{% if breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{%endif%}{% endblock %} -{% block primary %}
+{% block primary %}
-

Notes & Essays

-

Être fort pour être utile

-

Essays and stories on self-reliance, DIY, repair, tools, birding, walking, living well, and other bric-à-brac. Please, enjoy.

+

Spirit

+

Once Spirit meant "breath of a god," and therefore "inspiration; breath of life," hence life itself. Spirit animates us and everything we do; the why behind the what and how.

    {% for object in object_list %}
  • diff --git a/app/posts/templates/posts/guide_base.html b/app/posts/templates/posts/guide_base.html index aef4cf0..d8ccc98 100644 --- a/app/posts/templates/posts/guide_base.html +++ b/app/posts/templates/posts/guide_base.html @@ -2,28 +2,28 @@ {% load typogrify_tags %} {% load html5_datetime %} {% load pagination_tags %} -{% block pagetitle %}Advice, Tools, Tips, and Tricks for Full Time Van or RV Life.{% endblock %} -{% block metadescription %}Guides for fellow travelers: tools, tips, and tricks to make life on the road in an RV or Van easier and more enjoyable.{% endblock %} +{% block pagetitle %}Advice, Tools, Tips, and Tricks.{% endblock %} +{% block metadescription %}{% endblock %} {% block primary %}
    -

    Guides and How-Tos

    -

    Advice, Tools, Tips, and Tricks for Life.

    +

    Guides and How-Tos

    +

    Advice, Tools, Tips, and Tricks for Life.

    I don't know how many of these I'll do, but I wanted to have a place to share some things I've learned, so I made this page. So far, just some thoughts on photography and how to use the Darktable image editor.

    {%comment%}

    I don't want to tell you how to travel. Everyone is different. Besides, even after twenty some odd years of travel, I am still learning.

    I've always been most inspired by wandering monks and nuns, those who walked or sailed with next to nothing and survived. Mostly. Today most of us are not that skilled or strong of will, but keeping that example in mind is helpful. The less stuff you travel with the better off you are. Up to a point. Having the right tools is important. The right tools make life easier and more fun.

    I put this together to help you find the tools you need. These aren't casual reviews. These are things I have spent years seeking out, using, and refining. In the end what you need are not things, but strategies and tools that allow you to create solutions to problems.

    {%endcomment%}
    -
      + {% comment %} {% autopaginate object_list 30 %} diff --git a/app/posts/templates/posts/guide_detail.html b/app/posts/templates/posts/guide_detail.html index af0e649..28ff563 100644 --- a/app/posts/templates/posts/guide_detail.html +++ b/app/posts/templates/posts/guide_detail.html @@ -18,87 +18,26 @@ - Guides + Guides - {{topic}} + {{object.title}} {% endblock %} {% block primary %}
      -
      -
      -

      {{object.title|smartypants|safe}}

      - {% if object.subtitle %}

      {{object.subtitle|smartypants|safe}}

      {%endif%} - -
      -
      - {% if object.prologue_html %}
      - {{object.prologue_html|smartypants|safe}} -

      {%endif%} - {{object.body_html|safe|smartypants}} -
      -
      - {% if object.related.all %}
      - -
      {%endif%} - - {% if object.enable_comments %} -{% get_comment_count for object as comment_count %} -{%if comment_count > 0 %} -
      -

      {{comment_count}} Comment{{ comment_count|pluralize }}

      -{% render_comment_list for object %} -{%endif%} -
      -{% render_comment_form for object %} -
      -{% else %} -

      Sorry, comments have been disabled for this post.

      -{%endif%} -
      {% endblock %} {% block js %} diff --git a/app/posts/templates/posts/guide_post_detail.html b/app/posts/templates/posts/guide_post_detail.html new file mode 100644 index 0000000..42d06a2 --- /dev/null +++ b/app/posts/templates/posts/guide_post_detail.html @@ -0,0 +1,115 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load comments %} +{%block htmlclass%}class="detail single"{%endblock%} +{% block pagetitle %}{{object.title|title|smartypants|safe}} - by Scott Gilbertson{% endblock %} + +{% block metadescription %}{% autoescape on %}{{object.meta_description|striptags|safe}}{% endautoescape %}{% endblock %}{%block extrahead%} + +{% if object.has_code %} {%endif %} +{%endblock%} +{% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} +{% block primary %}
      +
      +
      +

      {{object.title|smartypants|safe}}

      + {% if object.subtitle %}

      {{object.subtitle|smartypants|safe}}

      {%endif%} + +
      +
      + {% if object.prologue_html %}
      + {{object.prologue_html|smartypants|safe}} +

      {%endif%} + {{object.body_html|safe|smartypants}} + {% if object.epilogue_html %}
      + {{object.epilogue_html|smartypants|safe}} +
      {%endif%} +
      + {%if wildlife or object.field_notes.all or object.books.all %}{%endif%} +
      +
      + {% if object.related.all %}
      + +
      {%endif%} + {% comment %}
      +
      If you enjoyed this, you should join the mailing list…
      + {% include 'mailing_list.html' %} +
      {% endcomment %} + {% if object.enable_comments %} +{% get_comment_count for object as comment_count %} +{%if comment_count > 0 %} +
      +

      {{comment_count}} Comment{{ comment_count|pluralize }}

      +{% render_comment_list for object %} +{%endif%} +
      +{% render_comment_form for object %} +
      +{% else %} +

      Sorry, comments have been disabled for this post.

      +
      +{%endif%} + +{% endblock %} +{% block js %} + +{{ block.super }} +{%endblock%} diff --git a/app/posts/templates/posts/jrnl_list.html b/app/posts/templates/posts/jrnl_list.html index 6b4411f..a5e9163 100644 --- a/app/posts/templates/posts/jrnl_list.html +++ b/app/posts/templates/posts/jrnl_list.html @@ -5,8 +5,20 @@ {% block metadescription %}{% if region %}Travel writing, essays and dispatches from {{region.name|title|smartypants|safe}}{%else%}Travel writing, essays and dispatches from around the world{%endif%} Page {{page}}{% endblock %} {%block bodyid%}id="writing" class="archive"{%endblock%} {% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} -{% block primary %}
      -

      {% if region %}Journal entries from {%if region.name == 'United States'%}the United States{%else%}{{region.name|title|smartypants|safe}}{%endif%}{%else%}Journal {%endif%}

      {% autopaginate object_list 24 %} {% for object in object_list %} +{% block primary %}
      +
      +

      Psst, Wanna Join the Friends of a Long Year?

      + +

      Say what?

      +

      Friends of a Long Year is a private mailing list bringing stories to your inbox like it's still 1995. It's written in the spirit of Mary Austin. It was originally called Place Without a Postcard, which does a better job of summarizing what I like to write about. Friends is delivered roughly twice a month.

      + +
      +

      Archive

      {% autopaginate object_list 24 %} + +
      {%endwith%}{%endwith%} {% if object.related.all %}
      diff --git a/app/posts/templates/posts/range_list.html b/app/posts/templates/posts/range_list.html index 43275c6..09ad56d 100644 --- a/app/posts/templates/posts/range_list.html +++ b/app/posts/templates/posts/range_list.html @@ -3,38 +3,24 @@ {% block pagetitle %}Luxagraf | Range {% endblock %} {% block metadescription %}An weekly mailing list about living outdoors, photography, literature, music, vintage vehicles, and other ephemera.{% endblock %} {% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} -{% block primary %} -
      {% for object in object_list %}{% if forloop.first %} -
      - {%with image=object.featured_image%} - {{image.alt}} photographed by {% if image.photo_credit_source %}{{image.photo_credit_source}}{%else%}luxagraf{%endif%} - {%endwith%}{%endif%}{%endfor%} -
      +{% block primary %}
      -

      Range

      +

      Subscribe to Range

      +

      A weekly post, ranging.

      -

      Please join us by dropping your email in the form below:

      - -

      Range is a weekly mailing of photographs and words.

      -

      I like to write about things tangential to living on the road, but didn't want to clutter up the Journal with extraneous stuff. I had this newsletter originally as a photo newsletter, but I wanted to let myself, ahem, range a little more than that. You can browse the archives below to see if it interests you, and sign up if it does.

      -

      Unsubscribing is easy. It's self-hosted and respects your privacy. If you don't want an email, there's also an RSS feed, and it's all archived below.

      -

      There's also the Friends of a Long Year newsletter if you want some stories about life on the road in your inbox. You can also sign up to get a postcard from us on the road

      +

      Range is a weekly mailing about life and how to live it. We talk about the intersection of Spirit, Craft, and Tools. Browse the archive below. If you like what you see, join us.

      +

      Être fort pour être utile

      -

      Ranges

      -
      {% for object in object_list %} - {% endfor %} + Filed Under: {{object.get_post_topic_display}}{% for obj in object.topics.all %}{%if forloop.last or forloop.first %}, {%endif%}{{obj}}{%endfor%} + {%endfor%}
      {%endblock%} diff --git a/app/posts/templates/posts/range_listold.html b/app/posts/templates/posts/range_listold.html new file mode 100644 index 0000000..43275c6 --- /dev/null +++ b/app/posts/templates/posts/range_listold.html @@ -0,0 +1,43 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% block pagetitle %}Luxagraf | Range {% endblock %} +{% block metadescription %}An weekly mailing list about living outdoors, photography, literature, music, vintage vehicles, and other ephemera.{% endblock %} +{% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} +{% block primary %} +
      {% for object in object_list %}{% if forloop.first %} +
      + {%with image=object.featured_image%} + {{image.alt}} photographed by {% if image.photo_credit_source %}{{image.photo_credit_source}}{%else%}luxagraf{%endif%} + {%endwith%}{%endif%}{%endfor%} +
      +
      +

      Range

      +

      A weekly post, ranging.

      +

      Please join us by dropping your email in the form below:

      + +

      Range is a weekly mailing of photographs and words.

      +

      I like to write about things tangential to living on the road, but didn't want to clutter up the Journal with extraneous stuff. I had this newsletter originally as a photo newsletter, but I wanted to let myself, ahem, range a little more than that. You can browse the archives below to see if it interests you, and sign up if it does.

      +

      Unsubscribing is easy. It's self-hosted and respects your privacy. If you don't want an email, there's also an RSS feed, and it's all archived below.

      +

      There's also the Friends of a Long Year newsletter if you want some stories about life on the road in your inbox. You can also sign up to get a postcard from us on the road

      +
      +

      Ranges

      +
      {% for object in object_list %} + {% endfor %} +
      +
      +{%endblock%} + +

      If you're not familiar, darktable is open source raw image developer. It's free, you can download a copy for Linux, macOS, or Windows. The darktable user manual is very helpful if you're brand new. I also recommend Bruce Williams' darktable videos, and Boris Hajdukovic's videos, which were the inspiration for what you see here.

      +

      I'm no expert either, so feel free to hit reply and let me know if I get something wrong.

      diff --git a/app/posts/templates/posts/review_list.html b/app/posts/templates/posts/review_list.html new file mode 100644 index 0000000..5dcaa72 --- /dev/null +++ b/app/posts/templates/posts/review_list.html @@ -0,0 +1,21 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% block pagetitle %}Notes and Essays On Living - By Scott Gilbertson {% endblock %} +{% block metadescription %}Essays and stories on self-reliance, DIY, repair, tools, birding, walking, living well, and other ephemera.{% endblock %} +{% block breadcrumbs %}{% if breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{%endif%}{% endblock %} +{% block primary %}
      +
      +

      Tools

      +

      At some point the wrench must be turned, the shutter clicked, the paper scratched. The right tool makes all the difference. In decades of testing, these are the best I've used.

      +
      + +
      +{%endblock%} diff --git a/app/posts/urls/guide_urls.py b/app/posts/urls/guide_urls.py index f3891e3..5e2b37e 100644 --- a/app/posts/urls/guide_urls.py +++ b/app/posts/urls/guide_urls.py @@ -10,16 +10,20 @@ urlpatterns = [ r'', views.GuideListView.as_view(), {'page':1}, - name="guide-base" + name="guide-list" ), path( - r'/', - views.GuideTopicListView.as_view(), - {'page':1}, - name="guides-by-topic" + r'/', + views.GuideListView.as_view(), + name="guide-list" ), path( r'/', + views.GuidePostDetailView.as_view(), + name="guide-post-detail" + ), + path( + r'/', views.GuideDetailView.as_view(), name="guide-detail" ), diff --git a/app/posts/urls/range_urls.py b/app/posts/urls/range_urls.py index 16655d6..e035a25 100644 --- a/app/posts/urls/range_urls.py +++ b/app/posts/urls/range_urls.py @@ -11,15 +11,15 @@ urlpatterns = [ views.RangeRSSFeedView(), name="feed" ), - path( - r'/', - views.RangeDetailView.as_view(), - name="range-detail" - ), path( r'', views.RangeListView.as_view(), {'page':1}, name="range-list" ), + path( + r'', + views.RangeListView.as_view(), + name="range-list" + ), ] diff --git a/app/posts/urls/review_urls.py b/app/posts/urls/review_urls.py index 6b78e43..3c8368d 100644 --- a/app/posts/urls/review_urls.py +++ b/app/posts/urls/review_urls.py @@ -1,28 +1,28 @@ from django.urls import path, re_path -from ..views import guide_views as views +from ..views import review_views as views app_name = "reviews" urlpatterns = [ path( r'', - views.PostDetailView.as_view(), + views.ReviewDetailView.as_view(), name="review-detail" ), path( r'.txt', - views.PostDetailViewTXT.as_view(), + views.ReviewDetailViewTXT.as_view(), name="review-detail-txt" ), path( r'/', - views.ReviewsListView.as_view(), + views.ReviewListView.as_view(), name="review-list" ), path( r'', - views.ReviewsListView.as_view(), + views.ReviewListView.as_view(), {'page':1}, name="review-list" ), diff --git a/app/posts/views/essay_views.py b/app/posts/views/essay_views.py index ca1697f..02a1087 100644 --- a/app/posts/views/essay_views.py +++ b/app/posts/views/essay_views.py @@ -1,6 +1,7 @@ from django.views.generic import ListView from django.views.generic.detail import DetailView from django.contrib.syndication.views import Feed +from django.urls import reverse from django.apps import apps from django.conf import settings @@ -43,6 +44,8 @@ class EssayDetailView(LuxDetailView): model = apps.get_model(obj.model_name.app_label, obj.model_name.model) related.append(model.objects.get(slug=obj.slug, pub_date=obj.pub_date)) context['related'] = related + context['breadcrumbs'] = ('Range',) + context['crumb_url'] = reverse('range:range-list') return context def get_template_names(self): diff --git a/app/posts/views/film_views.py b/app/posts/views/film_views.py index 3122240..48bdaa4 100644 --- a/app/posts/views/film_views.py +++ b/app/posts/views/film_views.py @@ -1,6 +1,7 @@ from django.views.generic import ListView from django.views.generic.detail import DetailView from django.contrib.syndication.views import Feed +from django.urls import reverse from django.apps import apps from django.conf import settings @@ -43,6 +44,8 @@ class FilmDetailView(LuxDetailView): model = apps.get_model(obj.model_name.app_label, obj.model_name.model) related.append(model.objects.get(slug=obj.slug, pub_date=obj.pub_date)) context['related'] = related + context['breadcrumbs'] = ('Range',) + context['crumb_url'] = reverse('range:range-list') return context def get_template_names(self): diff --git a/app/posts/views/guide_views.py b/app/posts/views/guide_views.py index 641da66..e19a7db 100644 --- a/app/posts/views/guide_views.py +++ b/app/posts/views/guide_views.py @@ -7,7 +7,7 @@ from django.conf import settings from utils.views import PaginatedListView, LuxDetailView -from ..models import Post, PostType +from ..models import Guide, Post, PostType from taxonomy.models import Category @@ -15,44 +15,18 @@ class GuideListView(PaginatedListView): """ Return a list of Entries in reverse chronological order """ - model = Post + model = Guide template_name = "posts/guide_base.html" def get_queryset(self): queryset = super(GuideListView, self).get_queryset() - return queryset.filter(status__exact=1).filter(post_type__in=[PostType.REVIEW,PostType.GUIDE]).order_by('-pub_date').prefetch_related('location').prefetch_related('featured_image') - - -class GuideTopicListView(PaginatedListView): - """ - Return a list of Posts by topic in reverse chronological order - """ - model = Post - template_name = "posts/guide_by_topic.html" - - def get_queryset(self): - queryset = super(GuideTopicListView, self).get_queryset() - topic = Category.objects.get(slug=self.kwargs['topic']) - return queryset.filter(status__exact=1).filter(topics__slug=topic.slug).order_by('-pub_date').prefetch_related('featured_image') - - def get_context_data(self, **kwargs): - context = super(GuideTopicListView, self).get_context_data(**kwargs) - topic = Category.objects.get(slug=self.kwargs['topic']) - context['topic'] = topic - context['breadcrumbs'] = ('Guides', topic.name ) - context['crumb_url'] = reverse('guides:guide-base') - - Category.objects.get(slug=self.kwargs['topic']) - return context + return queryset.filter(status__exact=1) class GuideDetailView(LuxDetailView): - model = Post + model = Guide slug_field = "slug" - def get_template_names(self): - obj = self.get_object() - return ["posts/%s_detail.html" % obj.get_post_type_display(), 'posts/post_detail.html'] def get_context_data(self, **kwargs): context = super(GuideDetailView, self).get_context_data(**kwargs) @@ -61,8 +35,14 @@ class GuideDetailView(LuxDetailView): model = apps.get_model(obj.model_name.app_label, obj.model_name.model) related.append(model.objects.get(slug=obj.slug, pub_date=obj.pub_date)) context['related'] = related - topic = Category.objects.get(slug=self.kwargs['topic']) - context['topic'] = topic - context['breadcrumbs'] = ('Guides', topic.name ) - context['crumb_url'] = reverse('guides:guide-base') + context['breadcrumbs'] = ('Guides', self.object.title ) + context['crumb_url'] = reverse('guides:guide-list') return context + + +class GuidePostDetailView(LuxDetailView): + model = Post + slug_field = "slug" + template_name = "posts/guide_post_detail.html" + + diff --git a/app/posts/views/range_views.py b/app/posts/views/range_views.py index da3b61f..f196e5e 100644 --- a/app/posts/views/range_views.py +++ b/app/posts/views/range_views.py @@ -18,29 +18,13 @@ from locations.models import LuxCheckIn, Country, Region, Location from sightings.models import Sighting -class RangeDetailView(LuxDetailView): - model = Post - slug_field = "slug" - template_name = "posts/range_detail.html" - - def get_context_data(self, **kwargs): - context = super(RangeDetailView, self).get_context_data(**kwargs) - related = [] - for obj in self.object.related.all(): - model = apps.get_model(obj.model_name.app_label, obj.model_name.model) - related.append(model.objects.get(slug=obj.slug, pub_date=obj.pub_date)) - context['related'] = related - context['mailing'] = NewsletterMailing.objects.get(post__id=self.object.id) - return context - - class RangeListView(PaginatedListView): """ Return a list of Newsletter posts in reverse chronological order """ model = Post template_name = "posts/range_list.html" - queryset = Post.objects.filter(post_type=PostType.RANGE,status=1).order_by('-pub_date') + queryset = Post.objects.filter(post_type__in=[PostType.ESSAY,PostType.FILM,PostType.HOWTO,PostType.REVIEW],status=1).order_by('-pub_date') def get_context_data(self, **kwargs): context = super(RangeListView, self).get_context_data(**kwargs) diff --git a/app/posts/views/repair_views.py b/app/posts/views/repair_views.py new file mode 100644 index 0000000..0a5eabf --- /dev/null +++ b/app/posts/views/repair_views.py @@ -0,0 +1,53 @@ +from django.views.generic import ListView +from django.views.generic.detail import DetailView +from django.views.generic.dates import DateDetailView +from django.urls import reverse +from django.views.generic.dates import YearArchiveView, MonthArchiveView +from django.contrib.syndication.views import Feed +from django.apps import apps +from django.shortcuts import get_object_or_404 +from django.conf import settings +from django.db.models import Q + +from utils.views import PaginatedListView, LuxDetailView + +#from ..models import Entry, HomepageCurrator, Home +from ..models import Post, PostType +from locations.models import LuxCheckIn, Country, Region, Location +from sightings.models import Sighting + + +class RepairStoryDetailView(LuxDetailView): + model = Post + slug_field = "slug" + template_name = "posts/repair_detail.html" + + +class RepairStoryListView(PaginatedListView): + """ + Return a list of Newsletter posts in reverse chronological order + """ + model = Post + template_name = "posts/repair_list.html" + + def get_context_data(self, **kwargs): + context = super(FriendsListView, self).get_context_data(**kwargs) + context['breadcrumbs'] = ['repair',] + return context + + +class FriendsRSSFeedView(Feed): + title = "Friends of a Long Year" + link = "/range/" + description = "Friends of a Long Year: A monthly newsletter" + description_template = 'feeds/blog_description.html' + + def items(self): + return Post.objects.filter(status__exact=1).filter(post_type=PostType.FRIENDS).order_by('-pub_date')[:10] + + def item_pubdate(self, item): + """ + Takes an item, as returned by items(), and returns the item's + pubdate. + """ + return item.pub_date diff --git a/app/posts/views/review_views.py b/app/posts/views/review_views.py new file mode 100644 index 0000000..353a5e9 --- /dev/null +++ b/app/posts/views/review_views.py @@ -0,0 +1,53 @@ +from django.views.generic import ListView +from django.views.generic.detail import DetailView +from django.contrib.syndication.views import Feed +from django.urls import reverse +from django.apps import apps +from django.conf import settings + +from utils.views import PaginatedListView, LuxDetailView + +from ..models import Post, PostType +from taxonomy.models import Category + + +class ReviewListView(PaginatedListView): + model = Post + template_name = "posts/review_list.html" + + def get_queryset(self): + queryset = super(ReviewListView, self).get_queryset() + return queryset.filter(site__domain='luxagraf.net').filter(post_type__in=[PostType.REVIEW]).filter(status__exact=1).order_by('-pub_date').prefetch_related('location').prefetch_related('featured_image') + + def get_context_data(self, **kwargs): + ''' + override for custom breadcrumb path + ''' + # Call the base implementation first to get a context + context = super(ReviewListView, self).get_context_data(**kwargs) + context['breadcrumbs'] = ('Reviews',) + return context + + +class ReviewDetailView(LuxDetailView): + model = Post + slug_field = "slug" + + def get_context_data(self, **kwargs): + context = super(ReviewDetailView, self).get_context_data(**kwargs) + related = [] + for obj in self.object.related.all(): + model = apps.get_model(obj.model_name.app_label, obj.model_name.model) + related.append(model.objects.get(slug=obj.slug, pub_date=obj.pub_date)) + context['related'] = related + context['breadcrumbs'] = ('Range',) + context['crumb_url'] = reverse('range:range-list') + return context + + def get_template_names(self): + obj = self.get_object() + return ["posts/review_detail.html"] + + +class ReviewDetailViewTXT(ReviewDetailView): + template_name = "posts/entry_detail.txt" -- cgit v1.2.3-70-g09d2