From 650e16ea9dce097d09ca050bb21f391054aafda3 Mon Sep 17 00:00:00 2001 From: liangliangyy Date: Wed, 2 Jul 2025 22:51:53 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=8F=92=E4=BB=B6=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blog/views.py | 16 ++++++- djangoblog/plugin_manage/base_plugin.py | 41 ++++++++++++++++++ djangoblog/plugin_manage/hook_constants.py | 4 ++ djangoblog/plugin_manage/hooks.py | 44 ++++++++++++++++++++ djangoblog/settings.py | 21 ++++++++-- plugins/__init__.py | 0 plugins/article_copyright_plugin/__init__.py | 0 plugins/article_copyright_plugin/plugin.py | 33 +++++++++++++++ 8 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 djangoblog/plugin_manage/base_plugin.py create mode 100644 djangoblog/plugin_manage/hook_constants.py create mode 100644 djangoblog/plugin_manage/hooks.py create mode 100644 plugins/__init__.py create mode 100644 plugins/article_copyright_plugin/__init__.py create mode 100644 plugins/article_copyright_plugin/plugin.py diff --git a/blog/views.py b/blog/views.py index 4af9242..e4cc47e 100644 --- a/blog/views.py +++ b/blog/views.py @@ -2,6 +2,7 @@ import logging import os import uuid +import markdown from django.conf import settings from django.core.paginator import Paginator from django.http import HttpResponse, HttpResponseForbidden @@ -17,6 +18,7 @@ from haystack.views import SearchView from blog.models import Article, Category, LinkShowType, Links, Tag from comments.forms import CommentForm +from djangoblog.plugin_manage import hooks from djangoblog.utils import cache, get_blog_setting, get_sha256 logger = logging.getLogger(__name__) @@ -154,7 +156,19 @@ class ArticleDetailView(DetailView): kwargs['next_article'] = self.object.next_article kwargs['prev_article'] = self.object.prev_article - return super(ArticleDetailView, self).get_context_data(**kwargs) + context = super(ArticleDetailView, self).get_context_data(**kwargs) + article = self.object + # Action Hook, 通知插件"文章详情已获取" + hooks.run_action('after_article_body_get', article=article, request=self.request) + # Filter Hook, 允许插件修改文章正文 + article.body = hooks.apply_filters('the_content', article.body, article=article, request=self.request) + # toc = markdown.toc + md = markdown.Markdown(extensions=[ + 'markdown.extensions.extra', + ]) + article.body = md.convert(article.body) + + return context class CategoryDetailView(ArticleListView): diff --git a/djangoblog/plugin_manage/base_plugin.py b/djangoblog/plugin_manage/base_plugin.py new file mode 100644 index 0000000..2b4be5c --- /dev/null +++ b/djangoblog/plugin_manage/base_plugin.py @@ -0,0 +1,41 @@ +import logging + +logger = logging.getLogger(__name__) + + +class BasePlugin: + # 插件元数据 + PLUGIN_NAME = None + PLUGIN_DESCRIPTION = None + PLUGIN_VERSION = None + + def __init__(self): + if not all([self.PLUGIN_NAME, self.PLUGIN_DESCRIPTION, self.PLUGIN_VERSION]): + raise ValueError("Plugin metadata (PLUGIN_NAME, PLUGIN_DESCRIPTION, PLUGIN_VERSION) must be defined.") + self.init_plugin() + self.register_hooks() + + def init_plugin(self): + """ + 插件初始化逻辑 + 子类可以重写此方法来实现特定的初始化操作 + """ + logger.info(f'{self.PLUGIN_NAME} initialized.') + + def register_hooks(self): + """ + 注册插件钩子 + 子类可以重写此方法来注册特定的钩子 + """ + pass + + def get_plugin_info(self): + """ + 获取插件信息 + :return: 包含插件元数据的字典 + """ + return { + 'name': self.PLUGIN_NAME, + 'description': self.PLUGIN_DESCRIPTION, + 'version': self.PLUGIN_VERSION + } diff --git a/djangoblog/plugin_manage/hook_constants.py b/djangoblog/plugin_manage/hook_constants.py new file mode 100644 index 0000000..e1ad4be --- /dev/null +++ b/djangoblog/plugin_manage/hook_constants.py @@ -0,0 +1,4 @@ +ARTICLE_DETAIL_LOAD = 'article_detail_load' +ARTICLE_CREATE = 'article_create' +ARTICLE_UPDATE = 'article_update' +ARTICLE_DELETE = 'article_delete' diff --git a/djangoblog/plugin_manage/hooks.py b/djangoblog/plugin_manage/hooks.py new file mode 100644 index 0000000..d712540 --- /dev/null +++ b/djangoblog/plugin_manage/hooks.py @@ -0,0 +1,44 @@ +import logging + +logger = logging.getLogger(__name__) + +_hooks = {} + + +def register(hook_name: str, callback: callable): + """ + 注册一个钩子回调。 + """ + if hook_name not in _hooks: + _hooks[hook_name] = [] + _hooks[hook_name].append(callback) + logger.debug(f"Registered hook '{hook_name}' with callback '{callback.__name__}'") + + +def run_action(hook_name: str, *args, **kwargs): + """ + 执行一个 Action Hook。 + 它会按顺序执行所有注册到该钩子上的回调函数。 + """ + if hook_name in _hooks: + logger.debug(f"Running action hook '{hook_name}'") + for callback in _hooks[hook_name]: + try: + callback(*args, **kwargs) + except Exception as e: + logger.error(f"Error running action hook '{hook_name}' callback '{callback.__name__}': {e}", exc_info=True) + + +def apply_filters(hook_name: str, value, *args, **kwargs): + """ + 执行一个 Filter Hook。 + 它会把 value 依次传递给所有注册的回调函数进行处理。 + """ + if hook_name in _hooks: + logger.debug(f"Applying filter hook '{hook_name}'") + for callback in _hooks[hook_name]: + try: + value = callback(value, *args, **kwargs) + except Exception as e: + logger.error(f"Error applying filter hook '{hook_name}' callback '{callback.__name__}': {e}", exc_info=True) + return value diff --git a/djangoblog/settings.py b/djangoblog/settings.py index fa970b5..ea7add5 100644 --- a/djangoblog/settings.py +++ b/djangoblog/settings.py @@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/1.10/ref/settings/ """ import os import sys +from pathlib import Path from django.utils.translation import gettext_lazy as _ @@ -20,9 +21,8 @@ def env_to_bool(env, default): return default if str_val is None else str_val == 'True' -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) - -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ @@ -330,3 +330,18 @@ if os.environ.get('DJANGO_ELASTICSEARCH_HOST'): 'ENGINE': 'djangoblog.elasticsearch_backend.ElasticSearchEngine', }, } + +# Plugin System +PLUGINS_DIR = BASE_DIR / 'plugins' +ACTIVE_PLUGINS = [ + 'article_plugin_test', +] + +# 加载插件 +for plugin_dir in os.listdir(PLUGINS_DIR): + plugin_path = os.path.join(PLUGINS_DIR, plugin_dir) + if os.path.isdir(plugin_path) and os.path.exists(os.path.join(plugin_path, '__init__.py')): + try: + __import__(f'plugins.{plugin_dir}.plugin') + except ImportError: + pass diff --git a/plugins/__init__.py b/plugins/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/plugins/article_copyright_plugin/__init__.py b/plugins/article_copyright_plugin/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/plugins/article_copyright_plugin/plugin.py b/plugins/article_copyright_plugin/plugin.py new file mode 100644 index 0000000..2dab2b3 --- /dev/null +++ b/plugins/article_copyright_plugin/plugin.py @@ -0,0 +1,33 @@ +from djangoblog.plugin_manage.base_plugin import BasePlugin +from djangoblog.plugin_manage import hooks + + +class ArticleCopyrightPlugin(BasePlugin): + # 1. 将插件元数据定义为类属性,以匹配 BasePlugin 的要求 + PLUGIN_NAME = '文章结尾版权声明' + PLUGIN_DESCRIPTION = '一个在文章正文末尾添加版权声明的测试插件。' + PLUGIN_VERSION = '0.2.0' + # 也可以添加作者等其他自定义元数据 + PLUGIN_AUTHOR = 'liangliangyy' + + # 2. 实现 register_hooks 方法,专门用于注册钩子 + def register_hooks(self): + # 在这里将插件的方法注册到指定的钩子上 + hooks.register('the_content', self.add_copyright_to_content) + + def add_copyright_to_content(self, content, *args, **kwargs): + """ + 这个方法会被注册到 'the_content' 过滤器钩子上。 + 它接收原始内容,并返回添加了版权信息的新内容。 + """ + article = kwargs.get('article') + if not article: + return content + + copyright_info = f"\n

