1.服务器选择原因:
uWSGI web服务器+Django其实也可以满足web服务器的要求,那么再接上nginx web服务器的原因?
首先Nginx服务器处理静态网页的能力特别强,起码比uWSGI web服务器好。所以可以两个服务器结合,做好动静服务的分离。即是Nginx提供静态服务,uWSGI服务器+Django提供动态服务,这样可以大大的提高响应效率。

2.安装配置uWSGI服务:
2.1安装uWSGI:
pip install uWSGI
2.2 终端命令启动uwsgi服务
Django应用可以单独跑起来(Django也带有web服务功能,但是比较差,可以验证开发)
Django 起服务的命令如下:python3 manage.py runserver 0.0.0.0:9000,如果这个可以通过浏览器验证通过,说明自己开发服务端程序没问题。
在之前验证通过的前提下,在Django项目目录中,执行一下命令,验证uwsgi服务器。
uwsgi --http 0.0.0.0:9000 --file form_demo/wsgi.py --static-map=/static=static
--file form_demo/wsgi.py: Django的form_demo项目名称,wsgi.py指定协议的名称即是wsgi协议。
--static-map=/static=static: 静态文件,可以不写。在浏览器刷新时会找不到。
以上是命令行启动,实际项目中更多的使用配置文件启动。
2.3使用配置文件启动uWSGI [ini 格式]
如下文件uwsgi.ini
[uwsgi]
#项目目录,根据自己项目来定
chdir=/data/Project/python/django_project/form_demo
#启动uwsgi的用户名和用户组
uid=root
gid=root
#指定项目的application
moudle=for_demo.wsgi
#指定sock的文件路径,相对路径有时会出现无法创建文件的情况.
socket=/data/Project/python/django_project/script/uwsgi.sock
#http = :8080 # 如果需要同时提供HTTP服务(如直接对外),此处配合nginx,未用
#启用主进程
master=true
#进程个数
worker=2
#每个进程的线程数
threads=3
#记录进程ID文件
pidfile=/data/Project/python/django_project/script/uwsgi.pid
#当uwsgi服务停止的时候,是否自动删除socket和pid
vacuum=true
#启用
thunder-lock
功能,当设置为true
时,uWSGI 会使用全局文件锁来处理资源竞争问题。你也可以将其设置为false
来禁用该功能thunder-lock = true
#允许多线程(需配合'threads'使用)
enable-threads = true
#请求超时时间(秒),超时自动重启进程
harakiri = 30
#
post-buffering
设置为 65536 字节(即 64KB),意味着 uWSGI 会将 POST 请求数据# 缓冲到 64KB 后再传递给应用程序,当post-buffering
设置为 0 时,uWSGI 会采用流# 式处理的方式,将客户端发送的 POST 请求数据逐块传递给应用程序,而不会进行缓冲post_buffering = 4096
日志配置
daemonize = /data/Project/python/django_project/script/uwsgi.log # 后台运行并输出日志
#logto = /var/log/uwsgi.log # 等同于 daemonize(二者选一)
#disable-logging = true # 关闭请求日志(仅记录错误)
#下述配置将 URL 中以
/static
开头的请求映射到服务器文件系统中的/path/to/#static/files
目录。例如,当客户端请求http://example.com/static/#style.css
时,uWSGI 会尝试从/path/to/static/files/style.css
文件中读取#内容并返回给客户端#static-map = /static=/path/to/static/files #此处暂时不用
虚拟环境(如果使用)
#virtualenv = /path/to/venv # (本项目Python虚拟环境路径,未使用)
-
socket
指定与Web服务器(如Nginx)通信的地址。可以是端口(如
:8000
)或Unix Socket文件(如/tmp/uwsgi.sock
)。-
使用Nginx时通常选择Unix Socket(性能更好)。
-
直接对外提供HTTP服务时用
http
代替socket
。
-
-
module
指定WSGI入口,例如Django项目的
myapp.wsgi:application
。 -
virtualenv
/home
指定Python虚拟环境路径,确保uWSGI使用项目依赖。
-
processes
和threads
根据服务器CPU核心数调整进程和线程数(如
processes = 2 * CPU核心数
)。 -
master
启用主进程管理子进程,提高稳定性。
-
harakiri
防止请求阻塞,超时自动终止并重启进程。
-
vacuum
退出时自动清理临时文件(避免残留Socket文件导致重启失败)。
2.4生产环境建议
-
使用 Nginx 反向代理到uWSGI的Socket。
-
用 Supervisor 或 systemd 管理uWSGI进程。
-
日志分割:使用
logrotate
或daemonize
结合日志文件路径
可以把uwsgi服务的配置文件和一些服务产生的log信息等放到一个统一目录管理。
我这里是创建一个script文件夹和Django项目同级目录。

