~linuxgoose/bocpress

089af2cd13ff5b43219fd79e2cce1ead7df9c25f — Jordan Robinson 2 months ago 244924e
add all_tags lists to templates and postmanager functions to get all unique tags for posts and blog setting to show/hide tags in posts list
M main/admin.py => main/admin.py +1 -0
@@ 60,6 60,7 @@ class UserAdmin(DjUserAdmin):
                    "post_backups_on",
                    "show_posts_on_homepage",
                    "show_posts_in_nav",
                    "show_tags_in_post_list",
                    "noindex_on",
                    "reading_time_on",
                    "export_unsubscribe_key",

A main/migrations/0122_user_show_tags_in_post_list_alter_post_tags.py => main/migrations/0122_user_show_tags_in_post_list_alter_post_tags.py +23 -0
@@ 0,0 1,23 @@
# Generated by Django 5.2.5 on 2025-09-24 20:42

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('main', '0121_post_tags'),
    ]

    operations = [
        migrations.AddField(
            model_name='user',
            name='show_tags_in_post_list',
            field=models.BooleanField(default=True, help_text='Show/hide tags in the post list.', verbose_name='Show Tags In Post List'),
        ),
        migrations.AlterField(
            model_name='post',
            name='tags',
            field=models.CharField(blank=True, default=None, help_text='Enter comma-separated tags (e.g., django, python, blog).', max_length=300, null=True),
        ),
    ]

M main/models.py => main/models.py +34 -0
@@ 2,6 2,8 @@ import base64
import binascii
import os
import uuid
import re
from django.db.models import Q

import bleach
from django.conf import settings


@@ 17,6 19,31 @@ def _generate_key():
    """Return 32-char random string."""
    return binascii.b2a_hex(os.urandom(16)).decode("utf-8")

# custom queryset and manager for Post model to handle tag operations

class PostQuerySet(models.QuerySet):
    def with_tag(self, tag):
        return self.filter(
            Q(tags__regex=rf'(^|,){re.escape(tag)}(,|$)')
        )

    def all_unique_tags(self):
        tags = set()
        for post in self.exclude(tags__isnull=True).exclude(tags=""):
            for tag in post.tag_list:
                tags.add(tag)
        return sorted(tags)

class PostManager(models.Manager):
    def get_queryset(self):
        return PostQuerySet(self.model, using=self._db)

    def with_tag(self, tag):
        return self.get_queryset().with_tag(tag)

    def all_unique_tags(self):
        return self.get_queryset().all_unique_tags()


class User(AbstractUser):
    username = models.CharField(


@@ 117,6 144,11 @@ class User(AbstractUser):
        help_text="Show/hide posts in the navigation bar.",
        verbose_name="Show Posts In Nav",
    )
    show_tags_in_post_list = models.BooleanField(
        default=True,
        help_text="Show/hide tags in the post list.",
        verbose_name="Show Tags In Post List",
    )
    noindex_on = models.BooleanField(
        default=False,
        help_text="Add a noindex meta tag so your blog is not indexed by search engines.",


@@ 270,6 302,8 @@ class Post(models.Model):
        ordering = ["-published_at", "-created_at"]
        unique_together = [["slug", "owner"]]

    objects = PostManager()

    @property
    def body_as_html(self):
        return util.md_to_html(self.body)

M main/templates/main/blog_posts.html => main/templates/main/blog_posts.html +10 -1
@@ 69,7 69,7 @@
        {% if p.published_at %}
        <li>
            <a href="{% url 'post_detail' p.slug %}">{{ p.title }}</a>
            {% if p.tag_list %}
            {% if p.tag_list and request.user.show_tags_in_post_list %}
            <small>
                <b>Tags</b>:


@@ 91,6 91,15 @@
        </li>
        {% endif %}
        {% endfor %}

        {% if all_tags and request.user.show_tags_in_post_list %}
        <hr>
        <p><strong>All tags:</strong>
            {% for tag in all_tags %}
                <a href="{% url 'post_list_filter' tag %}" class="tag{% if tag == tag %} active{% endif %}">{{ tag }}</a>{% if not forloop.last %}, {% endif %}
            {% endfor %}
        </p>
        {% endif %}
    </ul>
</main>


M main/templates/main/post_list.html => main/templates/main/post_list.html +11 -1
@@ 14,6 14,7 @@
        Active tag filter: <strong>{{ filter_tag }}</strong> (<a href="{% url 'post_list' %}">clear filter</a>)
    </p>
    {% endif %}

    <p>
        List of posts:
    </p>


@@ 23,7 24,7 @@
            <a href="{% url 'post_detail' post.slug %}">
                {{ post.title }}
            </a>
            {% if p.tag_list %}
            {% if p.tag_list and request.user.show_tags_in_post_list %}
            <small>
                <b>Tags</b>:


@@ 48,5 49,14 @@
        {% endfor %}
    </ul>
    {% endif %}

    {% if all_tags and request.user.show_tags_in_post_list %}
    <hr>
    <p><strong>All tags:</strong>
        {% for tag in all_tags %}
            <a href="{% url 'post_list_dashboard_filter' tag %}" class="tag{% if filter_tag == tag %} active{% endif %}">{{ tag }}</a>{% if not forloop.last %}, {% endif %}
        {% endfor %}
    </p>
    {% endif %}
</main>
{% endblock content %}

M main/urls.py => main/urls.py +1 -0
@@ 80,6 80,7 @@ urlpatterns += [
# blog posts and post snapshots
urlpatterns += [
    path("posts-workshop/", general.PostList.as_view(), name="post_list_dashboard"),
    path("posts-workshop/tag/<slug:tag>/", general.PostList.as_view(), name="post_list_dashboard_filter"),
    path(
        "post-backups/create/", general.SnapshotCreate.as_view(), name="snapshot_create"
    ),

M main/views/general.py => main/views/general.py +20 -2
@@ 152,7 152,8 @@ def post_list(request):
                    "pages": models.Page.objects.filter(
                        owner=request.blog_user, is_hidden=False
                    ).defer("body"),
                    "license_url": license_url
                    "license_url": license_url,
                    "all_tags": models.Post.objects.all_unique_tags()
                },
            )
        


@@ 207,6 208,7 @@ def post_list_filter(request, tag = None):
                    ).defer("body"),
                    "license_url": license_url,
                    "filter_tag": tag,
                    "all_tags": models.Post.objects.all_unique_tags()
                },
            )
        


@@ 228,7 230,22 @@ class PostList(LoginRequiredMixin, ListView):
    model = models.Post

    def get_queryset(self):
        return models.Post.objects.filter(owner=self.request.user)
        qs = models.Post.objects.filter(owner=self.request.user)

        #tag = self.request.GET.get("tag")
        tag = self.kwargs.get("tag")
        if tag:
            qs = qs.with_tag(tag)

        return qs

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["filter_tag"] = self.kwargs.get("tag")
        context["all_tags"] = models.Post.objects.filter(
            owner=self.request.user
        ).all_unique_tags()
        return context

def domain_check(request):
    """


@@ 335,6 352,7 @@ class UserUpdate(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
        "post_backups_on",
        "show_posts_on_homepage",
        "show_posts_in_nav",
        "show_tags_in_post_list",
        "noindex_on",
        "reading_time_on",
        "robots_txt",