本文由 {article.author.username} 原创,转载请注明出处。

" + return content + copyright_info + + +# 3. 实例化插件。 +# 这会自动调用 BasePlugin.__init__,然后 BasePlugin.__init__ 会调用我们上面定义的 register_hooks 方法。 +plugin = ArticleCopyrightPlugin() From ef3efec6304b6b3bef9dd1085f2e60c57e654f50 Mon Sep 17 00:00:00 2001 From: liangliangyy Date: Wed, 2 Jul 2025 23:11:14 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=8F=92=E4=BB=B6=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- djangoblog/settings.py | 4 +- plugins/__init__.py | 1 + plugins/article_copyright/__init__.py | 1 + .../plugin.py | 6 +-- plugins/article_copyright_plugin/__init__.py | 0 plugins/external_links/__init__.py | 1 + plugins/external_links/plugin.py | 47 +++++++++++++++++++ plugins/reading_time/__init__.py | 1 + plugins/reading_time/plugin.py | 41 ++++++++++++++++ 9 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 plugins/article_copyright/__init__.py rename plugins/{article_copyright_plugin => article_copyright}/plugin.py (80%) delete mode 100644 plugins/article_copyright_plugin/__init__.py create mode 100644 plugins/external_links/__init__.py create mode 100644 plugins/external_links/plugin.py create mode 100644 plugins/reading_time/__init__.py create mode 100644 plugins/reading_time/plugin.py diff --git a/djangoblog/settings.py b/djangoblog/settings.py index ea7add5..a092698 100644 --- a/djangoblog/settings.py +++ b/djangoblog/settings.py @@ -334,7 +334,9 @@ if os.environ.get('DJANGO_ELASTICSEARCH_HOST'): # Plugin System PLUGINS_DIR = BASE_DIR / 'plugins' ACTIVE_PLUGINS = [ - 'article_plugin_test', + 'article_copyright', + 'reading_time', + 'external_links', ] # 加载插件 diff --git a/plugins/__init__.py b/plugins/__init__.py index e69de29..e88afca 100644 --- a/plugins/__init__.py +++ b/plugins/__init__.py @@ -0,0 +1 @@ +# This file makes this a Python package diff --git a/plugins/article_copyright/__init__.py b/plugins/article_copyright/__init__.py new file mode 100644 index 0000000..e88afca --- /dev/null +++ b/plugins/article_copyright/__init__.py @@ -0,0 +1 @@ +# This file makes this a Python package diff --git a/plugins/article_copyright_plugin/plugin.py b/plugins/article_copyright/plugin.py similarity index 80% rename from plugins/article_copyright_plugin/plugin.py rename to plugins/article_copyright/plugin.py index 2dab2b3..a97dd92 100644 --- a/plugins/article_copyright_plugin/plugin.py +++ b/plugins/article_copyright/plugin.py @@ -3,11 +3,9 @@ from djangoblog.plugin_manage import hooks class ArticleCopyrightPlugin(BasePlugin): - # 1. 将插件元数据定义为类属性,以匹配 BasePlugin 的要求 PLUGIN_NAME = '文章结尾版权声明' - PLUGIN_DESCRIPTION = '一个在文章正文末尾添加版权声明的测试插件。' + PLUGIN_DESCRIPTION = '一个在文章正文末尾添加版权声明的插件。' PLUGIN_VERSION = '0.2.0' - # 也可以添加作者等其他自定义元数据 PLUGIN_AUTHOR = 'liangliangyy' # 2. 实现 register_hooks 方法,专门用于注册钩子 @@ -24,7 +22,7 @@ class ArticleCopyrightPlugin(BasePlugin): if not article: return content - copyright_info = f"\n

