Add tags on articles and list view

This commit is contained in:
Gabriel Augendre 2021-03-04 18:24:22 +01:00
parent 8d5edfd8df
commit 4ddf916364
6 changed files with 60 additions and 7 deletions

View file

@ -0,0 +1,40 @@
# Generated by Django 3.1.5 on 2021-03-04 17:17
from django.db import migrations, models
from django.utils.text import slugify
def forwards(apps, schema_editor):
Tag = apps.get_model("articles", "Tag")
db_alias = schema_editor.connection.alias
tags = Tag.objects.using(db_alias).all()
for tag in tags:
tag.slug = slugify(tag.name)
Tag.objects.bulk_update(tags, ["slug"])
def backwards(apps, schema_editor):
Tag = apps.get_model("articles", "Tag")
db_alias = schema_editor.connection.alias
Tag.objects.using(db_alias).update(slug="")
class Migration(migrations.Migration):
dependencies = [
("articles", "0029_auto_20210303_1711"),
]
operations = [
migrations.AddField(
model_name="tag",
name="slug",
field=models.CharField(blank=True, max_length=255),
),
migrations.RunPython(forwards, backwards),
migrations.AlterField(
model_name="tag",
name="slug",
field=models.CharField(max_length=255, unique=True),
),
]

View file

@ -25,6 +25,7 @@ class User(AbstractUser):
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
slug = models.CharField(max_length=255, unique=True)
class Meta:
ordering = ["name"]

View file

@ -20,7 +20,7 @@ footer > :first-child {
margin-top: 1em;
}
nav a:not(:first-child):before {
nav a:not(:first-child):before, a.tag:not(:first-of-type):before {
content: '\00B7';
margin: 0 5px;
color: var(--nc-tx-1);

View file

@ -2,4 +2,7 @@
Published on {% include "articles/snippets/datetime.html" %}
· {{ article.get_read_time }} min read
{% include "articles/snippets/admin_link.html" %}
{% if article.tags.all %}
<br>{% for tag in article.tags.all %}<a href="{% url "tag" slug=tag.slug %}" class="tag">{{ tag.name }}</a>{% endfor %}
{% endif %}
</p>

View file

@ -6,6 +6,7 @@ urlpatterns = [
path("", html.ArticlesListView.as_view(), name="articles-list"),
path("drafts/", html.DraftsListView.as_view(), name="drafts-list"),
path("search/", html.SearchArticlesListView.as_view(), name="search"),
path("tag/<slug:slug>/", html.TagArticlesListView.as_view(), name="tag"),
path("feed/", feeds.CompleteFeed(), name="complete-feed"),
path("api/render/<int:article_pk>/", api.render_article, name="api-render-article"),
path("<slug:slug>/", html.ArticleDetailView.as_view(), name="article-detail"),

View file

@ -5,9 +5,10 @@ from typing import Dict
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import F, Q
from django.shortcuts import get_object_or_404
from django.views import generic
from articles.models import Article
from articles.models import Article, Tag
class BaseArticleListView(generic.ListView):
@ -41,9 +42,11 @@ class BaseArticleListView(generic.ListView):
return "&".join(map(lambda item: f"{item[0]}={item[1]}", querystring.items()))
class ArticlesListView(BaseArticleListView):
class PublicArticleListView(BaseArticleListView):
queryset = Article.objects.filter(status=Article.PUBLISHED)
class ArticlesListView(PublicArticleListView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
home_article = Article.objects.filter(
@ -53,8 +56,7 @@ class ArticlesListView(BaseArticleListView):
return context
class SearchArticlesListView(BaseArticleListView):
queryset = Article.objects.filter(status=Article.PUBLISHED)
class SearchArticlesListView(PublicArticleListView):
template_name = "articles/article_search.html"
def get_context_data(self, **kwargs):
@ -85,6 +87,12 @@ class SearchArticlesListView(BaseArticleListView):
return {}
class TagArticlesListView(PublicArticleListView):
def get_queryset(self):
tag = get_object_or_404(Tag, slug=self.kwargs.get("slug"))
return super().get_queryset().filter(tags=tag)
class DraftsListView(LoginRequiredMixin, BaseArticleListView):
queryset = Article.objects.filter(status=Article.DRAFT)
@ -103,9 +111,9 @@ class ArticleDetailView(generic.DetailView):
def get_queryset(self):
key = self.request.GET.get("draft_key")
if key:
return Article.objects.filter(draft_key=key)
return Article.objects.filter(draft_key=key).prefetch_related("tags")
queryset = super().get_queryset()
queryset = super().get_queryset().prefetch_related("tags")
if not self.request.user.is_authenticated:
queryset = queryset.filter(status=Article.PUBLISHED)
return queryset