Django项目下有三个应用:blog、work、yuge,然后有两个域名,codenotes.cn 和 yugemetal.com,希望blog对应codenotes.cn,work对应codenotes.cn/work/,yuge对应yugemetal.com。
参考各种资料及踩坑后,完成相应配置,记录下。
1. 安装 django-hosts
pip install django-hosts
2. 添加应用及配置参数
# 非完整代码,仅参考
# codenotes/settings.py
# 增加应用
INSTALLED_APPS = [
# ... 内置应用等
'django_hosts', # 新增
'blog',
'work',
'yuge',
]
# 增加 django_hosts 中间件
# 'django_hosts.middleware.HostsRequestMiddleware' 必须在所有中间件最前面
# 'django_hosts.middleware.HostsResponseMiddleware' 必须在所有中间件最后面
MIDDLEWARE = [
'django_hosts.middleware.HostsRequestMiddleware', # <--- 放在最前面
# ... 其他常规中间件 (Security, Session, Common, Csrf, Auth, Message, Clickjacking等)
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django_hosts.middleware.HostsResponseMiddleware', # <--- 放在最后面
]
# 配置 django-hosts
ROOT_HOSTCONF = 'codenotes.hosts' # 指向创建的 hosts.py 文件
DEFAULT_HOST = 'blog' # 默认主机名
3. 创建 hosts 文件
# codenotes/hosts.py
from django_hosts import patterns, host
# 域名与应用路由的映射
host_patterns = patterns(
'',
# codenotes.cn 绑定 blog 应用的 urls
host(r'^codenotes\.cn$', 'codenotes.urls', name='blog'),
# yugemetal.com 绑定 yuge 应用的 urls,注意,此处需新增一个 urls_yuge.py 文件
host('^yugemetal\.com$', 'yuge.urls_yuge', name='yuge'),
)
4. codenotes/urls.py
# 非完整代码,仅参考
# codenotes/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('work/', include(('work.urls', 'work'), namespace='work')),
path('', include(('blog.urls', 'blog'), namespace='blog')),
]
5. blog/urls.py
# 非完整代码,仅参考
# blog/urls.py
# 必须添加app_name
app_name = 'blog'
urlpatterns = [
path('about/', views.about, name='about'),
path('timeline/', views.timeline, name='timeline'),
path('article/<int:article_id>', views.article, name='article'),
path('', views.index, name='index'),
]
6. work/urls.py
# 非完整代码,仅参考
# work/urls.py
app_name = 'work'
urlpatterns = [
path('condition/core/', views.monitor_core, name='monitor_core'),
]
7. yuge/urls.py
# 非完整代码,仅参考
# yuge/urls.py
app_name = 'yuge'
urlpatterns = [
path('', views.index, name='index'),
]
8. 新增 yuge/urls_yuge.py
# yuge/urls_yuge/py
from django.urls import path, include
urlpatterns = [
# yugemetal.com/ 根路径对应yuge应用
path('', include(('yuge.urls', 'yuge'), namespace='yuge')),
]
9. templates 中使用
<!-- templates/app/xxx.html -->
<!-- 页面模板中使用时,必须先加载 hosts -->
{% load hosts %}
<ul class="nav-menu" id="navMenu">
<!-- 用 host_url 替换默认的 url,参数照常放,在最后面增加 host 对应名称 -->
<li><a href="{% host_url 'yuge:index' host 'yuge' %}#home" class="nav-link active">首页</a></li>
<li><a href="{% host_url 'blog:tag' tag.id host 'blog' %}" class="tag"></li>
</ul>
10. nginx 正常配置
# 动态请求 (Django/uWSGI)
location / {
# 使用 uWSGI 协议
uwsgi_pass django_codenotes;
include uwsgi_params;
# uWSGI 专用参数设置 (比 proxy_set_header 更准确)
uwsgi_param Host $host; # !!留意此条,根据域名区分!!
uwsgi_param X-Real-IP $remote_addr;
uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
uwsgi_param X-Forwarded-Proto $scheme;
}
OVER…
其中折腾最久的是页面提示 NoReverseMatch, 一开始是 hosts 中的 blog 的 url 未对应正确,对应到应用 blog 下的 urls.py 去了,实际需要对应项目的 urls.py,即 codenotes/urls.py;然后 yuge 用现有的 urls.py 无法正常显示页面,一直提示 NoReverseMatch,新建了 yuge/yuge_ursl.py 并配置相关内容后,页面及相关链接全部显示正常。
至此,目标达成,记录下。
https://codenotes.cn 正常显示博客,
https://codenotes.cn/work/ 正常显示 work 相关内容
https://yugemetal.com 正常显示宇格金属
Django默认登录只有用户名密码,存在一定安全隐患,想着提高下,用 django-simple-captcha 实现。
1. 安装 django-simple-captcha
# 如无 pillow,需安装才可正常使用
# pip install pillow
pip install django-simple-captcha
2. 添加应用及配置
# settings
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 添加应用
'captcha',
]
# 验证码图片宽度/高度
CAPTCHA_IMAGE_SIZE = (100, 40)
# 验证码字符长度(数学公式时不生效)
CAPTCHA_LENGTH = 4
# 验证码字符类型:字母数字混合(可选值:'numeric'纯数字 / 'alphabetic'纯字母 / 'alphanumeric'混合)
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge'
# 数学公式验证码(替代上述字符验证码)
# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
# 验证码过期时间(秒)
CAPTCHA_TIMEOUT = 5 * 60 # 5分钟
# 干扰线数量(0=无干扰线,数值越大干扰越强)
CAPTCHA_NOISE_FUNCTIONS = (
'captcha.helpers.noise_arcs', # 弧形干扰线
'captcha.helpers.noise_dots', # 点状干扰
)
# 验证码背景色(RGB)
CAPTCHA_BACKGROUND_COLOR = '#ffffff'
# 验证码文字颜色(RGB)
CAPTCHA_FOREGROUND_COLOR = '#001100'
3. 执行 python manage.py migrate
4. 新增验证码表单
# 新建 project/forms.py
from django import forms
from django.contrib.admin.forms import AdminAuthenticationForm
from captcha.fields import CaptchaField
class AdminCaptchaAuthenticationForm(AdminAuthenticationForm):
# 新增验证码字段,label 可自定义显示文本
captcha = CaptchaField(label='验证码')
# 保留原有的 admin 登录验证逻辑,仅新增验证码校验
def clean(self):
# 先执行父类的 clean 方法(验证用户名密码)
cleaned_data = super().clean()
# 验证码的校验由 CaptchaField 自动完成,无需额外处理
return cleaned_data
5. 新增视图
# 新建 project/views.py
from django.contrib.admin.sites import AdminSite
from django.contrib.auth.views import LoginView
from .captcha_forms import AdminCaptchaAuthenticationForm
class AdminCaptchaLoginView(LoginView):
# 指定自定义表单
form_class = AdminCaptchaAuthenticationForm
# 复用 admin 登录模板
template_name = 'admin/login.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
admin_site = AdminSite()
context.update({
'site_title': admin_site.site_title,
'site_header': admin_site.site_header,
'site_url': admin_site.site_url,
'title': '管理员登录',
})
return context
6. 新增 login.html
# 新建 project/codenotes/templates/admin.py
<!-- templates/admin/login.html -->
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block extrastyle %}{{ block.super }}
<link rel="stylesheet" href="{% static "admin/css/login.css" %}">
{{ form.media }} <!-- 新增:加载验证码所需的静态资源 -->
<style>
/* 控制验证码图片垂直对齐,与输入框居中 */
.captcha {
vertical-align: middle;
margin-bottom: 3px;
border: none;
}
/* 调整验证码输入框的高度,与图片更匹配 */
input[name="captcha_1"] {
height: 25px;
}
</style>
{% endblock %}
{% block bodyclass %}{{ block.super }} login{% endblock %}
{% block nav-breadcrumbs %}{% endblock %}
{% block content_title %}{% endblock %}
{% block content %}
{% if form.errors and not form.non_field_errors %}
<p class="errornote">
{% blocktranslate count counter=form.errors.items|length %}Please correct the error below.{% plural %}Please
correct the errors below.{% endblocktranslate %}
</p>
{% endif %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p class="errornote">
{{ error }}
</p>
{% endfor %}
{% endif %}
<div id="content-main">
{% if user.is_authenticated %}
<p class="errornote">
{% blocktranslate trimmed %}
You are authenticated as {{ username }}, but are not authorized to access this page.
Would you like to login to a different account?
{% endblocktranslate %}
</p>
{% endif %}
<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
<div class="form-row">
{{ form.username.errors }}
{{ form.username.label_tag }} {{ form.username }}
</div>
<div class="form-row">
{{ form.password.errors }}
{{ form.password.label_tag }} {{ form.password }}
<input type="hidden" name="next" value="{{ next }}">
</div>
<!-- 新增:验证码字段渲染 -->
<div class="form-row">
{{ form.captcha.errors }} <!-- 验证码错误提示 -->
{{ form.captcha.label_tag }} {{ form.captcha }} <!-- 验证码标签 + 输入框 + 图片 -->
</div>
{% url 'admin_password_reset' as password_reset_url %}
{% if password_reset_url %}
<div class="password-reset-link">
<a href="{{ password_reset_url }}">{% translate 'Forgotten your password or username?' %}</a>
</div>
{% endif %}
<div class="submit-row">
<input type="submit" value="{% translate 'Log in' %}">
</div>
</form>
</div>
{% endblock %}
7. 添加路由
# urls
urlpatterns = [
# 增加路由
path('captcha/', include('captcha.urls')),
]
完成测试看是否成功。
习惯使用Django-CKeditor实现博客后台的富文本输入,但发现少个代码高亮功能,几经查找,发现其有内置的代码块功能:codesnippet,用此插件就可以实现代码高亮功能,且自带不少常见主题,原理为通过highlight.js实现。
1. 参考配置参数,调出代码按钮
CKEDITOR_CONFIGS = {
'default': {
"skin": "moono-lisa",
"toolbar_Basic": [["Source", "-", "Bold", "Italic"]],
"toolbar_Full": [
["Styles", "Format", "Bold", "Italic", "Underline", "Strike"],
["Blockquote", "Link", "Unlink"],
["Image", "Table", "HorizontalRule"],
["NumberedList", "BulletedList", "JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock"],
["TextColor", "BGColor", ],
["CodeSnippet", "Source"],
],
"toolbar": "Full",
"height": 500,
"width": 860,
"filebrowserWindowWidth": 940,
"filebrowserWindowHeight": 725,
'extraPlugins': 'codesnippet',
'tabSpaces': 4,
'allowedContent': True,
# 配置后台语法高亮主题
'codeSnippet_theme': 'monokai',
# 配置后台显示支持语言,格式:{语言标识: 显示名称}
'codeSnippet_languages': {
'bash': 'Bash',
'css': 'CSS',
'html': 'HTML',
'ini': 'INI',
'javascript': 'JavaScript',
'json': 'JSON',
'nginx': 'Nginx',
'python': 'Python',
'sql': 'SQL',
},
}
}
2. 前台使用
<!-- django-ckeditor 自带的highlight版本比较低,推荐用highlightjs官网最新的js -->
<!-- 喜欢的高亮主题 -->
<link href="{% static 'blog/css/atom-one-dark.min.css' %}" rel="stylesheet">
<!-- highlight.js文件 -->
<script src="{% static 'blog/js/highlight.min.js' %}"></script>
<!-- 调用highlight -->
<script>hljs.highlightAll();</script>
3. 补充
部分超长代码不会自动换行问题,可以在.css文件中添加white-space: pre-wrap; 可实现正常显示自动换行。
.hljs {
border-radius: 0.5rem; # 代码框圆角
white-space: pre-wrap; # 代码超长自动换行
}
1. 更新
# Debian系统中,已有shadowsocks应用,直接更新安装即可
sudo apt update
# 安装
sudo apt install shadowsocks-libev
2. 修改完善相关配置
# 配置文件路径
vim /etc/shadowsocks-libev/config.json
# 修改相关配置
{
# 任意IP访问
"server":["0.0.0.0"],
"mode":"tcp_and_udp",
# 服务器端口,默认为8288
"server_port":8288,
# 本地端口,默认为1080
"local_port":1080,
# 密码,根据个人喜好修改
"password":"loveqiqi",
# 连接超时(单位:秒)
"timeout":36000,
# 加密方式
"method":"chacha20-ietf-poly1305"
}
3. 客户端下载
https://github.com/shadowsocks
1. 更新下载MySQL资源仓库
https://dev.mysql.com/get/mysql-apt-config_0.8.36-1_all.deb
2. 安装更新
sudo dpkg -i mysql-apt-config_0.8.36-1_all.deb
3. 更新升级
sudo apt update
sudo apt upgrade
4. 安装MySQL
sudu apt install mysql-server
# 期间会提示输入密码, 并确认密码
5. 修改完善MySQL相关配置
# 配置文件
vim /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
# 允许远程访问
bind-address = 0.0.0.0
# 修改端口号
port = 13306
# 内存优化,按需
performance_schema = off
# 进入MySQL后,执行相关语句允许远程访问(MySQL 5.7.40版本后)
> CREATE USER 'root'@'%' IDENTIFIED BY '密码';
> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
> FLUSH PRIVILEGES;
# 进入MySQL后,执行相关语句允许远程访问(5.7.38版本之前)
> GRANT ALL PRIVILEGES ON . TO 'root'@'%' IDENTIFIED BY '密码' WITH GRANT OPTION;
> FLUSH PRIVILEGES;
# 查看端口
netstat -tulnp | grep mysql