From d59565fa82743b016e9727705e56402e28ce4b55 Mon Sep 17 00:00:00 2001 From: Gabriel Augendre Date: Sun, 3 Jan 2021 21:51:46 +0100 Subject: [PATCH] Refactor articles model --- articles/models.py | 58 +++++++++----------------------- articles/tests/test_api_views.py | 3 +- articles/utils.py | 40 ++++++++++++++++++++++ 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/articles/models.py b/articles/models.py index 11ec6fa..1b274d5 100644 --- a/articles/models.py +++ b/articles/models.py @@ -1,10 +1,7 @@ import random -import re import uuid from functools import cached_property, reduce -import html2text -import markdown import readtime from django.contrib.auth.models import AbstractUser from django.contrib.contenttypes.models import ContentType @@ -12,39 +9,20 @@ from django.db import models from django.template.defaultfilters import slugify from django.urls import reverse from django.utils import timezone -from markdown.extensions.codehilite import CodeHiliteExtension -from articles.markdown import LazyLoadingImageExtension -from articles.utils import build_full_absolute_url +from articles.utils import ( + build_full_absolute_url, + format_article_content, + get_html_to_text_converter, + truncate_words_after_char_count, +) class User(AbstractUser): pass -class AdminUrlMixin: - def get_admin_url(self): - content_type = ContentType.objects.get_for_model(self.__class__) - return reverse( - "admin:%s_%s_change" % (content_type.app_label, content_type.model), - args=(self.id,), - ) - - -def format_article_content(content): - md = markdown.Markdown( - extensions=[ - "extra", - "admonition", - CodeHiliteExtension(linenums=False, guess_lang=False), - LazyLoadingImageExtension(), - ] - ) - content = re.sub(r"(\s)#(\w+)", r"\1\#\2", content) - return md.convert(content) - - -class Article(AdminUrlMixin, models.Model): +class Article(models.Model): DRAFT = "draft" PUBLISHED = "published" STATUS_CHOICES = [ @@ -82,20 +60,9 @@ class Article(AdminUrlMixin, models.Model): @cached_property def get_description(self): html = self.get_formatted_content - converter = html2text.HTML2Text() - converter.ignore_images = True - converter.ignore_links = True - converter.ignore_tables = True - converter.ignore_emphasis = True + converter = get_html_to_text_converter() text = converter.handle(html) - total_length = 0 - text_result = [] - for word in text.split(): - if len(word) + 1 + total_length > 160: - break - text_result.append(word) - total_length += len(word) + 1 - return " ".join(text_result) + "..." + return truncate_words_after_char_count(text, 160) @cached_property def get_formatted_content(self): @@ -165,3 +132,10 @@ class Article(AdminUrlMixin, models.Model): css = self.custom_css.replace("\n", " ") return reduce(reducer, css, "") + + def get_admin_url(self): + content_type = ContentType.objects.get_for_model(self.__class__) + return reverse( + "admin:%s_%s_change" % (content_type.app_label, content_type.model), + args=(self.id,), + ) diff --git a/articles/tests/test_api_views.py b/articles/tests/test_api_views.py index 67764f1..9311000 100644 --- a/articles/tests/test_api_views.py +++ b/articles/tests/test_api_views.py @@ -2,7 +2,8 @@ import pytest from django.test import Client from django.urls import reverse -from articles.models import Article, format_article_content +from articles.models import Article +from articles.utils import format_article_content @pytest.mark.django_db diff --git a/articles/utils.py b/articles/utils.py index a7c92cb..4ee6af4 100644 --- a/articles/utils.py +++ b/articles/utils.py @@ -1,4 +1,11 @@ +import re + +import html2text +import markdown from django.conf import settings +from markdown.extensions.codehilite import CodeHiliteExtension + +from articles.markdown import LazyLoadingImageExtension def build_full_absolute_url(request, url): @@ -6,3 +13,36 @@ def build_full_absolute_url(request, url): return request.build_absolute_uri(url) else: return (settings.BLOG["base_url"] + url)[::-1].replace("//", "/", 1)[::-1] + + +def format_article_content(content): + md = markdown.Markdown( + extensions=[ + "extra", + "admonition", + CodeHiliteExtension(linenums=False, guess_lang=False), + LazyLoadingImageExtension(), + ] + ) + content = re.sub(r"(\s)#(\w+)", r"\1\#\2", content) + return md.convert(content) + + +def truncate_words_after_char_count(text, char_count): + total_length = 0 + text_result = [] + for word in text.split(): + if len(word) + 1 + total_length > char_count: + break + text_result.append(word) + total_length += len(word) + 1 + return " ".join(text_result) + "..." + + +def get_html_to_text_converter(): + converter = html2text.HTML2Text() + converter.ignore_images = True + converter.ignore_links = True + converter.ignore_tables = True + converter.ignore_emphasis = True + return converter