常用命令:
uwsgi --ini uwsgi.ini通过配置文件启动wsgi服务
ps -ef | grep -i uwsgi 查看uwsgi服务是否启动?
uwsgi --stop uwsgi.pid 关闭uwsgi服务。
以上命令在创建的script文件夹下执行即可
3.安装配置Nginx
3.1安装Nginx
sudo apt install nginx
也可以用yum源管理安装nginx。
3.2Nginx配置:
server{
#监听端口
listen 8080;
#建议使用域名
server_name 10.2.6.161;
日志配置
access_log /data/Project/python/django_project/nginx_file/form_demo.log;
error_log /data/Project/python/django_project/nginx_file/form_demo_error.log;
启用 Gzip 压缩功能
gzip on;
设置允许压缩的最小响应体大小,单位为字节,小于该值的响应不会被压缩
gzip_min_length 1000;
设置允许压缩的 MIME 类型,只有匹配这些类型的响应才会被压缩
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
处理静态文件请求
静态文件由 Nginx 直接处理(无需经过 uWSGI)
location /static/ {
静态文件的实际存储路径
必须以 `/` 结尾
指定静态文件的根目录。当客户端请求 /static/style.css 时,Nginx 会尝试从
/data/Project/python/django_project/nginx_file/static/style.css
文件中读取内容并返回给客户端
#root /data/Project/python/django_project/nginx_file/static/;
alias 指令会将 location 匹配的部分替换为指定的路径。
当客户端请求 /static/style.css 时,Nginx 会直接从
/data/Project/python/django_project/nginx_file/static/style.css
文件中读取内容
alias /data/Project/python/django_project/nginx_file/static/;
index index.html;
}
location / {
包含uWSGI参数配置
include uwsgi_params;
使用 Unix 套接字通信,需与 uWSGI 配置一致
uwsgi_pass unix:/data/Project/python/django_project/script/uwsgi.sock;
连接 uWSGI 的超时时间(默认 60s)
uwsgi_connect_timeout 70;
等待 uWSGI 响应的超时时间(重要!)
uwsgi_read_timeout 300s;
发送请求到 uWSGI 的超时时间
uwsgi_send_timeout 300s;
保持的长连接数量,版本过低会提示错误,需升级nginx版本
uwsgi_keepalive 32;
连接保持时间(秒)
keepalive_timeout 65;
设置请求头信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
配置参数解释
全局配置部分
listen
:指定 Nginx 服务器监听的端口,可以是具体的端口号(如80
),也可以是[::]:80
同时监听 IPv4 和 IPv6。server_name
:定义服务器的名称,可以是域名(如example.com
)、IP 地址或通配符(如*.example.com
),用于匹配客户端请求的域名。
日志配置部分
access_log
:指定访问日志的存储路径,记录客户端的访问信息,如请求的 URL、请求方法、响应状态码等。error_log
:指定错误日志的存储路径,记录 Nginx 运行过程中出现的错误信息,方便排查问题。
静态文件处理部分
location /static/
:定义一个匹配以/static/
开头的 URL 请求的位置块,用于处理静态文件请求。root
:指定静态文件的实际存储路径,Nginx 会根据请求的 URL 在该路径下查找对应的文件并返回给客户端。- alias 指令会将 location 匹配的部分替换为指定的路径当客户端请求 /static/style.css 时,Nginx 会直接从/data/Project/python/django_project/nginx_file/static/style.css文件中读取内容
动态请求处理部分
include uwsgi_params
:包含 Nginx 自带的uwsgi_params
文件,该文件定义了一系列 uWSGI 相关的参数,如请求的方法、URL、头部信息等,确保请求能正确传递给 uWSGI 服务器。uwsgi_pass
:指定 uWSGI 服务器的地址和端口,Nginx 会将匹配该location
块的请求转发到指定的 uWSGI 服务器进行处理。uwsgi_read_timeout
:设置 Nginx 从 uWSGI 服务器读取响应的超时时间(单位:秒),如果在该时间内没有收到响应,Nginx 会终止连接。uwsgi_send_timeout
:设置 Nginx 向 uWSGI 服务器发送请求的超时时间(单位:秒),如果在该时间内没有发送完请求,Nginx 会终止连接。uwsgi_connect_timeout
:设置 Nginx 与 uWSGI 服务器建立连接的超时时间(单位:秒),如果在该时间内无法建立连接,Nginx 会返回错误信息。proxy_set_header
:用于设置转发请求时的请求头信息,常见的设置包括Host
(客户端请求的主机名)、X-Real-IP
(客户端的真实 IP 地址)、X-Forwarded-For
(客户端的真实 IP 地址及经过的代理服务器 IP 地址)和X-Forwarded-Proto
(客户端请求使用的协议,如http
或https
),这些信息可以帮助 uWSGI 服务器获取客户端的真实信息。
nginx在测试验证中常用的命令等:
sudo service nginx start开启nginx服务
sudo service nginx stop关闭nginx服务
sudo systemctl reload nginx动态加载nginx的配置文件,适用于nginx服务未停止而修改了配置参数
sudo systemctl status nginx 查看nginx服务运行状态,
4.验证服务
建议先启动uwsgi服务再启动nginx服务,关闭时则相反即可.
4.1验证静态网页服务:
html
<!DOCTYPE html>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>This is a static webpage served by Nginx.</p>
</body>
</html>
创建以上的index.html,文件路径:/data/Project/python/django_project/nginx_file/static。
根据nginx服务配置:
。。。
#监听端口
listen 8080;
#建议使用域名
server_name 10.2.6.161;
location /static/ {
alias /data/Project/python/django_project/nginx_file/static/;
index index.html;
}
。。。
在ubuntu终端先后执行命令如下:

可以在同一个pc上的浏览器直接输入地址:http://0.0.0.0:8080/static/

4.2动态服务请求验证:
贴上具体的uwsgi.ini文件:
[uwsgi]
chdir=../form_demo
uid=root
gid=root
socket = /data/Project/python/django_project/script/uwsgi.sock
chmod-socket = 666
module = form_demo.wsgi
master = true
workers = 2
threads = 3
pidfile=./uwsgi.pid
logto = ./uwsgi.log
daemonize = ./uwsgi.log
vacuum = true
自己撰写的Nginx confgi文件,路径:/etc/nginx/conf.d/form_demo.conf。最终的配置结果可以通过命令: sudo nginx -T查看有效的配置.
server{
#监听端口
listen 8080;
#建议使用域名
server_name 10.2.6.161;
日志配置
access_log /data/Project/python/django_project/nginx_file/form_demo.log;
error_log /data/Project/python/django_project/nginx_file/form_demo_error.log;
启用 Gzip 压缩功能
#gzip on;
设置允许压缩的最小响应体大小,单位为字节,小于该值的响应不会被压缩
#gzip_min_length 1000;
设置允许压缩的 MIME 类型,只有匹配这些类型的响应才会被压缩
#gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
处理静态文件请求
静态文件由 Nginx 直接处理(无需经过 uWSGI)
location /static/ {
静态文件的实际存储路径
必须以 `/` 结尾
alias /data/Project/python/django_project/nginx_file/static/;
index index.html;
}
location / {
包含uWSGI参数配置
include uwsgi_params;
连接 uWSGI 的超时时间(默认 60s)
uwsgi_connect_timeout 70;
uwsgi_pass unix:/data/Project/python/django_project/script/uwsgi.sock;
等待 uWSGI 响应的超时时间(重要!)
#uwsgi_read_timeout 300s;
发送请求到 uWSGI 的超时时间
#uwsgi_send_timeout 300s;
保持的长连接数量
#uwsgi_keepalive 32;
连接保持时间(秒)
#keepalive_timeout 65;
设置请求头信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
nginx配置包含哪些路径配置可以查看:/etc/nginx/nginx.conf,通常自己写的配置文件可以放在目录:/etc/nginx/conf.d。
操作命令:

Django项目名字form_demo,目录结果如下:

form_demo->urls.py 代码如下:
python
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
# 新增
path('front/',include('front.urls')),
]
front->urls.py代码如下:
python
from django.urls import path
from . import views
urlpatterns = [
path('', views.index,name = 'index_view'),
path('register', views.register_view,name = 'register_view'),
path('article', views.article_view,name = 'article_view'),
]
front->views.py代码如下:
python
from django.shortcuts import render,HttpResponse
from .forms import MessageBoardForm,RegisterForm,ArticleForm
# Create your views here.
#请求的method
#1 Get 请求
#2 Post 请求
def index(request):
#如果是get请求就返回一个模板:
if request.method == 'GET':
form = MessageBoardForm()
return render(request,'index.html',context={'form':form})
elif request.method == 'POST':
# 对用post提交的数据进行数据验证
form = MessageBoardForm(request.POST)
if form.is_valid():
#验证通过:
content = form.cleaned_data.get('content')
title = form.cleaned_data.get('title')
email = form.cleaned_data.get('email')
return HttpResponse(f'{content},{title},{email}')
else:
#表单验证失败:
print(form.errors)
return HttpResponse('表单验证失败')
def register_view(request):
if request.method == 'GET':
return render(request,'register.html')
elif request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
phone = form.cleaned_data.get('phone')
print('phone is %s'%phone)
return HttpResponse(f'{phone}')
else:
print(form.errors)
return HttpResponse('表单验证失败')
def article_view(request):
if request.method == 'GET':
return render(request,'article.html')
elif request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
title = form.cleaned_data.get('title')
content = form.cleaned_data.get('content')
return HttpResponse(f'{title},{content}')
else:
print(form.errors)
return HttpResponse('表单验证失败')
front->form.py代码如下:
python
from django import forms
from django.core.validators import RegexValidator
from .models import Article
#留言板的表单
class MessageBoardForm(forms.Form):
title = forms.CharField(max_length=100,min_length=2,label='标题',error_messages=
{'required':'标题不能为空','min_length':'标题不能小于2个字符','max_length':'标题不能大于100个字符'})
content = forms.CharField(widget=forms.Textarea,label='内容')
email = forms.EmailField(label='邮箱')
class RegisterForm(forms.Form):
phone = forms.CharField(validators=[RegexValidator(r'^1[3-8]\d{9}$',message='电话手机号格式不正确')])
def clean_phone(self):
phone = self.cleaned_data.get('phone')
return phone
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = '__all__'
#fields = ['title','content']
# 测试fields = '__all__' 时 category字段 blank=False,提示信息。
error_messages = {
'category':{'required':'分类字段不能为空'}
}
form->settings.py配置如下:
python
"""
Django settings for form_demo project.
Generated by 'django-admin startproject' using Django 4.2.18.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-6@rc#x8(#!x5*r#ol6cj$u()^7d28*0^k#qj*%_*ojbc303t8b'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'front',
]
MIDDLEWARE = [
'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',
]
ROOT_URLCONF = 'form_demo.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [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',
],
},
},
]
WSGI_APPLICATION = 'form_demo.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
新建的templates文件夹下是存放的模板html:
index.html文件如下:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Front页面</title>
</head>
<body>
<h1>留言板</h1>
<form action="" method="post">
{{ form }}
<input type="submit" value="提交">
</form>
</body>
</html>
article.html如下:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>article</title>
</head>
<body>
<form action="" method="post">
<div>
<input type="text" name="title" placeholder="请输入标题">
</div>
<div>
<textarea name="content" id="" cols="30" rows="10" placeholder="请输入内容"></textarea>
</div>
<div>
<input type="submit" value="提交">
</div>
</form>
</body>
</html>
article.html如下:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>注册</title>
</head>
<body>
<form action="" method="post">
<input type="text" name="phone">
<input type="submit" value="提交">
</form>
</body>
</html>
在浏览器验证结果(http://localhost:8080/front/),不是专业的html人员,凑合看,勿喷!

验证(http://localhost:8080/front/article)

以上是操作nginx,uwsgi,django的基本操作,不够全面与细致,仅供参考!