IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Nginx+uWSGI+Django项目(史上最详细) -> 正文阅读

[Python知识库]Nginx+uWSGI+Django项目(史上最详细)

项目设计与配置

实现功能

  • 信息反馈页面:信息提交功能以表单形式实现,信息展示以数据列表形式呈现;每条信息包含序号、用户名、信息内容和提交日期

信息反馈页面

  • Admin后台系统:管理信息反馈页面的数据内容,方便网站管理员维护和管理网站的数据内容

  • 自定义异常机制:实现404和500的页面设置,使404和500页面与信息反馈页面的设计风格保持一致

自定义异常机制

  • 单元测试:测试信息反馈页面的功能,比如测试模型的读写操作、视图函数的业务逻辑

项目架构设计

  • 创建项目messageBoard
django-admin startproject messageBoard
  • 创建项目应用index(用于实现信息反馈页面)
python manage.py startapp index
  • 针对全局template的路由配置:在项目根目录下创建模板文件夹templates,并分别创建模板文件404.html、500.html和base.html(共用模板文件);在setting设置TEMPLATES
# setting.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # 添加全局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):
    #render()是模板引擎,第一个参数是request,第二个参数是页面
    return render(request, "index.html")
  • 针对本应用内template的路由配置:在index应用文件夹中新建templates,其中再新建文件夹index,放置index.html(用于生成信息反馈页面,它继承共用模板文件base.html);在setting设置INSTALLED_APPS
# setting.py

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):
    #render()是模板引擎,第一个参数是request,第二个参数是页面
    return render(request, "index/index.html")
  • index应用文件夹中新建static(该文件夹的静态资源只能在Django的调试模式下使用),其中放置静态资源

  • 项目目录下新建static(该文件夹存放静态资源),需要对static进行配置(如进阶所述)

  • index应用文件夹中创建urls.py文件

  • index应用文件夹中创建form.py文件(用于定义表单类MessageModelForm,在模板文件index.html中使用表单类实现信息提交功能)

项目架构设计1
项目架构设计2

中间件

中间件介绍

中间件

  • Django中间件作用

    • 修改请求,即传送到view中的HttpRequest对象
    • 修改响应,即view返回的HttpResponse对象
  • 中间件组件配置在settings.py文件的MIDDLEWARE选项列表中

  • 配置中的每个字符串选项都是一个类,也就是一个中间件

中间件配置

# 添加中间件LocaleMiddleware,因为项目需要使用内置Admin后台系统实现信息反馈页面的数据管理
'django.middleware.locale.LocaleMiddleware', 

数据库配置

创建数据库

  • 使用Navicat创建数据库messagedb

连接数据库

# setting.py

# 将项目与数据库进行连接
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'messagedb',
        'USER' : 'root',
        'PASSWORD' : 'root',
        'HOST' : '127.0.0.1',
        'PORT' : '3306',
    }
}

数据库架构设计

  • 用户提交的信息以数据列表形式呈现;每条信息包含序号、用户名、信息内容和提交日期

  • 利用Django ORM,在models.py中定义表并映射到MySQL

# index的models.py

from django.db import models

class Message(models.Model): # 继承基类
    id = models.AutoField('序号', primary_key = True) # 自增长类型,数据表的字段类型为整数,长度为11位
    name = models.CharField('名称', max_length = 50) # 字符类型
    content = models.CharField('信息内容', max_length = 200) 
    timestamp = models.DateField('反馈时间', auto_now = True) # 日期(Date)类型

    def __str__(self):
        return self.name
    class Meta:
        verbose_name = '信息反馈表'
        verbose_name_plural = '信息反馈表' # verbose_name和verbose_name_plural用于设置模型Message在Admin后台系统的名称
  • 该Django项目在python虚拟环境下(虚拟环境下安装的内容在其他环境不起作用),需要安装驱动程序,而Django默认驱动是MySQLdb
# index的__init__.py

import pymysql

pymysql.install_as_MySQLdb() # 安装Django默认驱动
  • 整个项目的数据迁移
python manage.py makemigrations
python manage.py migrate

程序功能开发

共用模板base.html

  • 共用模板必须具有所有模板文件的共性

  • 404.html、500.html、index.html都要继承base.html

  • base.html

信息反馈页面(首页)功能

  • 全局路由
# messageBoard的urls.py

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')), # 将网站首页地址指向项目应用index的urls.py
]
  • 局部路由
# index的urls.py

from os import name
from django.urls import path
from . import views

app_name = index # app_name

urlpatterns = [
    path('index/', views.index, name='index'), # url_name,满足url标签
]
  • 表单类

ModelForm

# index的form.py

from django import forms
from .models import *

class MessageModelForm(forms.ModelForm):  # 继承表单ModelForm
    # 绑定模型Message
    class Meta:
        model = Message
        fields = '__all__'
  • 处理函数
# index的views.py

from django.shortcuts import render, redirect
from .models import Message
from .form import MessageModelForm

def index(request):
    # 有了数据库,自带GET功能
    messages = Message.objects.all().order_by('-id') # 对表Message的数据进行查询并生成messages对象
    if request.method == 'POST': # POST就是提交按钮
        form = MessageModelForm(request.POST) # 用表单类MessageModelForm接收请求参数,生成表单对象form
        if form.is_valid(): # 验证对象form的数据是否合理
            form.save()
        return redirect('/thanks/') # 重定向(通过路由重定向)
    return render(request, 'index/index.html', locals()) # 以字典形式返回当前位置的全部局部变量(messages)

提示页面thanks.html

  • 路由
# index的urls.py

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)
]
  • 处理函数
# index的views

def thanks(request):
    return render(request, 'index/thanks.html')

