diff --git a/src/DjangoBlog-master(1)/DjangoBlog-master/blog/models.py b/src/DjangoBlog-master(1)/DjangoBlog-master/blog/models.py index 083788b..edbe4e1 100644 --- a/src/DjangoBlog-master(1)/DjangoBlog-master/blog/models.py +++ b/src/DjangoBlog-master(1)/DjangoBlog-master/blog/models.py @@ -1,7 +1,6 @@ import logging import re from abc import abstractmethod - from django.conf import settings from django.core.exceptions import ValidationError from django.db import models @@ -129,7 +128,6 @@ class Article(BaseModel): def get_category_tree(self): tree = self.category.get_category_tree() names = list(map(lambda c: (c.name, c.get_absolute_url()), tree)) - return names def save(self, *args, **kwargs): @@ -176,6 +174,42 @@ class Article(BaseModel): return match.group(1) return "" + @cache_decorator(60 * 60 * 24) # 缓存24小时 + def get_related_articles(self, limit=5): + """ + 根据当前文章的标签和分类获取相关推荐文章 + :param limit: 推荐文章数量上限 + :return: 相关文章列表 + """ + # 1. 获取当前文章的所有标签ID + tag_ids = self.tags.values_list('id', flat=True) + + # 2. 查询有相同标签的已发布文章(排除当前文章),并去重 + related_by_tag = Article.objects.filter( + tags__id__in=tag_ids, + status='p' + ).exclude(id=self.id).distinct() + + # 3. 如果标签匹配的文章不足,补充同分类的已发布文章 + if related_by_tag.count() < limit: + # 计算还需要补充的文章数量 + need = limit - related_by_tag.count() + # 查询同分类的文章(排除当前文章和已通过标签匹配的文章) + related_by_category = Article.objects.filter( + category=self.category, + status='p' + ).exclude( + id__in=list(related_by_tag.values_list('id', flat=True)) + [self.id] + ).order_by('-pub_time')[:need] + + # 合并结果(标签匹配的文章在前,分类匹配的在后) + related_articles = list(related_by_tag) + list(related_by_category) + else: + # 标签匹配的文章足够,直接取前 limit 篇 + related_articles = list(related_by_tag)[:limit] + + return related_articles + class Category(BaseModel): """文章分类""" @@ -373,4 +407,4 @@ class BlogSettings(models.Model): def save(self, *args, **kwargs): super().save(*args, **kwargs) from djangoblog.utils import cache - cache.clear() + cache.clear() \ No newline at end of file diff --git a/src/DjangoBlog-master(1)/DjangoBlog-master/blog/views.py b/src/DjangoBlog-master(1)/DjangoBlog-master/blog/views.py index b359186..b207192 100644 --- a/src/DjangoBlog-master(1)/DjangoBlog-master/blog/views.py +++ b/src/DjangoBlog-master(1)/DjangoBlog-master/blog/views.py @@ -38,7 +38,7 @@ class ArticleListView(ListView): link_type = LinkShowType.L def get_view_cache_key(self): - return self.request.get['pages'] + return self.request.GET.get('page', 1) @property def page_number(self): @@ -86,6 +86,14 @@ class ArticleListView(ListView): def get_context_data(self, **kwargs): kwargs['linktype'] = self.link_type + # 新增:添加热门文章数据(所有列表页共享) + hot_articles_cache_key = 'hot_articles' + hot_articles = cache.get(hot_articles_cache_key) + if not hot_articles: + hot_articles = Article.objects.filter(type='a', status='p').order_by('-views')[:5] + cache.set(hot_articles_cache_key, hot_articles, 60 * 60) # 缓存1小时 + logger.info('set hot articles cache') + kwargs['hot_articles'] = hot_articles return super(ArticleListView, self).get_context_data(** kwargs) @@ -147,14 +155,27 @@ class ArticleDetailView(DetailView): kwargs['comment_count'] = len( article_comments) if article_comments else 0 - kwargs['next_article'] = self.object.next_article - kwargs['prev_article'] = self.object.prev_article + kwargs['next_article'] = self.object.next_article() + kwargs['prev_article'] = self.object.prev_article() + + # 新增:获取相关推荐文章 + related_articles = self.object.get_related_articles(limit=5) + kwargs['related_articles'] = related_articles + + # 新增:添加热门文章数据(详情页也显示) + hot_articles_cache_key = 'hot_articles' + hot_articles = cache.get(hot_articles_cache_key) + if not hot_articles: + hot_articles = Article.objects.filter(type='a', status='p').order_by('-views')[:5] + cache.set(hot_articles_cache_key, hot_articles, 60 * 60) + logger.info('set hot articles cache') + kwargs['hot_articles'] = hot_articles 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, 允许插件修改文章正文 + # Filter Hook, 允许插件修改文章正文 article.body = hooks.apply_filters(ARTICLE_CONTENT_HOOK_NAME, article.body, article=article, request=self.request) @@ -189,7 +210,6 @@ class CategoryDetailView(ArticleListView): return cache_key def get_context_data(self, **kwargs): - categoryname = self.categoryname try: categoryname = categoryname.split('/')[-1] @@ -251,7 +271,6 @@ class TagDetailView(ArticleListView): return cache_key def get_context_data(self, **kwargs): - # tag_name = self.kwargs['tag_name'] tag_name = self.name kwargs['page_type'] = TagDetailView.page_type kwargs['tag_name'] = tag_name @@ -274,6 +293,17 @@ class ArchivesView(ArticleListView): cache_key = 'archives' return cache_key + def get_context_data(self,** kwargs): + # 归档页单独添加热门文章(因继承自ArticleListView但需确保显示) + hot_articles_cache_key = 'hot_articles' + hot_articles = cache.get(hot_articles_cache_key) + if not hot_articles: + hot_articles = Article.objects.filter(type='a', status='p').order_by('-views')[:5] + cache.set(hot_articles_cache_key, hot_articles, 60 * 60) + logger.info('set hot articles cache') + kwargs['hot_articles'] = hot_articles + return super(ArchivesView, self).get_context_data(**kwargs) + class LinkListView(ListView): model = Links @@ -282,21 +312,29 @@ class LinkListView(ListView): def get_queryset(self): return Links.objects.filter(is_enable=True) + def get_context_data(self,** kwargs): + # 链接页添加热门文章 + hot_articles_cache_key = 'hot_articles' + hot_articles = cache.get(hot_articles_cache_key) + if not hot_articles: + hot_articles = Article.objects.filter(type='a', status='p').order_by('-views')[:5] + cache.set(hot_articles_cache_key, hot_articles, 60 * 60) + logger.info('set hot articles cache') + kwargs['hot_articles'] = hot_articles + return super(LinkListView, self).get_context_data(**kwargs) + class EsSearchView(SearchView): def get_context(self): - paginator, page = self.build_page() - context = { - "query": self.query, - "form": self.form, - "page": page, - "paginator": paginator, - "suggestion": None, - } - if hasattr(self.results, "query") and self.results.query.backend.include_spelling: - context["suggestion"] = self.results.query.get_spelling_suggestion() - context.update(self.extra_context()) - + context = super().get_context() + # 搜索页添加热门文章 + hot_articles_cache_key = 'hot_articles' + hot_articles = cache.get(hot_articles_cache_key) + if not hot_articles: + hot_articles = Article.objects.filter(type='a', status='p').order_by('-views')[:5] + cache.set(hot_articles_cache_key, hot_articles, 60 * 60) + logger.info('set hot articles cache') + context['hot_articles'] = hot_articles return context @@ -319,7 +357,7 @@ def fileupload(request): imgextensions = ['jpg', 'png', 'jpeg', 'bmp'] fname = u''.join(str(filename)) isimage = len([i for i in imgextensions if fname.find(i) >= 0]) > 0 - base_dir = os.path.join(settings.STATICFILES, "files" if not isimage else "image", timestr) + base_dir = os.path.join(settings.STATICFILES_DIRS[0], "files" if not isimage else "image", timestr) if not os.path.exists(base_dir): os.makedirs(base_dir) savepath = os.path.normpath(os.path.join(base_dir, f"{uuid.uuid4().hex}{os.path.splitext(filename)[-1]}")) @@ -332,7 +370,9 @@ def fileupload(request): from PIL import Image image = Image.open(savepath) image.save(savepath, quality=20, optimize=True) - url = static(savepath) + # 修正静态文件URL路径 + relative_path = os.path.relpath(savepath, settings.STATICFILES_DIRS[0]) + url = static(relative_path) response.append(url) return HttpResponse(response) @@ -403,7 +443,7 @@ class DjangoBlogFeed(Feed): 返回要在订阅中显示的项目列表。 这里我们返回最新的 10 篇已发布的文章。 """ - return Article.objects.filter(status='p').order_by('-created_time')[:10] + return Article.objects.filter(status='p').order_by('-creation_time')[:10] def item_title(self, item): """ @@ -425,11 +465,16 @@ class DjangoBlogFeed(Feed): """ 返回单个项目(文章)的绝对链接。 """ - return reverse('blog:article_detail', kwargs={'article_id': item.pk}) + return reverse('blog:detailbyid', kwargs={ + 'article_id': item.pk, + 'year': item.creation_time.year, + 'month': item.creation_time.month, + 'day': item.creation_time.day + }) def item_pubdate(self, item): """ 返回单个项目(文章)的发布日期。 这是可选的,但推荐添加,以符合 RSS 规范。 """ - return item.created_time \ No newline at end of file + return item.creation_time \ No newline at end of file diff --git a/src/DjangoBlog-master(1)/DjangoBlog-master/templates/blog/article_detail.html b/src/DjangoBlog-master(1)/DjangoBlog-master/templates/blog/article_detail.html index a74a0db..1361436 100644 --- a/src/DjangoBlog-master(1)/DjangoBlog-master/templates/blog/article_detail.html +++ b/src/DjangoBlog-master(1)/DjangoBlog-master/templates/blog/article_detail.html @@ -3,6 +3,7 @@ {% block header %} {% endblock %} + {% block content %}