本文由 {article.author.username} 原创,转载请注明出处。

" + copyright_info = f"\n

本文由 {article.author.nickname} 原创,转载请注明出处。

" return content + copyright_info diff --git a/plugins/article_copyright_plugin/__init__.py b/plugins/article_copyright_plugin/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/plugins/external_links/__init__.py b/plugins/external_links/__init__.py new file mode 100644 index 0000000..e88afca --- /dev/null +++ b/plugins/external_links/__init__.py @@ -0,0 +1 @@ +# This file makes this a Python package diff --git a/plugins/external_links/plugin.py b/plugins/external_links/plugin.py new file mode 100644 index 0000000..bb8b734 --- /dev/null +++ b/plugins/external_links/plugin.py @@ -0,0 +1,47 @@ +import re +from urllib.parse import urlparse +from djangoblog.plugin_manage.base_plugin import BasePlugin +from djangoblog.plugin_manage import hooks + + +class ExternalLinksPlugin(BasePlugin): + PLUGIN_NAME = '外部链接处理器' + PLUGIN_DESCRIPTION = '自动为文章中的外部链接添加 target="_blank" 和 rel="noopener noreferrer" 属性。' + PLUGIN_VERSION = '0.1.0' + PLUGIN_AUTHOR = 'liangliangyy' + + def register_hooks(self): + hooks.register('the_content', self.process_external_links) + + def process_external_links(self, content, *args, **kwargs): + from djangoblog.utils import get_current_site + site_domain = get_current_site().domain + + # 正则表达式查找所有 标签 + link_pattern = re.compile(r'(]*?\s+)?href=")([^"]*)(".*?/a>)', re.IGNORECASE) + + def replacer(match): + # match.group(1) 是 ... + href = match.group(2) + + # 如果链接已经有 target 属性,则不处理 + if 'target=' in match.group(0).lower(): + return match.group(0) + + # 解析链接 + parsed_url = urlparse(href) + + # 如果链接是外部的 (有域名且域名不等于当前网站域名) + if parsed_url.netloc and parsed_url.netloc != site_domain: + # 添加 target 和 rel 属性 + return f'{match.group(1)}{href}" target="_blank" rel="noopener noreferrer"{match.group(3)}' + + # 否则返回原样 + return match.group(0) + + return link_pattern.sub(replacer, content) + + +plugin = ExternalLinksPlugin() diff --git a/plugins/reading_time/__init__.py b/plugins/reading_time/__init__.py new file mode 100644 index 0000000..e88afca --- /dev/null +++ b/plugins/reading_time/__init__.py @@ -0,0 +1 @@ +# This file makes this a Python package diff --git a/plugins/reading_time/plugin.py b/plugins/reading_time/plugin.py new file mode 100644 index 0000000..7a6a13e --- /dev/null +++ b/plugins/reading_time/plugin.py @@ -0,0 +1,41 @@ +import re +from djangoblog.plugin_manage.base_plugin import BasePlugin +from djangoblog.plugin_manage import hooks + + +class ReadingTimePlugin(BasePlugin): + PLUGIN_NAME = '阅读时间预测' + PLUGIN_DESCRIPTION = '估算文章阅读时间并显示在文章开头。' + PLUGIN_VERSION = '0.1.0' + PLUGIN_AUTHOR = 'liangliangyy' + + def register_hooks(self): + hooks.register('the_content', self.add_reading_time) + + def add_reading_time(self, content, *args, **kwargs): + """ + 计算阅读时间并添加到内容开头。 + """ + # 移除HTML标签和空白字符,以获得纯文本 + clean_content = re.sub(r'<[^>]*>', '', content) + clean_content = clean_content.strip() + + # 中文和英文单词混合计数的一个简单方法 + # 匹配中文字符或连续的非中文字符(视为单词) + words = re.findall(r'[\u4e00-\u9fa5]|\w+', clean_content) + word_count = len(words) + + # 按平均每分钟200字的速度计算 + reading_speed = 200 + reading_minutes = round(word_count / reading_speed) + + # 如果阅读时间少于1分钟,则显示为1分钟 + if reading_minutes < 1: + reading_minutes = 1 + + reading_time_html = f'

预计阅读时间:{reading_minutes} 分钟

' + + return reading_time_html + content + + +plugin = ReadingTimePlugin() \ No newline at end of file From 3e095cdf12054b0092eb2d04efad5caf1246cb33 Mon Sep 17 00:00:00 2001 From: liangliangyy Date: Wed, 2 Jul 2025 23:28:48 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=8F=92=E4=BB=B6=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blog/views.py | 15 ++++++++------- djangoblog/plugin_manage/hook_constants.py | 3 +++ djangoblog/settings.py | 4 ++-- plugins/article_copyright/plugin.py | 5 +++-- plugins/external_links/plugin.py | 3 ++- plugins/reading_time/plugin.py | 8 +++++--- 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/blog/views.py b/blog/views.py index e4cc47e..8bb5264 100644 --- a/blog/views.py +++ b/blog/views.py @@ -19,6 +19,7 @@ from haystack.views import SearchView from blog.models import Article, Category, LinkShowType, Links, Tag from comments.forms import CommentForm from djangoblog.plugin_manage import hooks +from djangoblog.plugin_manage.hook_constants import ARTICLE_CONTENT_HOOK_NAME from djangoblog.utils import cache, get_blog_setting, get_sha256 logger = logging.getLogger(__name__) @@ -160,13 +161,13 @@ class ArticleDetailView(DetailView): article = self.object # Action Hook, 通知插件"文章详情已获取" hooks.run_action('after_article_body_get', article=article, request=self.request) - # Filter Hook, 允许插件修改文章正文 - article.body = hooks.apply_filters('the_content', article.body, article=article, request=self.request) - # toc = markdown.toc - md = markdown.Markdown(extensions=[ - 'markdown.extensions.extra', - ]) - article.body = md.convert(article.body) + # # Filter Hook, 允许插件修改文章正文 + article.body = hooks.apply_filters(ARTICLE_CONTENT_HOOK_NAME, article.body, article=article, request=self.request) + # # toc = markdown.toc + # md = markdown.Markdown(extensions=[ + # 'markdown.extensions.extra', + # ]) + # article.body = md.convert(article.body) return context diff --git a/djangoblog/plugin_manage/hook_constants.py b/djangoblog/plugin_manage/hook_constants.py index e1ad4be..6685b7c 100644 --- a/djangoblog/plugin_manage/hook_constants.py +++ b/djangoblog/plugin_manage/hook_constants.py @@ -2,3 +2,6 @@ ARTICLE_DETAIL_LOAD = 'article_detail_load' ARTICLE_CREATE = 'article_create' ARTICLE_UPDATE = 'article_update' ARTICLE_DELETE = 'article_delete' + +ARTICLE_CONTENT_HOOK_NAME = "the_content" + diff --git a/djangoblog/settings.py b/djangoblog/settings.py index a092698..9b527da 100644 --- a/djangoblog/settings.py +++ b/djangoblog/settings.py @@ -345,5 +345,5 @@ for plugin_dir in os.listdir(PLUGINS_DIR): if os.path.isdir(plugin_path) and os.path.exists(os.path.join(plugin_path, '__init__.py')): try: __import__(f'plugins.{plugin_dir}.plugin') - except ImportError: - pass + except ImportError as e: + print("Failed to import plugin:", plugin_dir, e) diff --git a/plugins/article_copyright/plugin.py b/plugins/article_copyright/plugin.py index a97dd92..317fed2 100644 --- a/plugins/article_copyright/plugin.py +++ b/plugins/article_copyright/plugin.py @@ -1,5 +1,6 @@ from djangoblog.plugin_manage.base_plugin import BasePlugin from djangoblog.plugin_manage import hooks +from djangoblog.plugin_manage.hook_constants import ARTICLE_CONTENT_HOOK_NAME class ArticleCopyrightPlugin(BasePlugin): @@ -11,7 +12,7 @@ class ArticleCopyrightPlugin(BasePlugin): # 2. 实现 register_hooks 方法,专门用于注册钩子 def register_hooks(self): # 在这里将插件的方法注册到指定的钩子上 - hooks.register('the_content', self.add_copyright_to_content) + hooks.register(ARTICLE_CONTENT_HOOK_NAME, self.add_copyright_to_content) def add_copyright_to_content(self, content, *args, **kwargs): """ @@ -22,7 +23,7 @@ class ArticleCopyrightPlugin(BasePlugin): if not article: return content - copyright_info = f"\n

本文由 {article.author.nickname} 原创,转载请注明出处。

" + copyright_info = f"\n

本文由 {article.author.username} 原创,转载请注明出处。

" return content + copyright_info diff --git a/plugins/external_links/plugin.py b/plugins/external_links/plugin.py index bb8b734..5b2ef14 100644 --- a/plugins/external_links/plugin.py +++ b/plugins/external_links/plugin.py @@ -2,6 +2,7 @@ import re from urllib.parse import urlparse from djangoblog.plugin_manage.base_plugin import BasePlugin from djangoblog.plugin_manage import hooks +from djangoblog.plugin_manage.hook_constants import ARTICLE_CONTENT_HOOK_NAME class ExternalLinksPlugin(BasePlugin): @@ -11,7 +12,7 @@ class ExternalLinksPlugin(BasePlugin): PLUGIN_AUTHOR = 'liangliangyy' def register_hooks(self): - hooks.register('the_content', self.process_external_links) + hooks.register(ARTICLE_CONTENT_HOOK_NAME, self.process_external_links) def process_external_links(self, content, *args, **kwargs): from djangoblog.utils import get_current_site diff --git a/plugins/reading_time/plugin.py b/plugins/reading_time/plugin.py index 7a6a13e..35f9db1 100644 --- a/plugins/reading_time/plugin.py +++ b/plugins/reading_time/plugin.py @@ -1,6 +1,8 @@ +import math import re from djangoblog.plugin_manage.base_plugin import BasePlugin from djangoblog.plugin_manage import hooks +from djangoblog.plugin_manage.hook_constants import ARTICLE_CONTENT_HOOK_NAME class ReadingTimePlugin(BasePlugin): @@ -10,7 +12,7 @@ class ReadingTimePlugin(BasePlugin): PLUGIN_AUTHOR = 'liangliangyy' def register_hooks(self): - hooks.register('the_content', self.add_reading_time) + hooks.register(ARTICLE_CONTENT_HOOK_NAME, self.add_reading_time) def add_reading_time(self, content, *args, **kwargs): """ @@ -26,8 +28,8 @@ class ReadingTimePlugin(BasePlugin): word_count = len(words) # 按平均每分钟200字的速度计算 - reading_speed = 200 - reading_minutes = round(word_count / reading_speed) + reading_speed = 200 + reading_minutes = math.ceil(word_count / reading_speed) # 如果阅读时间少于1分钟,则显示为1分钟 if reading_minutes < 1: From 677b40167572130b0a3ac03a1a0588d530665ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=94=E5=90=AC=E9=A3=8E=E5=90=9F?= Date: Wed, 2 Jul 2025 23:35:23 +0800 Subject: [PATCH 4/5] Update blog/views.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- blog/views.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/blog/views.py b/blog/views.py index 8bb5264..7e082a6 100644 --- a/blog/views.py +++ b/blog/views.py @@ -161,13 +161,8 @@ class ArticleDetailView(DetailView): article = self.object # Action Hook, 通知插件"文章详情已获取" hooks.run_action('after_article_body_get', article=article, request=self.request) - # # Filter Hook, 允许插件修改文章正文 + # Filter Hook, 允许插件修改文章正文 article.body = hooks.apply_filters(ARTICLE_CONTENT_HOOK_NAME, article.body, article=article, request=self.request) - # # toc = markdown.toc - # md = markdown.Markdown(extensions=[ - # 'markdown.extensions.extra', - # ]) - # article.body = md.convert(article.body) return context From a2b38a5f2ddefa77bd2d89e6b266ced36d474bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=94=E5=90=AC=E9=A3=8E=E5=90=9F?= Date: Wed, 2 Jul 2025 23:35:52 +0800 Subject: [PATCH 5/5] Update blog/views.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- blog/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/blog/views.py b/blog/views.py index 7e082a6..fc5e346 100644 --- a/blog/views.py +++ b/blog/views.py @@ -2,7 +2,6 @@ import logging import os import uuid -import markdown from django.conf import settings from django.core.paginator import Paginator from django.http import HttpResponse, HttpResponseForbidden