diff --git a/src/articles/models.py b/src/articles/models.py index 9d00560..20bb221 100644 --- a/src/articles/models.py +++ b/src/articles/models.py @@ -12,7 +12,7 @@ from django.conf import settings from django.contrib.auth.models import AbstractUser from django.contrib.contenttypes.models import ContentType from django.db import models -from django.db.models import Prefetch +from django.db.models import F, Prefetch from django.template.defaultfilters import slugify from django.urls import reverse from django.utils import timezone @@ -132,13 +132,9 @@ class Article(models.Model): self.save() def get_read_time(self) -> int: - try: - content = self.get_formatted_content - if content: - return readtime.of_html(content).minutes - except ParseError: - print(f"minutes failed for pk {self.pk}") - return 0 + content = self.get_formatted_content + if content: + return readtime.of_markdown(content).minutes return 0 @cached_property @@ -168,3 +164,7 @@ class Article(models.Model): f"admin:{content_type.app_label}_{content_type.model}_change", args=(self.id,), ) + + def increment_view_count(self) -> None: + self.views_count = F("views_count") + 1 + self.save(update_fields=["views_count"]) diff --git a/src/articles/urls.py b/src/articles/urls.py index ea5c851..329ba53 100644 --- a/src/articles/urls.py +++ b/src/articles/urls.py @@ -10,5 +10,5 @@ urlpatterns = [ path("tag//", html.TagArticlesListView.as_view(), name="tag"), path("feed/", feeds.CompleteFeed(), name="complete-feed"), path("api/render//", api.render_article, name="api-render-article"), - path("/", html.ArticleDetailView.as_view(), name="article-detail"), + path("/", html.view_article, name="article-detail"), ] diff --git a/src/articles/views/html.py b/src/articles/views/html.py index e76ff09..15e3923 100644 --- a/src/articles/views/html.py +++ b/src/articles/views/html.py @@ -6,11 +6,10 @@ from django.conf import settings from django.contrib.auth.mixins import LoginRequiredMixin from django.core.handlers.wsgi import WSGIRequest from django.core.paginator import Page -from django.db.models import F, Q, QuerySet +from django.db.models import Q, QuerySet from django.http.response import HttpResponse, HttpResponseBase -from django.shortcuts import get_object_or_404 +from django.shortcuts import get_object_or_404, render from django.views import generic -from django.views.generic import DetailView from articles.models import Article, Tag @@ -127,29 +126,19 @@ class DraftsListView(LoginRequiredMixin, BaseArticleListView): return context -class ArticleDetailView(DetailView): - model = Article - context_object_name = "article" - template_name = "articles/article_detail.html" +def view_article(request: WSGIRequest, slug: str) -> HttpResponse: + article = get_article(request, slug) + if not request.user.is_authenticated: + article.increment_view_count() + context = {"article": article, "tags": article.tags.all()} + return render(request, "articles/article_detail.html", context) - def get_queryset(self) -> QuerySet: - key = self.request.GET.get("draft_key") - if key: - return Article.objects.filter(draft_key=key).prefetch_related("tags") - queryset = super().get_queryset().prefetch_related("tags") - if not self.request.user.is_authenticated: - queryset = queryset.filter(status=Article.PUBLISHED) - return queryset - - def get_object(self, queryset: QuerySet | None = None) -> Article: - obj: Article = super().get_object(queryset) - if not self.request.user.is_authenticated: - obj.views_count = F("views_count") + 1 - obj.save(update_fields=["views_count"]) - - return obj - - def get_context_data(self, **kwargs: Any) -> dict[str, Any]: - kwargs["tags"] = self.object.tags.all() - return super().get_context_data(**kwargs) +def get_article(request: WSGIRequest, slug: str) -> Article: + key = request.GET.get("draft_key") + qs = Article.objects.prefetch_related("tags") + if key: + return get_object_or_404(qs, draft_key=key, slug=slug) + if not request.user.is_authenticated: + qs = qs.filter(status=Article.PUBLISHED) + return get_object_or_404(qs, slug=slug)