forked from plhw57tbe/SoftwareMethodology
@ -0,0 +1,26 @@
|
||||
# 项目开发报告
|
||||
|
||||
## 项目概述
|
||||
本项目是一个软件工程方法论实践项目。
|
||||
|
||||
## 登录功能开发进度
|
||||
|
||||
### 已完成
|
||||
- [x] 项目环境搭建
|
||||
- [x] Git分支管理配置
|
||||
- [x] 基础文档结构创建
|
||||
|
||||
### 进行中
|
||||
- [ ] 用户登录功能实现
|
||||
- [ ] 密码加密模块
|
||||
- [ ] 会话管理功能
|
||||
|
||||
### 技术栈
|
||||
- Python 3.x
|
||||
- Git 版本控制
|
||||
- Markdown 文档
|
||||
|
||||
## 下一步计划
|
||||
1. 实现登录功能代码
|
||||
2. 编写单元测试
|
||||
3. 完成集成测试
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,10 +1,12 @@
|
||||
[run]
|
||||
source = .
|
||||
include = *.py
|
||||
[run] # 运行配置部分
|
||||
source = . # 指定要测量覆盖率的源代码根目录为当前目录
|
||||
include = *.py # 包含所有.py文件进行覆盖率测量
|
||||
|
||||
# 排除的文件和目录列表
|
||||
omit =
|
||||
*migrations*
|
||||
*tests*
|
||||
*.html
|
||||
*whoosh_cn_backend*
|
||||
*settings.py*
|
||||
*venv*
|
||||
*migrations* # 排除Django迁移文件
|
||||
*tests* # 排除测试文件
|
||||
*.html # 排除HTML模板文件
|
||||
*whoosh_cn_backend* # 排除中文搜索后端相关文件
|
||||
*settings.py* # 排除配置文件
|
||||
*venv* # 排除虚拟环境目录
|
||||
@ -1,11 +1,29 @@
|
||||
# 数据文件目录 - 通常包含动态生成的数据,不应纳入版本控制
|
||||
bin/data/
|
||||
# virtualenv
|
||||
|
||||
# Python 虚拟环境目录 - 包含项目依赖,应该通过 requirements.txt 管理
|
||||
venv/
|
||||
|
||||
# Django 收集的静态文件目录 - 由 collectstatic 命令生成
|
||||
collectedstatic/
|
||||
|
||||
# Whoosh 搜索引擎索引目录 - 包含搜索索引数据,会频繁变化
|
||||
djangoblog/whoosh_index/
|
||||
|
||||
# 用户上传文件目录 - 包含用户上传的媒体文件
|
||||
uploads/
|
||||
|
||||
# 生产环境配置文件 - 包含敏感信息如数据库密码、API密钥等
|
||||
settings_production.py
|
||||
|
||||
# 所有 Markdown 文档文件 - 可能是临时文件或本地笔记
|
||||
*.md
|
||||
|
||||
# 文档目录 - 可能包含生成的文档或本地文档
|
||||
docs/
|
||||
|
||||
# 日志文件目录 - 包含应用程序运行日志
|
||||
logs/
|
||||
|
||||
# 静态文件目录 - 可能包含前端构建产物或开发时的静态文件
|
||||
static/
|
||||
@ -1,6 +1,18 @@
|
||||
# 将 blog/static/ 目录下的所有文件标记为"vendored"(第三方代码)
|
||||
# 这样 GitHub 的语言统计会忽略这些文件
|
||||
blog/static/* linguist-vendored
|
||||
|
||||
# 将所有 .js 文件标记为"vendored",在语言统计中忽略
|
||||
*.js linguist-vendored
|
||||
|
||||
# 将所有 .css 文件标记为"vendored",在语言统计中忽略
|
||||
*.css linguist-vendored
|
||||
|
||||
# 设置所有文件使用自动换行符检测
|
||||
* text=auto
|
||||
|
||||
# 设置 .sh 文件为文本文件,并强制使用 LF 换行符
|
||||
*.sh text eol=lf
|
||||
|
||||
# 设置 .conf 文件为文本文件,并强制使用 LF 换行符
|
||||
*.conf text eol=lf
|
||||
Binary file not shown.
@ -1,74 +1,83 @@
|
||||
{% load blog_tags %}
|
||||
{% load cache %}
|
||||
{% load i18n %}
|
||||
<article id="post-{{ article.pk }} "
|
||||
class="post-{{ article.pk }} post type-post status-publish format-standard hentry">
|
||||
<header class="entry-header">
|
||||
{% load blog_tags %} {# 加载自定义博客标签 #}
|
||||
{% load cache %} {# 加载缓存标签 #}
|
||||
{% load i18n %} {# 加载国际化标签 #}
|
||||
|
||||
<article id="post-{{ article.pk }}" class="post-{{ article.pk }} post type-post status-publish format-standard hentry">
|
||||
|
||||
<header class="entry-header">
|
||||
{# 文章标题 #}
|
||||
<h1 class="entry-title">
|
||||
{% if isindex %}
|
||||
{% if article.article_order > 0 %}
|
||||
<a href="{{ article.get_absolute_url }}"
|
||||
rel="bookmark">【{% trans 'pin to top' %}】{{ article.title }}</a>
|
||||
{% else %}
|
||||
<a href="{{ article.get_absolute_url }}"
|
||||
rel="bookmark">{{ article.title }}</a>
|
||||
{% if isindex %} {# 如果是文章列表页 #}
|
||||
{% if article.article_order > 0 %} {# 如果文章有置顶顺序 #}
|
||||
<a href="{{ article.get_absolute_url }}" rel="bookmark">
|
||||
【{% trans 'pin to top' %}】{{ article.title }} {# 显示置顶标记 #}
|
||||
</a>
|
||||
{% else %} {# 普通文章 #}
|
||||
<a href="{{ article.get_absolute_url }}" rel="bookmark">
|
||||
{{ article.title }} {# 普通标题 #}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
{{ article.title }}
|
||||
{% else %} {# 如果是文章详情页 #}
|
||||
{{ article.title }} {# 直接显示标题,不带链接 #}
|
||||
{% endif %}
|
||||
</h1>
|
||||
|
||||
{# 评论链接和浏览统计 #}
|
||||
<div class="comments-link">
|
||||
{% if article.comment_status == "o" and open_site_comment %}
|
||||
<a href="{{ article.get_absolute_url }}#comments" class="ds-thread-count" data-thread-key="3815"
|
||||
rel="nofollow">
|
||||
{% if article.comment_status == "o" and open_site_comment %} {# 如果评论开启 #}
|
||||
<a href="{{ article.get_absolute_url }}#comments" class="ds-thread-count" data-thread-key="3815" rel="nofollow">
|
||||
<span class="leave-reply">
|
||||
{% if article.comment_set and article.comment_set.count %}
|
||||
{{ article.comment_set.count }} {% trans 'comments' %}
|
||||
{% else %}
|
||||
{% trans 'comment' %}
|
||||
{% endif %}
|
||||
{% if article.comment_set and article.comment_set.count %} {# 如果有评论 #}
|
||||
{{ article.comment_set.count }} {% trans 'comments' %} {# 显示评论数量 #}
|
||||
{% else %} {# 没有评论 #}
|
||||
{% trans 'comment' %} {# 显示"评论"文字 #}
|
||||
{% endif %}
|
||||
</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{# 浏览统计 #}
|
||||
<div style="float:right">
|
||||
{{ article.views }} views
|
||||
{{ article.views }} views {# 显示浏览次数 #}
|
||||
</div>
|
||||
</div><!-- .comments-link -->
|
||||
|
||||
<br/>
|
||||
{% if article.type == 'a' %}
|
||||
{% if not isindex %}
|
||||
{% cache 36000 breadcrumb article.pk %}
|
||||
{% load_breadcrumb article %}
|
||||
|
||||
{# 面包屑导航(仅限文章详情页且不是列表页) #}
|
||||
{% if article.type == 'a' %} {# 如果是文章类型 #}
|
||||
{% if not isindex %} {# 如果不是列表页 #}
|
||||
{% cache 36000 breadcrumb article.pk %} {# 缓存10小时 #}
|
||||
{% load_breadcrumb article %} {# 加载面包屑导航 #}
|
||||
{% endcache %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</header><!-- .entry-header -->
|
||||
|
||||
|
||||
{# 文章内容 #}
|
||||
<div class="entry-content" itemprop="articleBody">
|
||||
{% if isindex %}
|
||||
{% if isindex %} {# 列表页显示文章摘要 #}
|
||||
{# 处理markdown并截断内容 #}
|
||||
{{ article.body|custom_markdown|escape|truncatechars_content }}
|
||||
<p class='read-more'><a
|
||||
href=' {{ article.get_absolute_url }}'>Read more</a></p>
|
||||
{% else %}
|
||||
|
||||
{% if article.show_toc %}
|
||||
{# "阅读更多"链接 #}
|
||||
<p class='read-more'><a href='{{ article.get_absolute_url }}'>Read more</a></p>
|
||||
{% else %} {# 详情页显示完整内容 #}
|
||||
{% if article.show_toc %} {# 如果显示目录 #}
|
||||
{# 生成markdown目录 #}
|
||||
{% get_markdown_toc article.body as toc %}
|
||||
<b>{% trans 'toc' %}:</b>
|
||||
{{ toc|safe }}
|
||||
|
||||
<hr class="break_line"/>
|
||||
<b>{% trans 'toc' %}:</b> {# 目录标题 #}
|
||||
{{ toc|safe }} {# 安全输出HTML目录 #}
|
||||
<hr class="break_line"/> {# 分隔线 #}
|
||||
{% endif %}
|
||||
|
||||
{# 完整文章内容 #}
|
||||
<div class="article">
|
||||
|
||||
{{ article.body|custom_markdown|escape }}
|
||||
|
||||
{{ article.body|custom_markdown|escape }} {# 渲染完整markdown内容 #}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div><!-- .entry-content -->
|
||||
|
||||
|
||||
{# 加载文章元信息(作者、分类、标签等) #}
|
||||
{% load_article_metas article user %}
|
||||
|
||||
|
||||
</article><!-- #post -->
|
||||
@ -1,59 +1,65 @@
|
||||
{% load i18n %}
|
||||
{% load blog_tags %}
|
||||
|
||||
{% load i18n %} {# 加载国际化标签,支持多语言翻译 #}
|
||||
{% load blog_tags %} {# 加载自定义博客标签 #}
|
||||
|
||||
<footer class="entry-meta">
|
||||
{% trans 'posted in' %}
|
||||
<a href="{{ article.category.get_absolute_url }}" rel="category tag">{{ article.category.name }}</a>
|
||||
|
||||
|
||||
{# 文章分类信息 #}
|
||||
{% trans 'posted in' %} {# 翻译:"发表于" #}
|
||||
<a href="{{ article.category.get_absolute_url }}" rel="category tag">
|
||||
{{ article.category.name }} {# 显示分类名称 #}
|
||||
</a>
|
||||
{% if article.type == 'a' %}
|
||||
{% if article.tags.all %}
|
||||
|
||||
{% trans 'and tagged' %}
|
||||
{# 文章标签信息(仅对文章类型显示) #}
|
||||
{% if article.type == 'a' %} {# 如果是文章类型(非页面等) #}
|
||||
{% if article.tags.all %} {# 如果有标签 #}
|
||||
{% trans 'and tagged' %} {# 翻译:"和标签" #}
|
||||
{# 循环遍历所有标签 #}
|
||||
{% for t in article.tags.all %}
|
||||
<a href="{{ t.get_absolute_url }}" rel="tag">{{ t.name }}</a>
|
||||
<a href="{{ t.get_absolute_url }}" rel="tag">
|
||||
{{ t.name }} {# 显示标签名称 #}
|
||||
</a>
|
||||
{# 如果不是最后一个标签,添加逗号分隔 #}
|
||||
{% if t != article.tags.all.last %}
|
||||
,
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
.{% trans 'by ' %}
|
||||
|
||||
.{% trans 'by ' %} {# 翻译:"由" #}
|
||||
|
||||
{# 作者信息 #}
|
||||
<span class="by-author">
|
||||
<span class="author vcard">
|
||||
<a class="url fn n" href="{{ article.author.get_absolute_url }}"
|
||||
{% blocktranslate %}
|
||||
<a class="url fn n"
|
||||
href="{{ article.author.get_absolute_url }}"
|
||||
{% blocktranslate %} {# 翻译块 #}
|
||||
title="View all articles published by {{ article.author.username }}"
|
||||
{% endblocktranslate %}
|
||||
{% endblocktranslate %}
|
||||
rel="author">
|
||||
<span itemprop="author" itemscope itemtype="http://schema.org/Person">
|
||||
|
||||
<span itemprop="name" itemprop="publisher">
|
||||
|
||||
{{ article.author.username }}
|
||||
<span itemprop="author" itemscope itemtype="http://schema.org/Person">
|
||||
<span itemprop="name" itemprop="publisher">
|
||||
{{ article.author.username }} {# 显示作者用户名 #}
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
{% trans 'on' %} {# 翻译:"于" #}
|
||||
|
||||
{# 发布时间信息 #}
|
||||
<a href="{{ article.get_absolute_url }}"
|
||||
title="{% datetimeformat article.pub_time %}" {# 使用自定义过滤器格式化时间 #}
|
||||
itemprop="datePublished"
|
||||
content="{% datetimeformat article.pub_time %}"
|
||||
rel="bookmark">
|
||||
<time class="entry-date updated" datetime="{{ article.pub_time }}">
|
||||
{% datetimeformat article.pub_time %} {# 显示格式化后的发布时间 #}
|
||||
</time>
|
||||
</a>
|
||||
|
||||
|
||||
</span>
|
||||
{% trans 'on' %}
|
||||
<a href="{{ article.get_absolute_url }}"
|
||||
title="{% datetimeformat article.pub_time %}"
|
||||
itemprop="datePublished" content="{% datetimeformat article.pub_time %}"
|
||||
rel="bookmark">
|
||||
|
||||
<time class="entry-date updated"
|
||||
datetime="{{ article.pub_time }}">
|
||||
{% datetimeformat article.pub_time %}</time>
|
||||
{% if user.is_superuser %}
|
||||
<a href="{{ article.get_admin_url }}">{% trans 'edit' %}</a>
|
||||
{% endif %}
|
||||
|
||||
{# 管理员编辑链接 #}
|
||||
{% if user.is_superuser %} {# 如果是超级用户 #}
|
||||
<a href="{{ article.get_admin_url }}">{% trans 'edit' %}</a> {# 显示编辑链接 #}
|
||||
{% endif %}
|
||||
</span>
|
||||
</footer><!-- .entry-meta -->
|
||||
|
||||
|
||||
</footer><!-- .entry-meta -->
|
||||
@ -1,17 +1,29 @@
|
||||
{% load i18n %}
|
||||
{% load i18n %} {# 加载国际化标签,支持多语言翻译 #}
|
||||
|
||||
{# 文章分页导航 #}
|
||||
<nav id="nav-below" class="navigation" role="navigation">
|
||||
{# 导航标题(辅助文本,对屏幕阅读器友好) #}
|
||||
<h3 class="assistive-text">
|
||||
{% trans 'article navigation' %}
|
||||
{% trans 'article navigation' %} {# 翻译:"文章导航" #}
|
||||
</h3>
|
||||
{% if page_obj.has_next and next_url%}
|
||||
<div class="nav-previous"><a
|
||||
href="{{ next_url }}"><span
|
||||
class="meta-nav">←</span> {% trans 'earlier articles' %}</a></div>
|
||||
|
||||
{# 上一页/更早文章链接 #}
|
||||
{% if page_obj.has_next and next_url %} {# 如果有下一页且存在下一页URL #}
|
||||
<div class="nav-previous">
|
||||
<a href="{{ next_url }}"> {# 指向更早文章的链接 #}
|
||||
<span class="meta-nav">←</span> {# 左箭头图标 #}
|
||||
{% trans 'earlier articles' %} {# 翻译:"更早的文章" #}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if page_obj.has_previous and previous_url %}
|
||||
<div class="nav-next"><a href="{{ previous_url }}">{% trans 'newer articles' %}
|
||||
<span
|
||||
class="meta-nav">→</span></a>
|
||||
|
||||
{# 下一页/较新文章链接 #}
|
||||
{% if page_obj.has_previous and previous_url %} {# 如果有上一页且存在上一页URL #}
|
||||
<div class="nav-next">
|
||||
<a href="{{ previous_url }}"> {# 指向较新文章的链接 #}
|
||||
{% trans 'newer articles' %} {# 翻译:"较新的文章" #}
|
||||
<span class="meta-nav">→</span> {# 右箭头图标 #}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</nav><!-- .navigation -->
|
||||
@ -1,19 +1,26 @@
|
||||
{# 面包屑导航 - 使用Schema.org结构化数据 #}
|
||||
<ul itemscope itemtype="https://schema.org/BreadcrumbList" class="breadcrumb">
|
||||
|
||||
{# 循环遍历面包屑路径中的每个节点 #}
|
||||
{% for name,url in names %}
|
||||
<li itemprop="itemListElement" itemscope
|
||||
itemtype="https://schema.org/ListItem">
|
||||
<a href="{{ url }}" itemprop="item" >
|
||||
<span itemprop="name">{{ name }}</span></a>
|
||||
{# 可点击的面包屑链接 #}
|
||||
<a href="{{ url }}" itemprop="item">
|
||||
<span itemprop="name">{{ name }}</span>
|
||||
</a>
|
||||
{# 位置序号 - Schema.org结构化数据 #}
|
||||
<meta itemprop="position" content="{{ forloop.counter }}"/>
|
||||
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
{# 当前页面(最后一个节点,不可点击) #}
|
||||
<li class="active" itemprop="itemListElement" itemscope
|
||||
itemtype="https://schema.org/ListItem">
|
||||
{# 当前页面名称 #}
|
||||
<span itemprop="name">{{ title }}</span>
|
||||
{# 当前位置序号 #}
|
||||
<meta itemprop="position" content="{{ count }}"/>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
@ -1,34 +1,48 @@
|
||||
{% load blog_tags %}
|
||||
{% load blog_tags %} {# 加载自定义博客标签 #}
|
||||
|
||||
{# 评论项模板 - 显示单条评论及其回复 #}
|
||||
<li class="comment even thread-even depth-{{ depth }} parent" id="comment-{{ comment_item.pk }}">
|
||||
<div id="div-comment-{{ comment_item.pk }}" class="comment-body">
|
||||
|
||||
{# 评论作者信息 #}
|
||||
<div class="comment-author vcard">
|
||||
{# 使用Gravatar显示头像 #}
|
||||
<img alt=""
|
||||
src="{{ comment_item.author.email|gravatar_url:150 }}"
|
||||
srcset="{{ comment_item.author.email|gravatar_url:150 }}"
|
||||
src="{{ comment_item.author.email|gravatar_url:150 }}" {# 通过邮箱获取Gravatar头像 #}
|
||||
class="avatar avatar-96 photo" height="96" width="96">
|
||||
{# 作者姓名 #}
|
||||
<cite class="fn">
|
||||
<a rel="nofollow"
|
||||
{% if comment_item.author.is_superuser %}
|
||||
href="{{ comment_item.author.get_absolute_url }}"
|
||||
{% else %}
|
||||
href="#"
|
||||
{% endif %}
|
||||
{% if comment_item.author.is_superuser %} {# 如果是超级用户 #}
|
||||
href="{{ comment_item.author.get_absolute_url }}" {# 链接到用户主页 #}
|
||||
{% else %}
|
||||
href="#" {# 普通用户无链接 #}
|
||||
{% endif %}
|
||||
rel="external nofollow"
|
||||
class="url">{{ comment_item.author.username }}
|
||||
class="url">
|
||||
{{ comment_item.author.username }} {# 显示用户名 #}
|
||||
</a>
|
||||
</cite>
|
||||
|
||||
</div>
|
||||
|
||||
{# 评论元信息 #}
|
||||
<div class="comment-meta commentmetadata">
|
||||
<div>{{ comment_item.creation_time }}</div>
|
||||
<div>{{ comment_item.creation_time }}</div> {# 评论时间 #}
|
||||
{# 回复对象信息 #}
|
||||
<div>回复给:@{{ comment_item.author.parent_comment.username }}</div>
|
||||
</div>
|
||||
<p>{{ comment_item.body|escape|comment_markdown }}</p>
|
||||
<div class="reply"><a rel="nofollow" class="comment-reply-link"
|
||||
href="javascript:void(0)"
|
||||
onclick="do_reply({{ comment_item.pk }})"
|
||||
aria-label="回复给{{ comment_item.author.username }}">回复</a></div>
|
||||
|
||||
{# 评论内容 #}
|
||||
<p>{{ comment_item.body|escape|comment_markdown }}</p> {# 安全处理并渲染markdown #}
|
||||
|
||||
{# 回复按钮 #}
|
||||
<div class="reply">
|
||||
<a rel="nofollow" class="comment-reply-link"
|
||||
href="javascript:void(0)"
|
||||
onclick="do_reply({{ comment_item.pk }})" {# 点击触发回复函数 #}
|
||||
aria-label="回复给{{ comment_item.author.username }}"> {# 无障碍标签 #}
|
||||
回复 {# 回复按钮文本 #}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</li><!-- #comment-## -->
|
||||
@ -1,53 +1,69 @@
|
||||
{% load blog_tags %}
|
||||
{% load blog_tags %} {# 加载自定义博客标签 #}
|
||||
|
||||
{# 评论项模板 - 支持嵌套回复的树形结构 #}
|
||||
<li class="comment even thread-even depth-{{ depth }} parent" id="comment-{{ comment_item.pk }}"
|
||||
style="margin-left: {% widthratio depth 1 3 %}rem">
|
||||
style="margin-left: {% widthratio depth 1 3 %}rem"> {# 根据深度设置左边距,实现缩进 #}
|
||||
<div id="div-comment-{{ comment_item.pk }}" class="comment-body">
|
||||
|
||||
{# 评论作者信息 #}
|
||||
<div class="comment-author vcard">
|
||||
{# Gravatar头像 #}
|
||||
<img alt=""
|
||||
src="{{ comment_item.author.email|gravatar_url:150 }}"
|
||||
srcset="{{ comment_item.author.email|gravatar_url:150 }}"
|
||||
class="avatar avatar-96 photo" height="96" width="96">
|
||||
{# 作者姓名 #}
|
||||
<cite class="fn">
|
||||
<a rel="nofollow"
|
||||
{% if comment_item.author.is_superuser %}
|
||||
{% if comment_item.author.is_superuser %} {# 超级用户有个人主页链接 #}
|
||||
href="{{ comment_item.author.get_absolute_url }}"
|
||||
{% else %}
|
||||
href="#"
|
||||
{% endif %}
|
||||
{% else %}
|
||||
href="#" {# 普通用户无链接 #}
|
||||
{% endif %}
|
||||
rel="external nofollow"
|
||||
class="url">{{ comment_item.author.username }}
|
||||
class="url">
|
||||
{{ comment_item.author.username }}
|
||||
</a>
|
||||
</cite>
|
||||
|
||||
</div>
|
||||
|
||||
{# 评论元信息 #}
|
||||
<div class="comment-meta commentmetadata">
|
||||
{{ comment_item.creation_time }}
|
||||
{{ comment_item.creation_time }} {# 评论时间 #}
|
||||
</div>
|
||||
|
||||
{# 回复对象信息 #}
|
||||
<p>
|
||||
{% if comment_item.parent_comment %}
|
||||
<div>回复 <a
|
||||
href="#comment-{{ comment_item.parent_comment.pk }}">@{{ comment_item.parent_comment.author.username }}</a>
|
||||
{% if comment_item.parent_comment %} {# 如果是回复评论 #}
|
||||
<div>
|
||||
回复 <a href="#comment-{{ comment_item.parent_comment.pk }}"> {# 跳转到父评论 #}
|
||||
@{{ comment_item.parent_comment.author.username }} {# 显示被回复者用户名 #}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
<p>{{ comment_item.body|escape|comment_markdown }}</p>
|
||||
{# 评论内容 #}
|
||||
<p>{{ comment_item.body|escape|comment_markdown }}</p> {# 安全渲染评论内容 #}
|
||||
|
||||
<div class="reply"><a rel="nofollow" class="comment-reply-link"
|
||||
href="javascript:void(0)" data-pk="{{ comment_item.pk }}"
|
||||
aria-label="回复给{{ comment_item.author.username }}">回复</a></div>
|
||||
{# 回复按钮 #}
|
||||
<div class="reply">
|
||||
<a rel="nofollow" class="comment-reply-link"
|
||||
href="javascript:void(0)"
|
||||
data-pk="{{ comment_item.pk }}" {# 存储评论ID用于JavaScript #}
|
||||
aria-label="回复给{{ comment_item.author.username }}">回复</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</li><!-- #comment-## -->
|
||||
{% query article_comments parent_comment=comment_item as cc_comments %}
|
||||
{% for cc in cc_comments %}
|
||||
|
||||
{# 递归加载子评论 - 构建评论树 #}
|
||||
{% query article_comments parent_comment=comment_item as cc_comments %} {# 查询当前评论的子评论 #}
|
||||
{% for cc in cc_comments %} {# 遍历所有子评论 #}
|
||||
{% with comment_item=cc template_name="comments/tags/comment_item_tree.html" %}
|
||||
{% if depth >= 1 %}
|
||||
{% include template_name %}
|
||||
{% else %}
|
||||
{% with depth=depth|add:1 %}
|
||||
{% include template_name %}
|
||||
{% if depth >= 1 %} {# 如果已经有一定深度 #}
|
||||
{% include template_name %} {# 直接包含模板,保持当前深度 #}
|
||||
{% else %} {# 如果是第一层深度 #}
|
||||
{% with depth=depth|add:1 %} {# 深度加1 #}
|
||||
{% include template_name %} {# 包含模板,深度递增 #}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
{# 显示文章/内容标题 #}
|
||||
{{ object.title }}
|
||||
|
||||
{# 显示作者用户名 #}
|
||||
{{ object.author.username }}
|
||||
|
||||
{# 显示文章/内容正文 #}
|
||||
{{ object.body }}
|
||||
@ -1,66 +1,82 @@
|
||||
{% extends 'share_layout/base.html' %}
|
||||
{% load blog_tags %}
|
||||
{% extends 'share_layout/base.html' %} {# 继承基础布局模板 #}
|
||||
{% load blog_tags %} {# 加载自定义博客标签 #}
|
||||
|
||||
{% block header %}
|
||||
<title>{{ SITE_NAME }} | {{ SITE_DESCRIPTION }}</title>
|
||||
{# 页面头部元信息 #}
|
||||
<title>{{ SITE_NAME }} |{{ SITE_DESCRIPTION }}</title> {# 页面标题 #}
|
||||
|
||||
{# SEO优化元标签 #}
|
||||
<meta name="description" content="{{ SITE_SEO_DESCRIPTION }}"/>
|
||||
<meta name="keywords" content="{{ SITE_KEYWORDS }}"/>
|
||||
|
||||
{# Open Graph社交媒体元标签 #}
|
||||
<meta property="og:type" content="blog"/>
|
||||
<meta property="og:title" content="{{ SITE_NAME }}"/>
|
||||
<meta property="og:description" content="{{ SITE_DESCRIPTION }}"/>
|
||||
<meta property="og:url" content="{{ SITE_BASE_URL }}"/>
|
||||
<meta property="og:site_name" content="{{ SITE_NAME }}"/>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="primary" class="site-content">
|
||||
<div id="primary" class="site-content"> {# 主要内容区域 #}
|
||||
<div id="content" role="main">
|
||||
{% if query %}
|
||||
{% if query %} {# 如果有搜索查询 #}
|
||||
<header class="archive-header">
|
||||
{% if suggestion %}
|
||||
{% if suggestion %} {# 如果有搜索建议 #}
|
||||
<h2 class="archive-title">
|
||||
已显示<span style="color: red"> “{{ suggestion }}” </span>的搜索结果。
|
||||
已显示<span style="color: red"> "{{ suggestion }}" </span>的搜索结果。
|
||||
仍然搜索:<a style="text-transform: none;" href="/search/?q={{ query }}&is_suggest=no">{{ query }}</a> <br>
|
||||
{# 显示搜索建议,并提供原始搜索链接 #}
|
||||
</h2>
|
||||
{% else %}
|
||||
{% else %} {# 没有搜索建议,直接显示原始搜索词 #}
|
||||
<h2 class="archive-title">
|
||||
搜索:<span style="color: red">{{ query }} </span>
|
||||
</h2>
|
||||
{% endif %}
|
||||
</header><!-- .archive-header -->
|
||||
{% endif %}
|
||||
{% if query and page.object_list %}
|
||||
|
||||
{# 搜索结果展示 #}
|
||||
{% if query and page.object_list %} {# 如果有查询词且有搜索结果 #}
|
||||
{# 循环显示搜索结果文章 #}
|
||||
{% for article in page.object_list %}
|
||||
{% load_article_detail article.object True user %}
|
||||
{% load_article_detail article.object True user %} {# 加载文章摘要显示 #}
|
||||
{% endfor %}
|
||||
{% if page.has_previous or page.has_next %}
|
||||
|
||||
{# 分页导航 #}
|
||||
{% if page.has_previous or page.has_next %} {# 如果需要分页 #}
|
||||
<nav id="nav-below" class="navigation" role="navigation">
|
||||
<h3 class="assistive-text">文章导航</h3>
|
||||
{% if page.has_previous %}
|
||||
<div class="nav-previous"><a
|
||||
href="?q={{ query }}&page={{ page.previous_page_number }}"><span
|
||||
class="meta-nav">←</span> 早期文章</a></div>
|
||||
<h3 class="assistive-text">文章导航</h3> {# 屏幕阅读器辅助文本 #}
|
||||
{% if page.has_previous %} {# 上一页链接 #}
|
||||
<div class="nav-previous">
|
||||
<a href="?q={{ query }}&page={{ page.previous_page_number }}">
|
||||
<span class="meta-nav">←</span> 早期文章
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if page.has_next %}
|
||||
<div class="nav-next"><a href="?q={{ query }}&page={{ page.next_page_number }}">较新文章
|
||||
<span
|
||||
class="meta-nav">→</span></a>
|
||||
{% if page.has_next %} {# 下一页链接 #}
|
||||
<div class="nav-next">
|
||||
<a href="?q={{ query }}&page={{ page.next_page_number }}">
|
||||
较新文章 <span class="meta-nav">→</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</nav><!-- .navigation -->
|
||||
|
||||
{% endif %}
|
||||
{% else %}
|
||||
|
||||
{% else %} {# 没有搜索结果 #}
|
||||
<header class="archive-header">
|
||||
|
||||
<h1 class="archive-title">哎呀,关键字:<span>{{ query }}</span>没有找到结果,要不换个词再试试?</h1>
|
||||
<h1 class="archive-title">
|
||||
哎呀,关键字:<span>{{ query }}</span>没有找到结果,要不换个词再试试?
|
||||
{# 友好的无结果提示 #}
|
||||
</h1>
|
||||
</header><!-- .archive-header -->
|
||||
{% endif %}
|
||||
</div><!-- #content -->
|
||||
</div><!-- #primary -->
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block sidebar %}
|
||||
{% load_sidebar request.user 'i' %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{# 侧边栏区域 #}
|
||||
{% load_sidebar request.user 'i' %} {# 加载侧边栏内容 #}
|
||||
{% endblock %}
|
||||
@ -1,6 +1,10 @@
|
||||
<aside id="text-2" class="widget widget_text"><h3 class="widget-title">Google AdSense</h3>
|
||||
{# Google AdSense广告组件 #}
|
||||
<aside id="text-2" class="widget widget_text">
|
||||
{# 小部件标题 #}
|
||||
<h3 class="widget-title">Google AdSense</h3>
|
||||
{# 文本小部件内容区域 #}
|
||||
<div class="textwidget">
|
||||
|
||||
{# 显示Google AdSense广告代码 #}
|
||||
{{ GOOGLE_ADSENSE_CODES }}
|
||||
</div>
|
||||
</aside>
|
||||
@ -1,29 +1,34 @@
|
||||
{% load i18n %}
|
||||
{% load i18n %} {# 加载国际化标签,支持多语言翻译 #}
|
||||
|
||||
<nav id="site-navigation" class="main-navigation" role="navigation">
|
||||
<div class="menu-%e8%8f%9c%e5%8d%95-container">
|
||||
<ul id="menu-%e8%8f%9c%e5%8d%95" class="nav-menu">
|
||||
<div class="menu-%e8%8f%9c%e5%8d%95-container"> {# URL编码的"菜单"中文 #}
|
||||
<ul id="menu-%e8%8f%9c%e5%8d%95" class="nav-menu"> {# 导航菜单列表 #}
|
||||
{# 首页链接 #}
|
||||
<li id="menu-item-3498"
|
||||
class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-3498">
|
||||
<a href="/">{% trans 'index' %}</a></li>
|
||||
<a href="/">{% trans 'index' %}</a> {# 翻译:"首页" #}
|
||||
</li>
|
||||
|
||||
{# 动态加载分类导航 #}
|
||||
{% load blog_tags %}
|
||||
{% query nav_category_list parent_category=None as root_categorys %}
|
||||
{% for node in root_categorys %}
|
||||
{% include 'share_layout/nav_node.html' %}
|
||||
{% query nav_category_list parent_category=None as root_categorys %} {# 查询顶级分类 #}
|
||||
{% for node in root_categorys %} {# 遍历所有顶级分类 #}
|
||||
{% include 'share_layout/nav_node.html' %} {# 包含分类节点模板 #}
|
||||
{% endfor %}
|
||||
{% if nav_pages %}
|
||||
{% for node in nav_pages %}
|
||||
|
||||
|
||||
{# 静态页面导航 #}
|
||||
{% if nav_pages %} {# 如果有导航页面 #}
|
||||
{% for node in nav_pages %} {# 遍历导航页面 #}
|
||||
<li id="menu-item-{{ node.pk }}"
|
||||
class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-{{ node.pk }}">
|
||||
<a href="{{ node.get_absolute_url }}">{{ node.title }}</a>
|
||||
<a href="{{ node.get_absolute_url }}">{{ node.title }}</a> {# 页面标题和链接 #}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{# 文章归档链接 #}
|
||||
<li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children">
|
||||
|
||||
<a href="{% url "blog:archives" %}">{% trans 'Article archive' %}</a>
|
||||
<a href="{% url "blog:archives" %}">{% trans 'Article archive' %}</a> {# 翻译:"文章归档" #}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
{# 导航菜单节点模板 - 支持递归渲染子菜单 #}
|
||||
<li id="menu-item-{{ node.pk }}"
|
||||
class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-{{ node.pk }}">
|
||||
{# 当前分类链接 #}
|
||||
<a href="{{ node.get_absolute_url }}">{{ node.name }}</a>
|
||||
|
||||
{# 加载子分类 #}
|
||||
{% load blog_tags %}
|
||||
{% query nav_category_list parent_category=node as child_categorys %}
|
||||
{% if child_categorys %}
|
||||
|
||||
<ul class="sub-menu">
|
||||
{% for child in child_categorys %}
|
||||
{% query nav_category_list parent_category=node as child_categorys %} {# 查询当前分类的子分类 #}
|
||||
|
||||
{% if child_categorys %} {# 如果存在子分类 #}
|
||||
<ul class="sub-menu"> {# 子菜单容器 #}
|
||||
{% for child in child_categorys %} {# 遍历所有子分类 #}
|
||||
{# 递归调用自身模板渲染子分类 #}
|
||||
{% with node=child template_name="share_layout/nav_node.html" %}
|
||||
{% include template_name %}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
|
||||
</li>
|
||||
@ -1 +1,2 @@
|
||||
print('hello world')
|
||||
# This is the main Python file
|
||||
|
||||
Binary file not shown.
Loading…
Reference in new issue