From 61f85809878f4b4ed99662f35f93dfc8ca8226b6 Mon Sep 17 00:00:00 2001
From: zhangyu <1990336738@qq.com>
Date: Fri, 3 Oct 2025 23:47:33 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/.github/workflows/django.yml | 10 +-
src/Dockerfile | 6 +-
src/LICENSE | 2 +-
src/README.md | 201 +++++++++++-------------
src/accounts/tests.py | 14 +-
src/bin/docker_start.sh | 31 ++++
src/bin/nginx.conf | 50 ++++++
src/blog/admin.py | 21 ++-
src/blog/models.py | 11 --
src/blog/templatetags/blog_tags.py | 6 -
src/blog/tests.py | 4 +-
src/blog/views.py | 18 +--
src/comments/admin.py | 4 +-
src/djangoblog/__init__.py | 1 -
src/djangoblog/settings.py | 21 +--
src/djangoblog/spider_notify.py | 10 ++
src/djangoblog/whoosh_cn_backend.py | 2 +-
src/docker-compose.es.yml | 48 ++++++
src/docker-compose.yml | 59 ++++++++
src/docs/README-en.md | 202 ++++++++++---------------
src/docs/docker.md | 157 +++++++------------
src/owntracks/views.py | 10 +-
src/requirements.txt | Bin 2554 -> 474 bytes
src/templates/blog/article_detail.html | 24 +++
src/templates/share_layout/base.html | 40 ++---
25 files changed, 525 insertions(+), 427 deletions(-)
create mode 100644 src/bin/docker_start.sh
create mode 100644 src/bin/nginx.conf
create mode 100644 src/docker-compose.es.yml
create mode 100644 src/docker-compose.yml
diff --git a/src/.github/workflows/django.yml b/src/.github/workflows/django.yml
index 94baea9..bf23242 100644
--- a/src/.github/workflows/django.yml
+++ b/src/.github/workflows/django.yml
@@ -9,6 +9,7 @@ on:
- '**/*.md'
- '**/*.css'
- '**/*.js'
+ - '**/*.yml'
pull_request:
branches:
- master
@@ -17,6 +18,7 @@ on:
- '**/*.md'
- '**/*.css'
- '**/*.js'
+ - '**/*.yml'
jobs:
build-normal:
@@ -24,7 +26,7 @@ jobs:
strategy:
max-parallel: 4
matrix:
- python-version: ["3.10","3.11" ]
+ python-version: [ "3.8", "3.9","3.10","3.11" ]
steps:
- name: Start MySQL
@@ -64,7 +66,7 @@ jobs:
strategy:
max-parallel: 4
matrix:
- python-version: ["3.10","3.11" ]
+ python-version: [ "3.8", "3.9","3.10","3.11" ]
steps:
- name: Start MySQL
@@ -88,11 +90,9 @@ jobs:
sudo sysctl -w vm.max_map_count=262144
- uses: miyataka/elasticsearch-github-actions@1
-
with:
stack-version: '7.12.1'
- plugins: 'https://release.infinilabs.com/analysis-ik/stable/elasticsearch-analysis-ik-7.12.1.zip'
-
+ plugins: 'https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip'
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
diff --git a/src/Dockerfile b/src/Dockerfile
index 80b46ac..9b14ebe 100644
--- a/src/Dockerfile
+++ b/src/Dockerfile
@@ -6,10 +6,10 @@ RUN apt-get update && \
rm -rf /var/lib/apt/lists/*
ADD requirements.txt requirements.txt
RUN pip install --upgrade pip && \
- pip install --no-cache-dir -r requirements.txt && \
+ pip install --no-cache-dir -r requirements.txt && \
pip install --no-cache-dir gunicorn[gevent] && \
pip cache purge
ADD . .
-RUN chmod +x /code/djangoblog/deploy/entrypoint.sh
-ENTRYPOINT ["/code/djangoblog/deploy/entrypoint.sh"]
+RUN chmod +x /code/djangoblog/bin/docker_start.sh
+ENTRYPOINT ["/code/djangoblog/bin/docker_start.sh"]
diff --git a/src/LICENSE b/src/LICENSE
index 3b08474..1e22954 100644
--- a/src/LICENSE
+++ b/src/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2025 车亮亮
+Copyright (c) 2016 车亮亮
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
diff --git a/src/README.md b/src/README.md
index 56aa4cc..54a27f2 100644
--- a/src/README.md
+++ b/src/README.md
@@ -1,158 +1,137 @@
# DjangoBlog
-
-
-
-
-
-
-
-
- 一款功能强大、设计优雅的现代化博客系统
-
- English • 简体中文
-
+🌍
+*[English](/docs/README-en.md) ∙ [简体中文](README.md)*
----
+基于`python3.10`和`Django4.0`的博客。
-DjangoBlog 是一款基于 Python 3.10 和 Django 4.0 构建的高性能博客平台。它不仅提供了传统博客的所有核心功能,还通过一个灵活的插件系统,让您可以轻松扩展和定制您的网站。无论您是个人博主、技术爱好者还是内容创作者,DjangoBlog 都旨在为您提供一个稳定、高效且易于维护的写作和发布环境。
+[](https://github.com/liangliangyy/DjangoBlog/actions/workflows/django.yml) [](https://github.com/liangliangyy/DjangoBlog/actions/workflows/codeql-analysis.yml) [](https://codecov.io/gh/liangliangyy/DjangoBlog) []()
-## ✨ 特性亮点
+## 主要功能:
+- 文章,页面,分类目录,标签的添加,删除,编辑等。文章、评论及页面支持`Markdown`,支持代码高亮。
+- 支持文章全文搜索。
+- 完整的评论功能,包括发表回复评论,以及评论的邮件提醒,支持`Markdown`。
+- 侧边栏功能,最新文章,最多阅读,标签云等。
+- 支持Oauth登陆,现已有Google,GitHub,facebook,微博,QQ登录。
+- 支持`Redis`缓存,支持缓存自动刷新。
+- 简单的SEO功能,新建文章等会自动通知Google和百度。
+- 集成了简单的图床功能。
+- 集成`django-compressor`,自动压缩`css`,`js`。
+- 网站异常邮件提醒,若有未捕捉到的异常会自动发送提醒邮件。
+- 集成了微信公众号功能,现在可以使用微信公众号来管理你的vps了。
-- **强大的内容管理**: 支持文章、独立页面、分类和标签的完整管理。内置强大的 Markdown 编辑器,支持代码语法高亮。
-- **全文搜索**: 集成搜索引擎,提供快速、精准的文章内容搜索。
-- **互动评论系统**: 支持回复、邮件提醒等功能,评论内容同样支持 Markdown。
-- **灵活的侧边栏**: 可自定义展示最新文章、最多阅读、标签云等模块。
-- **社交化登录**: 内置 OAuth 支持,已集成 Google, GitHub, Facebook, 微博, QQ 等主流平台。
-- **高性能缓存**: 原生支持 Redis 缓存,并提供自动刷新机制,确保网站高速响应。
-- **SEO 友好**: 具备基础 SEO 功能,新内容发布后可自动通知 Google 和百度。
-- **便捷的插件系统**: 通过创建独立的插件来扩展博客功能,代码解耦,易于维护。我们已经通过插件实现了文章浏览计数、SEO 优化等功能!
-- **集成图床**: 内置简单的图床功能,方便图片上传和管理。
-- **自动化前端**: 集成 `django-compressor`,自动压缩和优化 CSS 及 JavaScript 文件。
-- **健壮的运维**: 内置网站异常邮件提醒和微信公众号管理功能。
-## 🛠️ 技术栈
+## 安装
+mysql客户端从`pymysql`修改成了`mysqlclient`,具体请参考 [pypi](https://pypi.org/project/mysqlclient/) 查看安装前的准备。
-- **后端**: Python 3.10, Django 4.0
-- **数据库**: MySQL, SQLite (可配置)
-- **缓存**: Redis
-- **前端**: HTML5, CSS3, JavaScript
-- **搜索**: Whoosh, Elasticsearch (可配置)
-- **编辑器**: Markdown (mdeditor)
+使用pip安装: `pip install -Ur requirements.txt`
-## 🚀 快速开始
+如果你没有pip,使用如下方式安装:
+- OS X / Linux 电脑,终端下执行:
-### 1. 环境准备
+ ```
+ curl http://peak.telecommunity.com/dist/ez_setup.py | python
+ curl https://bootstrap.pypa.io/get-pip.py | python
+ ```
-确保您的系统中已安装 Python 3.10+ 和 MySQL/MariaDB。
+- Windows电脑:
-### 2. 克隆与安装
+ 下载 http://peak.telecommunity.com/dist/ez_setup.py 和 https://raw.github.com/pypa/pip/master/contrib/get-pip.py 这两个文件,双击运行。
-```bash
-# 克隆项目到本地
-git clone https://github.com/liangliangyy/DjangoBlog.git
-cd DjangoBlog
-# 安装依赖
-pip install -r requirements.txt
+## 运行
+
+ 修改`djangoblog/setting.py` 修改数据库配置,如下所示:
+
+```python
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'NAME': 'djangoblog',
+ 'USER': 'root',
+ 'PASSWORD': 'password',
+ 'HOST': 'host',
+ 'PORT': 3306,
+ }
+}
```
-### 3. 项目配置
-
-- **数据库**:
- 打开 `djangoblog/settings.py` 文件,找到 `DATABASES` 配置项,修改为您的 MySQL 连接信息。
-
- ```python
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'djangoblog',
- 'USER': 'root',
- 'PASSWORD': 'your_password',
- 'HOST': '127.0.0.1',
- 'PORT': 3306,
- }
- }
- ```
- 在 MySQL 中创建数据库:
- ```sql
- CREATE DATABASE `djangoblog` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- ```
-
-- **更多配置**:
- 关于邮件发送、OAuth 登录、缓存等更多高级配置,请参阅我们的 [详细配置文档](/docs/config.md)。
-
-### 4. 初始化数据库
+### 创建数据库
+mysql数据库中执行:
+```sql
+CREATE DATABASE `djangoblog` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;
+```
+然后终端下执行:
```bash
python manage.py makemigrations
python manage.py migrate
+```
+
+### 创建超级用户
-# 创建一个超级管理员账户
+ 终端下执行:
+```bash
python manage.py createsuperuser
```
-### 5. 运行项目
-
+### 创建测试数据
+终端下执行:
```bash
-# (可选) 生成一些测试数据
python manage.py create_testdata
+```
-# (可选) 收集和压缩静态文件
+### 收集静态文件
+终端下执行:
+```bash
python manage.py collectstatic --noinput
python manage.py compress --force
-
-# 启动开发服务器
-python manage.py runserver
```
-现在,在您的浏览器中访问 `http://127.0.0.1:8000/`,您应该能看到 DjangoBlog 的首页了!
-
-## 部署
+### 开始运行:
+执行: `python manage.py runserver`
-- **传统部署**: 我们为您准备了非常详细的 [服务器部署教程](https://www.lylinux.net/article/2019/8/5/58.html)。
-- **Docker 部署**: 项目已全面支持 Docker。如果您熟悉容器化技术,请参考 [Docker 部署文档](/docs/docker.md) 来快速启动。
-- **Kubernetes 部署**: 我们也提供了完整的 [Kubernetes 部署指南](/docs/k8s.md),助您轻松上云。
-## 🧩 插件系统
+浏览器打开: http://127.0.0.1:8000/ 就可以看到效果了。
-插件系统是 DjangoBlog 的核心特色之一。它允许您在不修改核心代码的情况下,通过编写独立的插件来为您的博客添加新功能。
+## 服务器部署
-- **工作原理**: 插件通过在预定义的“钩子”上注册回调函数来工作。例如,当一篇文章被渲染时,`after_article_body_get` 钩子会被触发,所有注册到此钩子的函数都会被执行。
-- **现有插件**: `view_count`(浏览计数), `seo_optimizer`(SEO优化)等都是通过插件系统实现的。
-- **开发您自己的插件**: 只需在 `plugins` 目录下创建一个新的文件夹,并编写您的 `plugin.py`。欢迎探索并为 DjangoBlog 社区贡献您的创意!
+本地安装部署请参考 [DjangoBlog部署教程](https://www.lylinux.net/article/2019/8/5/58.html)
+有详细的部署介绍.
-## 🤝 贡献指南
+本项目已经支持使用docker来部署,如果你有docker环境那么可以使用docker来部署,具体请参考:[docker部署](/docs/docker.md)
-我们热烈欢迎任何形式的贡献!如果您有好的想法或发现了 Bug,请随时提交 Issue 或 Pull Request。
-## 📄 许可证
-本项目基于 [MIT License](LICENSE) 开源。
+## 更多配置:
+[更多配置介绍](/docs/config.md)
+[集成elasticsearch](/docs/es.md)
----
-
-## ❤️ 支持与赞助
+## 问题相关
-如果您觉得这个项目对您有帮助,并且希望支持我继续维护和开发新功能,欢迎请我喝杯咖啡!您的每一份支持都是我前进的最大动力。
+有任何问题欢迎提Issue,或者将问题描述发送至我邮箱 `liangliangyy#gmail.com`.我会尽快解答.推荐提交Issue方式.
-
-
-
-
-
- (左) 支付宝 / (右) 微信
-
+---
+ ## 致大家🙋♀️🙋♂️
+ 如果本项目帮助到了你,请在[这里](https://github.com/liangliangyy/DjangoBlog/issues/214)留下你的网址,让更多的人看到。
+您的回复将会是我继续更新维护下去的动力。
-## 🙏 鸣谢
-特别感谢 **JetBrains** 为本项目提供的免费开源许可证。
+## 捐赠
+如果您觉得本项目对您有所帮助,欢迎您请我喝杯咖啡,您的支持是我最大的动力,您可以扫描下方二维码为我付款,谢谢。
+### 支付宝:
+
+
+
-
-
-
-
-
+### 微信:
+
+
+
---
-> 如果本项目帮助到了你,请在[这里](https://github.com/liangliangyy/DjangoBlog/issues/214)留下你的网址,让更多的人看到。您的回复将会是我继续更新维护下去的动力。
+
+感谢jetbrains
+
+
+
diff --git a/src/accounts/tests.py b/src/accounts/tests.py
index 6893411..a308563 100644
--- a/src/accounts/tests.py
+++ b/src/accounts/tests.py
@@ -187,7 +187,12 @@ class AccountTest(TestCase):
)
self.assertEqual(resp.status_code, 200)
-
+ self.assertFormError(
+ response=resp,
+ form="form",
+ field="email",
+ errors=_("email does not exist")
+ )
def test_forget_password_email_code_error(self):
code = generate_code()
@@ -204,4 +209,9 @@ class AccountTest(TestCase):
)
self.assertEqual(resp.status_code, 200)
-
+ self.assertFormError(
+ response=resp,
+ form="form",
+ field="code",
+ errors=_('Verification code error')
+ )
diff --git a/src/bin/docker_start.sh b/src/bin/docker_start.sh
new file mode 100644
index 0000000..0be35a5
--- /dev/null
+++ b/src/bin/docker_start.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+NAME="djangoblog"
+DJANGODIR=/code/djangoblog
+USER=root
+GROUP=root
+NUM_WORKERS=1
+DJANGO_WSGI_MODULE=djangoblog.wsgi
+
+
+echo "Starting $NAME as `whoami`"
+
+cd $DJANGODIR
+
+export PYTHONPATH=$DJANGODIR:$PYTHONPATH
+
+python manage.py makemigrations && \
+ python manage.py migrate && \
+ python manage.py collectstatic --noinput && \
+ python manage.py compress --force && \
+ python manage.py build_index && \
+ python manage.py compilemessages
+
+exec gunicorn ${DJANGO_WSGI_MODULE}:application \
+--name $NAME \
+--workers $NUM_WORKERS \
+--user=$USER --group=$GROUP \
+--bind 0.0.0.0:8000 \
+--log-level=debug \
+--log-file=- \
+--worker-class gevent \
+--threads 4
diff --git a/src/bin/nginx.conf b/src/bin/nginx.conf
new file mode 100644
index 0000000..32161d8
--- /dev/null
+++ b/src/bin/nginx.conf
@@ -0,0 +1,50 @@
+user nginx;
+worker_processes auto;
+
+error_log /var/log/nginx/error.log notice;
+pid /var/run/nginx.pid;
+
+
+events {
+ worker_connections 1024;
+}
+
+
+http {
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ access_log /var/log/nginx/access.log main;
+
+ sendfile on;
+ #tcp_nopush on;
+
+ keepalive_timeout 65;
+
+ #gzip on;
+
+ server {
+ root /code/djangoblog/collectedstatic/;
+ listen 80;
+ keepalive_timeout 70;
+ location /static/ {
+ expires max;
+ alias /code/djangoblog/collectedstatic/;
+ }
+ location / {
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Host $http_host;
+ proxy_set_header X-NginX-Proxy true;
+ proxy_redirect off;
+ if (!-f $request_filename) {
+ proxy_pass http://djangoblog:8000;
+ break;
+ }
+ }
+ }
+}
diff --git a/src/blog/admin.py b/src/blog/admin.py
index 46c3420..5e1e035 100644
--- a/src/blog/admin.py
+++ b/src/blog/admin.py
@@ -3,12 +3,29 @@ from django.contrib import admin
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.utils.html import format_html
-from django.utils.translation import gettext_lazy as _
+from django.utils.translation import gettext_lazy as _
# Register your models here.
from .models import Article
+class ArticleListFilter(admin.SimpleListFilter):
+ title = _("author")
+ parameter_name = 'author'
+
+ def lookups(self, request, model_admin):
+ authors = list(set(map(lambda x: x.author, Article.objects.all())))
+ for author in authors:
+ yield (author.id, _(author.username))
+
+ def queryset(self, request, queryset):
+ id = self.value()
+ if id:
+ return queryset.filter(author__id__exact=id)
+ else:
+ return queryset
+
+
class ArticleForm(forms.ModelForm):
# body = forms.CharField(widget=AdminPagedownWidget())
@@ -54,7 +71,7 @@ class ArticlelAdmin(admin.ModelAdmin):
'type',
'article_order')
list_display_links = ('id', 'title')
- list_filter = ('status', 'type', 'category')
+ list_filter = (ArticleListFilter, 'status', 'type', 'category', 'tags')
filter_horizontal = ('tags',)
exclude = ('creation_time', 'last_modify_time')
view_on_site = True
diff --git a/src/blog/models.py b/src/blog/models.py
index 083788b..17f2fb8 100644
--- a/src/blog/models.py
+++ b/src/blog/models.py
@@ -1,5 +1,4 @@
import logging
-import re
from abc import abstractmethod
from django.conf import settings
@@ -166,16 +165,6 @@ class Article(BaseModel):
# 前一篇
return Article.objects.filter(id__lt=self.id, status='p').first()
- def get_first_image_url(self):
- """
- Get the first image url from article.body.
- :return:
- """
- match = re.search(r'!\[.*?\]\((.+?)\)', self.body)
- if match:
- return match.group(1)
- return ""
-
class Category(BaseModel):
"""文章分类"""
diff --git a/src/blog/templatetags/blog_tags.py b/src/blog/templatetags/blog_tags.py
index d6cd5d5..110b22b 100644
--- a/src/blog/templatetags/blog_tags.py
+++ b/src/blog/templatetags/blog_tags.py
@@ -18,18 +18,12 @@ from djangoblog.utils import CommonMarkdown, sanitize_html
from djangoblog.utils import cache
from djangoblog.utils import get_current_site
from oauth.models import OAuthUser
-from djangoblog.plugin_manage import hooks
logger = logging.getLogger(__name__)
register = template.Library()
-@register.simple_tag(takes_context=True)
-def head_meta(context):
- return mark_safe(hooks.apply_filters('head_meta', '', context))
-
-
@register.simple_tag
def timeformat(data):
try:
diff --git a/src/blog/tests.py b/src/blog/tests.py
index ee13505..f6bfac0 100644
--- a/src/blog/tests.py
+++ b/src/blog/tests.py
@@ -162,7 +162,7 @@ class ArticleTest(TestCase):
def test_image(self):
import requests
rsp = requests.get(
- 'https://www.python.org/static/img/python-logo.png')
+ 'https://www.python.org/static/img/python-logo@2x.png')
imagepath = os.path.join(settings.BASE_DIR, 'python.png')
with open(imagepath, 'wb') as file:
file.write(rsp.content)
@@ -180,7 +180,7 @@ class ArticleTest(TestCase):
from djangoblog.utils import save_user_avatar, send_email
send_email(['qq@qq.com'], 'testTitle', 'testContent')
save_user_avatar(
- 'https://www.python.org/static/img/python-logo.png')
+ 'https://www.python.org/static/img/python-logo@2x.png')
def test_errorpage(self):
rsp = self.client.get('/eee')
diff --git a/src/blog/views.py b/src/blog/views.py
index d5dc7ec..4af9242 100644
--- a/src/blog/views.py
+++ b/src/blog/views.py
@@ -17,8 +17,6 @@ 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__)
@@ -114,6 +112,12 @@ class ArticleDetailView(DetailView):
pk_url_kwarg = 'article_id'
context_object_name = "article"
+ def get_object(self, queryset=None):
+ obj = super(ArticleDetailView, self).get_object()
+ obj.viewed()
+ self.object = obj
+ return obj
+
def get_context_data(self, **kwargs):
comment_form = CommentForm()
@@ -150,15 +154,7 @@ class ArticleDetailView(DetailView):
kwargs['next_article'] = self.object.next_article
kwargs['prev_article'] = self.object.prev_article
- 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(ARTICLE_CONTENT_HOOK_NAME, article.body, article=article,
- request=self.request)
-
- return context
+ return super(ArticleDetailView, self).get_context_data(**kwargs)
class CategoryDetailView(ArticleListView):
diff --git a/src/comments/admin.py b/src/comments/admin.py
index a814f3f..5622781 100644
--- a/src/comments/admin.py
+++ b/src/comments/admin.py
@@ -26,7 +26,7 @@ class CommentAdmin(admin.ModelAdmin):
'is_enable',
'creation_time')
list_display_links = ('id', 'body', 'is_enable')
- list_filter = ('is_enable',)
+ list_filter = ('is_enable', 'author', 'article',)
exclude = ('creation_time', 'last_modify_time')
actions = [disable_commentstatus, enable_commentstatus]
@@ -38,7 +38,7 @@ class CommentAdmin(admin.ModelAdmin):
(link, obj.author.nickname if obj.author.nickname else obj.author.email))
def link_to_article(self, obj):
- info = (obj.article._meta.app_label, obj.article._meta.model_name)
+ info = (obj.author._meta.app_label, obj.author._meta.model_name)
link = reverse('admin:%s_%s_change' % info, args=(obj.article.id,))
return format_html(
u'%s ' % (link, obj.article.title))
diff --git a/src/djangoblog/__init__.py b/src/djangoblog/__init__.py
index 1e205f4..e69de29 100644
--- a/src/djangoblog/__init__.py
+++ b/src/djangoblog/__init__.py
@@ -1 +0,0 @@
-default_app_config = 'djangoblog.apps.DjangoblogAppConfig'
diff --git a/src/djangoblog/settings.py b/src/djangoblog/settings.py
index 57bf017..3269a34 100644
--- a/src/djangoblog/settings.py
+++ b/src/djangoblog/settings.py
@@ -11,7 +11,6 @@ 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 _
@@ -21,8 +20,9 @@ def env_to_bool(env, default):
return default if str_val is None else str_val == 'True'
-# Build paths inside the project like this: BASE_DIR / 'subdir'.
-BASE_DIR = Path(__file__).resolve().parent.parent
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
@@ -60,8 +60,7 @@ INSTALLED_APPS = [
'oauth',
'servermanager',
'owntracks',
- 'compressor',
- 'djangoblog'
+ 'compressor'
]
MIDDLEWARE = [
@@ -152,7 +151,7 @@ USE_I18N = True
USE_L10N = True
-USE_TZ = False
+USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
@@ -329,13 +328,3 @@ if os.environ.get('DJANGO_ELASTICSEARCH_HOST'):
'ENGINE': 'djangoblog.elasticsearch_backend.ElasticSearchEngine',
},
}
-
-# Plugin System
-PLUGINS_DIR = BASE_DIR / 'plugins'
-ACTIVE_PLUGINS = [
- 'article_copyright',
- 'reading_time',
- 'external_links',
- 'view_count',
- 'seo_optimizer'
-]
\ No newline at end of file
diff --git a/src/djangoblog/spider_notify.py b/src/djangoblog/spider_notify.py
index 7b909e9..f77c09b 100644
--- a/src/djangoblog/spider_notify.py
+++ b/src/djangoblog/spider_notify.py
@@ -2,6 +2,7 @@ import logging
import requests
from django.conf import settings
+from django.contrib.sitemaps import ping_google
logger = logging.getLogger(__name__)
@@ -16,6 +17,15 @@ class SpiderNotify():
except Exception as e:
logger.error(e)
+ @staticmethod
+ def __google_notify():
+ try:
+ ping_google('/sitemap.xml')
+ except Exception as e:
+ logger.error(e)
+
@staticmethod
def notify(url):
+
SpiderNotify.baidu_notify(url)
+ SpiderNotify.__google_notify()
diff --git a/src/djangoblog/whoosh_cn_backend.py b/src/djangoblog/whoosh_cn_backend.py
index 04e3f7f..c285cc2 100644
--- a/src/djangoblog/whoosh_cn_backend.py
+++ b/src/djangoblog/whoosh_cn_backend.py
@@ -12,7 +12,7 @@ import warnings
import six
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
-from datetime import datetime
+from django.utils.datetime_safe import datetime
from django.utils.encoding import force_str
from haystack.backends import BaseEngine, BaseSearchBackend, BaseSearchQuery, EmptyResults, log_query
from haystack.constants import DJANGO_CT, DJANGO_ID, ID
diff --git a/src/docker-compose.es.yml b/src/docker-compose.es.yml
new file mode 100644
index 0000000..83e35ff
--- /dev/null
+++ b/src/docker-compose.es.yml
@@ -0,0 +1,48 @@
+version: '3'
+
+services:
+ es:
+ image: liangliangyy/elasticsearch-analysis-ik:8.6.1
+ container_name: es
+ restart: always
+ environment:
+ - discovery.type=single-node
+ - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
+ ports:
+ - 9200:9200
+ volumes:
+ - ./bin/datas/es/:/usr/share/elasticsearch/data/
+
+ kibana:
+ image: kibana:8.6.1
+ restart: always
+ container_name: kibana
+ ports:
+ - 5601:5601
+ environment:
+ - ELASTICSEARCH_HOSTS=http://es:9200
+
+ djangoblog:
+ build: .
+ restart: always
+ command: bash -c 'sh /code/djangoblog/bin/docker_start.sh'
+ ports:
+ - "8000:8000"
+ volumes:
+ - ./collectedstatic:/code/djangoblog/collectedstatic
+ - ./uploads:/code/djangoblog/uploads
+ environment:
+ - DJANGO_MYSQL_DATABASE=djangoblog
+ - DJANGO_MYSQL_USER=root
+ - DJANGO_MYSQL_PASSWORD=DjAnGoBlOg!2!Q@W#E
+ - DJANGO_MYSQL_HOST=db
+ - DJANGO_MYSQL_PORT=3306
+ - DJANGO_MEMCACHED_LOCATION=memcached:11211
+ - DJANGO_ELASTICSEARCH_HOST=es:9200
+ links:
+ - db
+ - memcached
+ depends_on:
+ - db
+ container_name: djangoblog
+
diff --git a/src/docker-compose.yml b/src/docker-compose.yml
new file mode 100644
index 0000000..2735c32
--- /dev/null
+++ b/src/docker-compose.yml
@@ -0,0 +1,59 @@
+version: '3'
+
+services:
+ db:
+ image: mysql:latest
+ restart: always
+ environment:
+ - MYSQL_DATABASE=djangoblog
+ - MYSQL_ROOT_PASSWORD=DjAnGoBlOg!2!Q@W#E
+ ports:
+ - 3306:3306
+ volumes:
+ - ./bin/datas/mysql/:/var/lib/mysql
+ depends_on:
+ - redis
+ container_name: db
+
+ djangoblog:
+ build: .
+ restart: always
+ command: bash -c 'sh /code/djangoblog/bin/docker_start.sh'
+ ports:
+ - "8000:8000"
+ volumes:
+ - ./collectedstatic:/code/djangoblog/collectedstatic
+ - ./logs:/code/djangoblog/logs
+ - ./uploads:/code/djangoblog/uploads
+ environment:
+ - DJANGO_MYSQL_DATABASE=djangoblog
+ - DJANGO_MYSQL_USER=root
+ - DJANGO_MYSQL_PASSWORD=DjAnGoBlOg!2!Q@W#E
+ - DJANGO_MYSQL_HOST=db
+ - DJANGO_MYSQL_PORT=3306
+ - DJANGO_REDIS_URL=redis:6379
+ links:
+ - db
+ - redis
+ depends_on:
+ - db
+ container_name: djangoblog
+ nginx:
+ restart: always
+ image: nginx:latest
+ ports:
+ - "80:80"
+ - "443:443"
+ volumes:
+ - ./bin/nginx.conf:/etc/nginx/nginx.conf
+ - ./collectedstatic:/code/djangoblog/collectedstatic
+ links:
+ - djangoblog:djangoblog
+ container_name: nginx
+
+ redis:
+ restart: always
+ image: redis:latest
+ container_name: redis
+ ports:
+ - "6379:6379"
diff --git a/src/docs/README-en.md b/src/docs/README-en.md
index 37ea069..4b72655 100644
--- a/src/docs/README-en.md
+++ b/src/docs/README-en.md
@@ -1,158 +1,122 @@
# DjangoBlog
-
-
-
-
-
-
-
-
- A powerful, elegant, and modern blog system.
-
- English • 简体中文
-
+🌍
+*[English](README-en.md) ∙ [简体中文](README.md)*
----
+A blog system based on `python3.8` and `Django4.0`.
-DjangoBlog is a high-performance blog platform built with Python 3.10 and Django 4.0. It not only provides all the core functionalities of a traditional blog but also features a flexible plugin system, allowing you to easily extend and customize your website. Whether you are a personal blogger, a tech enthusiast, or a content creator, DjangoBlog aims to provide a stable, efficient, and easy-to-maintain environment for writing and publishing.
-## ✨ Features
+[](https://github.com/liangliangyy/DjangoBlog/actions/workflows/django.yml) [](https://github.com/liangliangyy/DjangoBlog/actions/workflows/codeql-analysis.yml) [](https://codecov.io/gh/liangliangyy/DjangoBlog) []()
-- **Powerful Content Management**: Full support for managing articles, standalone pages, categories, and tags. Comes with a powerful built-in Markdown editor with syntax highlighting.
-- **Full-Text Search**: Integrated search engine for fast and accurate content searching.
-- **Interactive Comment System**: Supports replies, email notifications, and Markdown formatting in comments.
-- **Flexible Sidebar**: Customizable modules for displaying recent articles, most viewed posts, tag cloud, and more.
-- **Social Login**: Built-in OAuth support, with integrations for Google, GitHub, Facebook, Weibo, QQ, and other major platforms.
-- **High-Performance Caching**: Native support for Redis caching with an automatic refresh mechanism to ensure high-speed website responses.
-- **SEO Friendly**: Basic SEO features are included, with automatic notifications to Google and Baidu upon new content publication.
-- **Extensible Plugin System**: Extend blog functionalities by creating standalone plugins, ensuring decoupled and maintainable code. We have already implemented features like view counting and SEO optimization through plugins!
-- **Integrated Image Hosting**: A simple, built-in image hosting feature for easy uploads and management.
-- **Automated Frontend**: Integrated with `django-compressor` to automatically compress and optimize CSS and JavaScript files.
-- **Robust Operations**: Built-in email notifications for website exceptions and management capabilities through a WeChat Official Account.
-## 🛠️ Tech Stack
+## Main Features:
+- Articles, Pages, Categories, Tags(Add, Delete, Edit), edc. Articles and pages support `Markdown` and highlighting.
+- Articles support full-text search.
+- Complete comment feature, include posting reply comment and email notification. `Markdown` supporting.
+- Sidebar feature: new articles, most readings, tags, etc.
+- OAuth Login supported, including Google, GitHub, Facebook, Weibo, QQ.
+- `Memcache` supported, with cache auto refresh.
+- Simple SEO Features, notify Google and Baidu when there was a new article or other things.
+- Simple picture bed feature integrated.
+- `django-compressor` integrated, auto-compressed `css`, `js`.
+- Website exception email notification. When there is an unhandle exception, system will send an email notification.
+- Wechat official account feature integrated. Now, you can use wechat official account to manage your VPS.
-- **Backend**: Python 3.10, Django 4.0
-- **Database**: MySQL, SQLite (configurable)
-- **Cache**: Redis
-- **Frontend**: HTML5, CSS3, JavaScript
-- **Search**: Whoosh, Elasticsearch (configurable)
-- **Editor**: Markdown (mdeditor)
+## Installation:
+Change MySQL client from `pymysql` to `mysqlclient`, more details please reference [pypi](https://pypi.org/project/mysqlclient/) , checkout preperation before installation.
-## 🚀 Getting Started
+Install via pip: `pip install -Ur requirements.txt`
-### 1. Prerequisites
+If you do NOT have `pip`, please use the following methods to install:
+- OS X / Linux, run the following commands:
-Ensure you have Python 3.10+ and MySQL/MariaDB installed on your system.
+ ```
+ curl http://peak.telecommunity.com/dist/ez_setup.py | python
+ curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python
+ ```
-### 2. Clone & Installation
+- Windows:
-```bash
-# Clone the project to your local machine
-git clone https://github.com/liangliangyy/DjangoBlog.git
-cd DjangoBlog
+ Download http://peak.telecommunity.com/dist/ez_setup.py and https://raw.github.com/pypa/pip/master/contrib/get-pip.py, and run with python.
+
+### Configuration
+Most configurations are in `setting.py`, others are in backend configurations.
+
+I set many `setting` configuration with my environment variables (such as: `SECRET_KEY`, `OAUTH`, `mysql` and some email configuration parts.) and they did NOT been submitted to the `GitHub`. You can change these in the code with your own configuration or just add them into your environment variables.
+
+Files in `test` directory are for `travis` with automatic testing. You do not need to care about this. Or just use it, in this way to integrate `travis` for automatic testing.
+
+In `bin` directory, we have scripts to deploy with `Nginx`+`Gunicorn`+`virtualenv`+`supervisor` on `linux` and `Nginx` configuration file. You can reference with my article
+
+>[DjangoBlog部署教程](https://www.lylinux.net/article/2019/8/5/58.html)
-# Install dependencies
-pip install -r requirements.txt
+More deploy detail in this article.
+
+## Run
+
+Modify `DjangoBlog/setting.py` with database settings, as following:
+
+```python
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'NAME': 'djangoblog',
+ 'USER': 'root',
+ 'PASSWORD': 'password',
+ 'HOST': 'host',
+ 'PORT': 3306,
+ }
+}
```
-### 3. Project Configuration
-
-- **Database**:
- Open `djangoblog/settings.py`, locate the `DATABASES` section, and update it with your MySQL connection details.
-
- ```python
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'djangoblog',
- 'USER': 'root',
- 'PASSWORD': 'your_password',
- 'HOST': '127.0.0.1',
- 'PORT': 3306,
- }
- }
- ```
- Create the database in MySQL:
- ```sql
- CREATE DATABASE `djangoblog` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- ```
-
-- **More Configurations**:
- For advanced settings such as email, OAuth, caching, and more, please refer to our [Detailed Configuration Guide](/docs/config-en.md).
-
-### 4. Database Initialization
+### Create database
+Run the following command in MySQL shell:
+```sql
+CREATE DATABASE `djangoblog` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;
+```
+Run the following commands in Terminal:
```bash
python manage.py makemigrations
python manage.py migrate
+```
-# Create a superuser account
+### Create super user
+
+Run command in terminal:
+```bash
python manage.py createsuperuser
```
-### 5. Running the Project
-
+### Create testing data
+Run command in terminal:
```bash
-# (Optional) Generate some test data
python manage.py create_testdata
+```
-# (Optional) Collect and compress static files
+### Collect static files
+Run command in terminal:
+```bash
python manage.py collectstatic --noinput
python manage.py compress --force
-
-# Start the development server
-python manage.py runserver
```
-Now, open your browser and navigate to `http://127.0.0.1:8000/`. You should see the DjangoBlog homepage!
-
-## Deployment
-
-- **Traditional Deployment**: A detailed guide for server deployment is available here: [Deployment Tutorial](https://www.lylinux.net/article/2019/8/5/58.html) (in Chinese).
-- **Docker Deployment**: This project fully supports Docker. If you are familiar with containerization, please refer to the [Docker Deployment Guide](/docs/docker-en.md) for a quick start.
-- **Kubernetes Deployment**: We also provide a complete [Kubernetes Deployment Guide](/docs/k8s-en.md) to help you go cloud-native easily.
-
-## 🧩 Plugin System
-
-The plugin system is a core feature of DjangoBlog. It allows you to add new functionalities to your blog without modifying the core codebase by writing standalone plugins.
+### Getting start to run server
+Execute: `python manage.py runserver`
-- **How it Works**: Plugins operate by registering callback functions to predefined "hooks". For instance, when an article is rendered, the `after_article_body_get` hook is triggered, and all functions registered to this hook are executed.
-- **Existing Plugins**: Features like `view_count` and `seo_optimizer` are implemented through this plugin system.
-- **Develop Your Own Plugin**: Simply create a new folder under the `plugins` directory and write your `plugin.py`. We welcome you to explore and contribute your creative ideas to the DjangoBlog community!
+Open up a browser and visit: http://127.0.0.1:8000/ , the you will see the blog.
-## 🤝 Contributing
+## More configurations
+[More configurations details](/docs/config-en.md)
-We warmly welcome contributions of any kind! If you have great ideas or have found a bug, please feel free to open an issue or submit a pull request.
+## About the issues
-## 📄 License
-
-This project is open-sourced under the [MIT License](LICENSE).
+If you have any *question*, please use Issue or send problem descriptions to my email `liangliangyy#gmail.com`. I will reponse you as soon as possible. And, we recommend you to use Issue.
---
+## To Everyone 🙋♀️🙋♂️
+If this project helps you, please submit your site address [here](https://github.com/liangliangyy/DjangoBlog/issues/214) to let more people see it.
-## ❤️ Support & Sponsorship
-
-If you find this project helpful and wish to support its continued maintenance and development, please consider buying me a coffee! Your support is my greatest motivation.
-
-
-
-
-
-
- (Left) Alipay / (Right) WeChat
-
-
-## 🙏 Acknowledgements
+Your reply will be the driving force for me to continue to update and maintain this project.
-A special thanks to **JetBrains** for providing a free open-source license for this project.
-
-
-
-
-
-
-
----
-> If this project has helped you, please leave your website URL [here](https://github.com/liangliangyy/DjangoBlog/issues/214) to let more people see it. Your feedback is the driving force for my continued updates and maintenance.
+🙏🙏🙏
diff --git a/src/docs/docker.md b/src/docs/docker.md
index e7c255a..92af9fa 100644
--- a/src/docs/docker.md
+++ b/src/docs/docker.md
@@ -1,114 +1,59 @@
-# 使用 Docker 部署 DjangoBlog
-
+# 使用docker部署



-本项目全面支持使用 Docker 进行容器化部署,为您提供了快速、一致且隔离的运行环境。我们推荐使用 `docker-compose` 来一键启动整个博客服务栈。
-
-## 1. 环境准备
-
-在开始之前,请确保您的系统中已经安装了以下软件:
-- [Docker Engine](https://docs.docker.com/engine/install/)
-- [Docker Compose](https://docs.docker.com/compose/install/) (对于 Docker Desktop 用户,它已内置)
-
-## 2. 推荐方式:使用 `docker-compose` (一键部署)
-
-这是最简单、最推荐的部署方式。它会自动为您创建并管理 Django 应用、MySQL 数据库,以及可选的 Elasticsearch 服务。
-
-### 步骤 1: 启动基础服务
-
-在项目根目录下,执行以下命令:
-
-```bash
-# 构建并以后台模式启动容器 (包含 Django 应用和 MySQL)
-docker-compose up -d --build
+使用docker部署支持如下两种方式:
+## docker镜像方式
+本项目已经支持了docker部署,如果你已经有了`mysql`,那么直接使用基础镜像即可,启动命令如下所示:
+```shell
+docker pull liangliangyy/djangoblog:latest
+docker run -d -p 8000:8000 -e DJANGO_MYSQL_HOST=mysqlhost -e DJANGO_MYSQL_PASSWORD=mysqlrootpassword -e DJANGO_MYSQL_USER=root -e DJANGO_MYSQL_DATABASE=djangoblog --name djangoblog liangliangyy/djangoblog:latest
```
-
-`docker-compose` 会读取 `docker-compose.yml` 文件,自动拉取所需镜像、构建项目镜像,并启动所有服务。
-
-- **访问您的博客**: 服务启动后,在浏览器中访问 `http://127.0.0.1` 即可看到博客首页。
-- **数据持久化**: MySQL 的数据文件将存储在项目根目录下的 `data/mysql` 文件夹中,确保数据在容器重启后不丢失。
-
-### 步骤 2: (可选) 启用 Elasticsearch 全文搜索
-
-如果您希望使用 Elasticsearch 提供更强大的全文搜索功能,可以额外加载 `docker-compose.es.yml` 配置文件:
-
-```bash
-# 构建并以后台模式启动所有服务 (Django, MySQL, Elasticsearch)
-docker-compose -f docker-compose.yml -f deploy/docker-compose/docker-compose.es.yml up -d --build
+启动完成后,访问 http://127.0.0.1:8000
+## 使用docker-compose
+如果你没有mysql等基础服务,那么可以使用`docker-compose`来运行,
+具体命令如下所示:
+```shell
+docker-compose build
+docker-compose up -d
```
-- **数据持久化**: Elasticsearch 的数据将存储在 `data/elasticsearch` 文件夹中。
-
-### 步骤 3: 首次运行的初始化操作
-
-当容器首次启动后,您需要进入容器来执行一些初始化命令。
-
-```bash
-# 进入 djangoblog 应用容器
-docker-compose exec web bash
-
-# 在容器内执行以下命令:
-# 创建超级管理员账户 (请按照提示设置用户名、邮箱和密码)
-python manage.py createsuperuser
-
-# (可选) 创建一些测试数据
-python manage.py create_testdata
-
-# (可选,如果启用了 ES) 创建索引
-python manage.py rebuild_index
-
-# 退出容器
-exit
+本方式生成的mysql数据文件在 `bin/datas/mysql` 文件夹。
+等启动完成后,访问 [http://127.0.0.1](http://127.0.0.1) 即可。
+### 使用es
+如果你期望使用es来作为后端的搜索引擎,那么可以使用如下命令来启动:
+```shell
+docker-compose -f docker-compose.yml -f docker-compose.es.yml build
+docker-compose -f docker-compose.yml -f docker-compose.es.yml up -d
```
-
-## 3. 备选方式:使用独立的 Docker 镜像
-
-如果您已经拥有一个正在运行的外部 MySQL 数据库,您也可以只运行 DjangoBlog 的应用镜像。
-
-```bash
-# 从 Docker Hub 拉取最新镜像
-docker pull liangliangyy/djangoblog:latest
-
-# 运行容器,并链接到您的外部数据库
-docker run -d \
- -p 8000:8000 \
- -e DJANGO_SECRET_KEY='your-strong-secret-key' \
- -e DJANGO_MYSQL_HOST='your-mysql-host' \
- -e DJANGO_MYSQL_USER='your-mysql-user' \
- -e DJANGO_MYSQL_PASSWORD='your-mysql-password' \
- -e DJANGO_MYSQL_DATABASE='djangoblog' \
- --name djangoblog \
- liangliangyy/djangoblog:latest
+本方式生成的es数据文件在 `bin/datas/es` 文件夹。
+## 配置说明:
+
+本项目较多配置都基于环境变量,所有的环境变量如下所示:
+
+| 环境变量名称 | 默认值 | 备注 |
+|---------------------------|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|
+| DJANGO_DEBUG | False | |
+| DJANGO_SECRET_KEY | DJANGO_BLOG_CHANGE_ME | 请务必修改,建议[随机生成](https://www.random.org/passwords/?num=5&len=24&format=html&rnd=new) |
+| DJANGO_MYSQL_DATABASE | djangoblog | |
+| DJANGO_MYSQL_USER | root | |
+| DJANGO_MYSQL_PASSWORD | djangoblog_123 | |
+| DJANGO_MYSQL_HOST | 127.0.0.1 | |
+| DJANGO_MYSQL_PORT | 3306 | |
+| DJANGO_MEMCACHED_ENABLE | True | |
+| DJANGO_MEMCACHED_LOCATION | 127.0.0.1:11211 | |
+| DJANGO_BAIDU_NOTIFY_URL | http://data.zz.baidu.com/urls?site=https://www.example.org&token=CHANGE_ME | 请在[百度站长平台](https://ziyuan.baidu.com/linksubmit/index)获取接口地址 |
+| DJANGO_EMAIL_TLS | False | |
+| DJANGO_EMAIL_SSL | True | |
+| DJANGO_EMAIL_HOST | smtp.example.org | |
+| DJANGO_EMAIL_PORT | 465 | |
+| DJANGO_EMAIL_USER | SMTP_USER_CHANGE_ME | |
+| DJANGO_EMAIL_PASSWORD | SMTP_PASSWORD_CHANGE_ME | |
+| DJANGO_ADMIN_EMAIL | admin@example.org | |
+| DJANGO_WEROBOT_TOKEN | DJANGO_BLOG_CHANGE_ME
+|DJANGO_ELASTICSEARCH_HOST|
+
+第一次启动之后,使用如下命令来创建超级用户:
+```shell
+docker exec -it djangoblog python /code/djangoblog/manage.py createsuperuser
```
-
-- **访问您的博客**: 启动完成后,访问 `http://127.0.0.1:8000`。
-- **创建管理员**: `docker exec -it djangoblog python manage.py createsuperuser`
-
-## 4. 配置说明 (环境变量)
-
-本项目的大部分配置都通过环境变量来管理。您可以在 `docker-compose.yml` 文件中修改它们,或者在使用 `docker run` 命令时通过 `-e` 参数传入。
-
-| 环境变量名称 | 默认值/示例 | 备注 |
-|-------------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------|
-| `DJANGO_SECRET_KEY` | `your-strong-secret-key` | **请务必修改为一个随机且复杂的字符串!** |
-| `DJANGO_DEBUG` | `False` | 是否开启 Django 的调试模式 |
-| `DJANGO_MYSQL_HOST` | `mysql` | 数据库主机名 |
-| `DJANGO_MYSQL_PORT` | `3306` | 数据库端口 |
-| `DJANGO_MYSQL_DATABASE` | `djangoblog` | 数据库名称 |
-| `DJANGO_MYSQL_USER` | `root` | 数据库用户名 |
-| `DJANGO_MYSQL_PASSWORD` | `djangoblog_123` | 数据库密码 |
-| `DJANGO_REDIS_URL` | `redis:6379/0` | Redis 连接地址 (用于缓存) |
-| `DJANGO_ELASTICSEARCH_HOST` | `elasticsearch:9200` | Elasticsearch 主机地址 |
-| `DJANGO_EMAIL_HOST` | `smtp.example.org` | 邮件服务器地址 |
-| `DJANGO_EMAIL_PORT` | `465` | 邮件服务器端口 |
-| `DJANGO_EMAIL_USER` | `user@example.org` | 邮件账户 |
-| `DJANGO_EMAIL_PASSWORD` | `your-email-password` | 邮件密码 |
-| `DJANGO_EMAIL_USE_SSL` | `True` | 是否使用 SSL |
-| `DJANGO_EMAIL_USE_TLS` | `False` | 是否使用 TLS |
-| `DJANGO_ADMIN_EMAIL` | `admin@example.org` | 接收异常报告的管理员邮箱 |
-| `DJANGO_BAIDU_NOTIFY_URL` | `http://data.zz.baidu.com/...` | [百度站长平台](https://ziyuan.baidu.com/linksubmit/index) 的推送接口 |
-
----
-
-部署完成后,请务必检查并根据您的实际需求调整这些环境变量,特别是 `DJANGO_SECRET_KEY` 和数据库、邮件相关的配置。
diff --git a/src/owntracks/views.py b/src/owntracks/views.py
index 4c72bdd..6c87a2b 100644
--- a/src/owntracks/views.py
+++ b/src/owntracks/views.py
@@ -3,15 +3,16 @@ import datetime
import itertools
import json
import logging
-from datetime import timezone
from itertools import groupby
-import django
+import django.utils.timezone
import requests
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.http import JsonResponse
from django.shortcuts import render
+from django.utils import timezone
+from django.utils.timezone import utc
from django.views.decorators.csrf import csrf_exempt
from .models import OwnTrackLog
@@ -47,7 +48,7 @@ def manage_owntrack_log(request):
@login_required
def show_maps(request):
if request.user.is_superuser:
- defaultdate = str(datetime.datetime.now(timezone.utc).date())
+ defaultdate = str(timezone.now().date())
date = request.GET.get('date', defaultdate)
context = {
'date': date
@@ -96,13 +97,14 @@ def convert_to_amap(locations):
@login_required
def get_datas(request):
- now = django.utils.timezone.now().replace(tzinfo=timezone.utc)
+ now = django.utils.timezone.now().replace(tzinfo=utc)
querydate = django.utils.timezone.datetime(
now.year, now.month, now.day, 0, 0, 0)
if request.GET.get('date', None):
date = list(map(lambda x: int(x), request.GET.get('date').split('-')))
querydate = django.utils.timezone.datetime(
date[0], date[1], date[2], 0, 0, 0)
+ querydate = django.utils.timezone.make_aware(querydate)
nextdate = querydate + datetime.timedelta(days=1)
models = OwnTrackLog.objects.filter(
creation_time__range=(querydate, nextdate))
diff --git a/src/requirements.txt b/src/requirements.txt
index 9dc5c935191f166db408850beb747475a262f65f..70457c301814df4bc4c584fc4f99473feb2ef84e 100644
GIT binary patch
literal 474
zcmY+BF;l}Z425_9m*{LKrDgEKv2w?;baow)xOJk`O4YwIi;k0zlS!vb^ljk`GMxP7Q7K~v1SF4s&d1<7*!wZhH4A<~1
zeaDCgUlufl=EyWoF`Sa1)Z%W{o6o0~u4Ab;YFPQ4LW*|>382+`Oo^_}87-%ga_t6r
zt-$MBCMc>m$SHk)3NsCx724O
z&svob%XMU|V{iQC@?R
zZ~0G!W+z_|B@^!EYb0|a8|zFJJ(1fNe%^|{En8uk>3b5kw*sb!x=F1+XweA^2Zpom&^VXcC#kB7{YUtyk1AW8lRCsH7kc&9|2FJZDW6fPxwcK<4UuCUBdsXLVs`_5F
zp~0oR=sQS>?<%PjW*zBU@cbYY3-!J}L^}_3Y27N;PkG)pk*uJsc&?t#R3o*J(X1SA
zka;NaQGO#GYHJxbBbSkJp-k9@@&PlNs$w3EcPR@sF|TltTB6Tpl&WX?P!AFM`gAq#
ziDP5!b%x?N`7!_PG~o%JQRKX9Y6p=$>EBXOM*7a}6;HOi-71ev8|^_li^@^eSj@w__0A3aLAaD3lW$cY-+ejf+0D0n;c*g?m`=Y9
z#D{NVKaQOf&bHqN|K6p!G41^vmi8TR=TIe^a2}m??@)Ypmc4|+%#Zt&bBpa!Y_Lna
z95ZK`d!>na86B&$`)xt#Oe-&k^ISIS%h_8C0ec(O{{Ln{w6Q!`KVv#@hd&K=)9UJoM~W6el-zM7!{x**T=1X
z^wa1z+L2b5chAc%ZKb?k2fY03=7b3E0}!J+D^
z`Om~yc~RJ~yuIGH-QLq%`|ZTuPLXcJX{%xE{f6^yk|#Rdx2k=`
SS`X?#O)JeKo3nk{t@?jbHFwMa
diff --git a/src/templates/blog/article_detail.html b/src/templates/blog/article_detail.html
index a74a0db..f694db3 100644
--- a/src/templates/blog/article_detail.html
+++ b/src/templates/blog/article_detail.html
@@ -2,6 +2,30 @@
{% load blog_tags %}
{% block header %}
+ {{ article.title }} | {{ SITE_DESCRIPTION }}
+
+
+
+
+
+
+
+
+
+
+ {% for t in article.tags.all %}
+
+ {% endfor %}
+
+
+
+ {% if article.tags %}
+
+ {% else %}
+
+ {% endif %}
+
{% endblock %}
{% block content %}
diff --git a/src/templates/share_layout/base.html b/src/templates/share_layout/base.html
index 75d0df5..d3e0e42 100644
--- a/src/templates/share_layout/base.html
+++ b/src/templates/share_layout/base.html
@@ -18,12 +18,7 @@
{% block header %}
-
{% block title %}{{ SITE_NAME }}{% endblock %}
-
-
{% endblock %}
- {% load blog_tags %}
- {% head_meta %}