自定义404、500异常页面功能

  • django处理异常机制:当HTTP请求引发一个异常时,若URLconf中没有设置handler,则django会加载一个内置处理异常的函数(django.views.defaults.page_not_found()、django.views.defaults.page_error());若URLconf中设置了handler,则django会加载这个特殊的处理函数

  • 设置handler

# messageBoard的urls.py

from index import views
handler404 = views.page_not_found # handler404用来设置404的处理函数
handler500 = views.page_error # handler500用来设置500的处理函数
  • 处理函数
# index的views.py

from django.shortcuts import render

def page_not_found(request, exception): # 在django2.2以上404的处理函数必须设置参数exception,否则运行时会提示异常信息
    return render(request, '404.html', status = 404)

def page_error(request):
    return render(request, '500.html', status = 500)
# setting.py

DEBUG = False # 正式上线后debug要设置为false,则此时异常处理就是自定义页面

ALLOWED_HOSTS = ['*'] # ALLOWED_HOSTS列表为了防止黑客入侵,只允许列表中的ip地址访问

Admin后台系统

设置Admin后台系统路由

# messageBoard的urls.py

urlpatterns = [
    path('admin/', admin.site.urls), # 该路由由于定义Admin后台系统的路由信息
]

创建用户

python manage.py createsuperuser

设置

App名在后台中文显示

# index的apps.py

from django.apps import AppConfig


class IndexConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'index'
    verbose_name = '信息管理'

表名、字段名后台中文显示

# index的models.py

from django.db import models

class Message(models.Model): # 继承基类
    id = models.AutoField(primary_key = True, verbose_name='序号') # 自增长类型,数据表的字段类型为整数,长度为11位
    name = models.CharField(max_length = 50, verbose_name='名称') # 字符类型
    content = models.CharField(max_length = 200, verbose_name='信息内容') 
    timestamp = models.DateField(auto_now = True, verbose_name='反馈时间') # 日期(Date)类型

    def __str__(self):
            return self.name
    class Meta:
        verbose_name = '信息反馈表' # 在后台的表名
        verbose_name_plural = verbose_name # 中文没有复数,将s去掉

定义模型Message的ModelAdmin

# index的admin.py

from index.models import Message
from django.contrib import admin

# 修改title和header
admin.site.site_title = '信息反馈后台系统'
admin.site.site_header = '信息反馈平台'

# Register your models here.
@admin.register(Message)
class MessageAdmin(admin.ModelAdmin):
    list_display = ['id', 'name', 'content', 'timestamp'] # 在后台增加信息的属性栏
    list_per_page = 10 # 设置每页默认记录数,默认是100条
    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功能是否正常

编写单元测试内容

# index的test.py

from index.models import Message
from django.test import TestCase, Client

# Create your tests here.

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() # 可以模拟GET与POST
        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) # 信息提交成功功能测试,状态码为302则说明已完成POST处理
        self.assertEqual(info.content, '删库跑路') # 查询是否存在data的数据,存在则说明表单类MessageModelForm成功将表单对象导入数据库

测试

python manage.py test

运行与上线

运行机制

Django自带的wsgi server

runserver性能较差,静态资源、动态资源请求都由Django自带的server处理

Django自带server请求处理逻辑

uWSGI server

并发量高、方便管理多进程、性能好

uWSGI请求处理逻辑

Nginx server

性能较好,静态资源请求交由Nginx server处理,动态资源交由uWSGI server处理,实现动、静态资源处理分离

Nginx+uWSGI请求动静分离逻辑

Linux基本配置

  • 环境;Ubuntu_Server 20.04

  • 下载xshell,密码:zmat,点击绿化安装

配置mysql

  • sudo apt update

  • sudo apt install mysql-server

  • sudo mysql_secure_installation:运行安全脚本以更改一些安全选项

    • 密码强度验证组件
    • 开启远程root登录
  • 更改验证插件并设置本地连接新密码

    • 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与HOST

# messageBoard的setting.py

DEBUG = False # 关闭DEBUG,结束调试阶段
ALLOWED_HOSTS = ['*'] # 允许任何ip访问
  • 静态资源
# messageBoard的setting.py
# 注释掉STATICFILES_DIRS

STATIC_ROOT = os.path.join(BASE_DIR, "static")
python manage.py collectstatic # 在项目根目录下创建static(在static目录下增加admin文件)

static

# messageBoard的urls.py

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), # 该路由由于定义Admin后台系统的路由信息
    path('', include('index.urls')), # 将网站首页地址指向项目应用index的urls.py
    # 设置静态资源的路由信息
    re_path('static/(?P<path>.*)', static.serve, {'document_root':settings.STATIC_ROOT}, name='static')
]

from index import views
handler404 = views.page_not_found # handler404用来设置404的处理函数
handler500 = views.page_error # handler500用来设置500的处理函数

使用runserver启动Django程序

python manage.py runserver 192.168.149.129:8000

使用uWSGI启动Django程序

# 项目目录下
# 后面的static没有则加载不了静态文件
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), # 该路由由于定义Admin后台系统的路由信息
        path('mess/', include('index.urls')), # 将网站首页地址指向项目应用index的urls.py
    ]
    
  • 对于项目2的全局路由urls.py

    urlpatterns = [
        path('msgappadmin/', admin.site.urls), # 该路由由于定义Admin后台系统的路由信息
        path('msgapp/', include('index.urls')), # 将网站首页地址指向项目应用index的urls.py
    ]
    
  • service nginx restart

  • 注意:Django程序代码、uwsgi.ini配置文件更改(例如路由更改)后需要使用uwsgi重启程序(reboot后uwsgi --ini uwsgi.ini);nginx.conf配置文件更改后需要重启nginx(service nginx restart)

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 07:42:06  更:2021-07-28 07:45:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/25 23:17:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码