项目设计与配置
实现功能
- 信息反馈页面:信息提交功能以表单形式实现,信息展示以数据列表形式呈现;每条信息包含序号、用户名、信息内容和提交日期
- 单元测试:测试信息反馈页面的功能,比如测试模型的读写操作、视图函数的业务逻辑
项目架构设计
django-admin startproject messageBoard
python manage.py startapp index
- 针对全局template的路由配置:在项目根目录下创建模板文件夹templates,并分别创建模板文件404.html、500.html和base.html(共用模板文件);在setting设置TEMPLATES
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
from django.shortcuts import render
def hello(request):
return render(request, "index.html")
- 针对本应用内template的路由配置:在index应用文件夹中新建templates,其中再新建文件夹index,放置index.html(用于生成信息反馈页面,它继承共用模板文件base.html);在setting设置INSTALLED_APPS
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
]
from django.shortcuts import render
def hello(request):
return render(request, "index/index.html")
-
在index应用文件夹中新建static(该文件夹的静态资源只能在Django的调试模式下使用),其中放置静态资源 -
在项目目录下新建static(该文件夹存放静态资源),需要对static进行配置(如进阶所述) -
在index应用文件夹中创建urls.py文件 -
在index应用文件夹中创建form.py文件(用于定义表单类MessageModelForm,在模板文件index.html中使用表单类实现信息提交功能)
中间件
中间件介绍
中间件配置
'django.middleware.locale.LocaleMiddleware',
数据库配置
创建数据库
连接数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'messagedb',
'USER' : 'root',
'PASSWORD' : 'root',
'HOST' : '127.0.0.1',
'PORT' : '3306',
}
}
数据库架构设计
from django.db import models
class Message(models.Model):
id = models.AutoField('序号', primary_key = True)
name = models.CharField('名称', max_length = 50)
content = models.CharField('信息内容', max_length = 200)
timestamp = models.DateField('反馈时间', auto_now = True)
def __str__(self):
return self.name
class Meta:
verbose_name = '信息反馈表'
verbose_name_plural = '信息反馈表'
- 该Django项目在python虚拟环境下(虚拟环境下安装的内容在其他环境不起作用),需要安装驱动程序,而Django默认驱动是MySQLdb
import pymysql
pymysql.install_as_MySQLdb()
python manage.py makemigrations
python manage.py migrate
程序功能开发
共用模板base.html
信息反馈页面(首页)功能
from django.contrib import admin
from django.urls import path, include, re_path
from django.conf.urls import static
from django.conf import settings
urlpatterns = [
path('', include('index.urls')),
]
from os import name
from django.urls import path
from . import views
app_name = index
urlpatterns = [
path('index/', views.index, name='index'),
]
from django import forms
from .models import *
class MessageModelForm(forms.ModelForm):
class Meta:
model = Message
fields = '__all__'
from django.shortcuts import render, redirect
from .models import Message
from .form import MessageModelForm
def index(request):
messages = Message.objects.all().order_by('-id')
if request.method == 'POST':
form = MessageModelForm(request.POST)
if form.is_valid():
form.save()
return redirect('/thanks/')
return render(request, 'index/index.html', locals())
提示页面thanks.html
from os import name
from django.urls import path
from . import views
app_name='index'
urlpatterns = [
path('index/', views.index, name='index'),
path('thanks/', views.thanks)
]
def thanks(request):
return render(request, 'index/thanks.html')
自定义404、500异常页面功能
from index import views
handler404 = views.page_not_found
handler500 = views.page_error
from django.shortcuts import render
def page_not_found(request, exception):
return render(request, '404.html', status = 404)
def page_error(request):
return render(request, '500.html', status = 500)
DEBUG = False
ALLOWED_HOSTS = ['*']
Admin后台系统
设置Admin后台系统路由
urlpatterns = [
path('admin/', admin.site.urls),
]
创建用户
python manage.py createsuperuser
设置
App名在后台中文显示
from django.apps import AppConfig
class IndexConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'index'
verbose_name = '信息管理'
表名、字段名后台中文显示
from django.db import models
class Message(models.Model):
id = models.AutoField(primary_key = True, verbose_name='序号')
name = models.CharField(max_length = 50, verbose_name='名称')
content = models.CharField(max_length = 200, verbose_name='信息内容')
timestamp = models.DateField(auto_now = True, verbose_name='反馈时间')
def __str__(self):
return self.name
class Meta:
verbose_name = '信息反馈表'
verbose_name_plural = verbose_name
定义模型Message的ModelAdmin
from index.models import Message
from django.contrib import admin
admin.site.site_title = '信息反馈后台系统'
admin.site.site_header = '信息反馈平台'
@admin.register(Message)
class MessageAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'content', 'timestamp']
list_per_page = 10
ordering = ['id']
list_editable = ['name', 'content']
list_filter = ['id', 'name', 'content', 'timestamp']
search_fields = ['name']
date_hierarchy = 'timestamp'
测试与运行
测试内容
-
信息反馈页面实现信息提交于信息显示功能。信息提交功能通过POST向MessageModelForm提交参数,表单类MessageModelForm生成表单对象,再将对象通过模型models存储在数据库;信息显示则通过模型models与模板语法进行显示。这两个功能都是开发者实现的,有必要对这些功能进行单元测试 -
Admin后台系统是Django内置功能,大多数不会存在问题,除非重写了ModelAdmin的类才需要进行单元测试 -
自定义的异常显示页面视图函数只是返回了404.html与500.html的模板,没有业务逻辑,无需进行单元测试
单元测试内容
说明
-
setUp()是在运行测试类的时候,为测试类提供提供数据支持。单元测试在运行过程中会创建一个虚拟的数据库,所有模型的数据操作都在虚拟数据库完成;通过重写setUp()向虚拟数据库添加数据,为测试用例提供数据支持 -
test_Message()用于测试Message的读取操作是否正常、timestamp的auto_now属性是否正常 -
test_post()用于测试POST功能是否正常、MessageModelForm功能是否正常
编写单元测试内容
from index.models import Message
from django.test import TestCase, Client
class MessageTest(TestCase):
def setUp(self):
Message.objects.create(name='Lucy', content='Django 入门')
Message.objects.create(name='May', content='入门到精通')
def test_Message(self):
info = Message.objects.get(name='Lucy')
self.assertIsNotNone(info.timestamp)
def test_post(self):
c = Client()
data = {
'name' : 'Tim',
'content' : '删库跑路'
}
response = c.post('/index/', data=data)
status_code = response.status_code
info = Message.objects.get(name='Tim')
self.assertEqual(status_code, 302)
self.assertEqual(info.content, '删库跑路')
测试
python manage.py test
运行与上线
运行机制
Django自带的wsgi server
runserver性能较差,静态资源、动态资源请求都由Django自带的server处理
uWSGI server
并发量高、方便管理多进程、性能好
Nginx server
性能较好,静态资源请求交由Nginx server处理,动态资源交由uWSGI server处理,实现动、静态资源处理分离
Linux基本配置
-
环境;Ubuntu_Server 20.04 -
下载xshell,密码:zmat,点击绿化安装
配置mysql
-
sudo apt update -
sudo apt install mysql-server -
sudo mysql_secure_installation:运行安全脚本以更改一些安全选项
-
更改验证插件并设置本地连接新密码
- sudo mysql
- 可见root用户为auth_socket:SELECT user,authentication_string,plugin,host FROM mysql.user;
- ALTER USER ‘root’@‘localhost’ IDENTIFIED WITH caching_sha2_password BY ‘你的密码’;
- FLUSH PRIVILEGES
- 检查:SELECT user,authentication_string,plugin,host FROM mysql.user;
- exit
-
设置开机启动:systemctl enable mysql -
vi /etc/mysql/mysql.conf.d/mysqld.cnf:注释掉bind-address=127.0.0.1 -
远程用户登录
- sudo mysql -u root -p
- 创建远程登录的root用户:create user ‘root’@’%’ identified by ‘密码’;
- 赋予权限:GRANT ALL PRIVILEGES ON . TO ‘root’@’%’ WITH GRANT OPTION;
- flush privileges;
- exit
-
重启mysql:systemctl restart mysql -
检查状态:systemctl status mysql -
查看各监听监听端口(是否3306为监听窗口):ss -ltn -
使用Navicat连接
配置python
- 安装python依赖包:apt-get install zlib1g zlib1g-dev libbz2-1.0 libbz2-dev openssl libssl-dev libncurses5-dev sqlite sqlite3 libreadline-gplv2-dev python3-tk gcc make
- 安装python(见Linux基础)
配置Nginx
-
安装依赖包
- sudo apt-get install build-essential
- sudo apt-get install libtool
- sudo apt-get update
- sudo apt-get install libpcre3 libpcre3-dev
- sudo apt-get install zlib1g-dev
- sudo apt-get install openssl
-
安装nginx
- nginx下载官网(找最新下载)
- 在/opt将压缩包放置目录下
- 解压:tar -zxvf nginx-1.19.9.tar.gz
- 进入解压目录:cd nginx-1.19.9
- 配置:./configure --prefix=/usr/local/nginx
- 编译:make
- 安装:make install
- 启动:/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf;-c 指定配置文件的路径,不加的话,nginx会自动加载默认路径的配置文件,可以通过-h查看帮助命令
- 查看进程:ps -ef |grep nginx
- 配置软连接(不用路径直接输入nginx启动):sudo ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
- vim /etc/init.d/nginx
- 设置服务脚本有执行权限:chmod +x /etc/init.d/nginx
- 注册服务cd /etc/init.d/:update-rc.d nginx defaults
- service nginx restart(若出现问题,kill掉80端口进程,再重启)
配置uWSGI
pip3 install uwsgi
上传代码
上传
-
在/opt目录下创建Django_Projects目录:mkdir Django_Projects -
cd Django_Projects -
在Django_Projects创建script目录,与项目相关的脚本放置处:mkdir script -
使用Xftp上传项目至Django_Projects目录下(chmod 777 Django_Projects) -
安装所需模块:appdirs、Django、packaging、pyparsing、pytz、six、uWSGI、pymysql
修改
DEBUG = False
ALLOWED_HOSTS = ['*']
STATIC_ROOT = os.path.join(BASE_DIR, "static")
python manage.py collectstatic
from django.contrib import admin
from django.urls import path, include, re_path
from django.views import static
from django.views.static import serve
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('index.urls')),
re_path('static/(?P<path>.*)', static.serve, {'document_root':settings.STATIC_ROOT}, name='static')
]
from index import views
handler404 = views.page_not_found
handler500 = views.page_error
使用runserver启动Django程序
python manage.py runserver 192.168.149.129:8000
使用uWSGI启动Django程序
uwsgi --http 192.168.149.129:80 --file messageBoard/wsgi.py --static-map=/static=static
使用Nginx+uWSGI启动Django程序
- 在script创建配置文件:vim uwsgi.ini
[uwsgi]
# 项目目录
chdir=/opt/Django_Projects/messageBoard/
# 启动uwsgi的用户名和用户组
uid=root
gid=root
# 指定项目的application
module=messageBoard.wsgi:application
# 指定sock的文件路径,nginx使用
socket=/opt/Django_Projects/script/uwsgi.sock
# 启用主进程
master=true
# 进程个数
workers=5
pidfile=/opt/Django_Projects/script/uwsgi.pid
# 自动移除unix socket和pid文件当uwsgi服务停止的时候
vacuum=true
# 设置自中断时间
harakiri=30
# 设置缓冲
post-buffering=4096
# 设置日志目录
daemonize=/opt/Django_Projects/script/uwsgi.log
# 设置socket读写权限
chmod-socket=666
-
启动命令:uwsgi --ini uwsgi.ini -
查看进程:ps -ef |grep -i uwsgi -
nginx添加项目的配置文件
- cd /etc/nginx/conf.d
- vim nginx.conf
server {
listen 80;
server_name 192.168.149.129;
charset utf-8;
# 指定项目路径uwsgi
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:/opt/Django_Projects/script/uwsgi.sock; # 使用unix socket与uwsgi通信
}
# 指定静态文件路径
location /static {
alias /opt/Django_Projects/messageBoard/static/;
}
}
-
service nginx restart
使用Nginx反向代理多个Django程序
-
目的:不使用域名来区分Django程序,使用目录形式来区分 -
同理对每个Django程序配置uwsgi.ini,使用uwsgi启动每个程序(uwsgi --ini uwsgi.ini) -
修改conf.d/nginx.conf server {
listen 80;
server_name 192.168.149.129;
charset utf-8;
# 指定项目1路径uwsgi
location /mess {
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:/opt/Django_Projects/script/uwsgi.sock; # 使用unix socket与uwsgi通信
}
# 指定项目1后台路径uwsgi
location /messadmin {
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:/opt/Django_Projects/script/uwsgi.sock; # 使用unix socket与uwsgi通信
}
# 指定静态文件路径
location /static {
alias /opt/Django_Projects/messageBoard/static/;
}
# 指定项目2路径uwsgi
location /msgapp {
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:/opt/msg/script/uwsgi.sock;
}
# 指定项目2后台路径uwsgi
location /msgappadmin {
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:/opt/msg/script/uwsgi.sock;
}
}
-
对于项目1的全局路由urls.py urlpatterns = [
path('messadmin/', admin.site.urls),
path('mess/', include('index.urls')),
]
-
对于项目2的全局路由urls.py urlpatterns = [
path('msgappadmin/', admin.site.urls),
path('msgapp/', include('index.urls')),
]
-
service nginx restart -
注意:Django程序代码、uwsgi.ini配置文件更改(例如路由更改)后需要使用uwsgi重启程序(reboot后uwsgi --ini uwsgi.ini);nginx.conf配置文件更改后需要重启nginx(service nginx restart)
|