项目需求和项目效果图:
提供给用户一个查询表单,用户输入需要查询的手机号和日期后,就会得到相应的查询结果。
用户查询表单
查询结果效果图
为什么要先把项目需求和项目效果图写在最开始的位置呢?
原因很简单,为了节省读者不必要的时间!读者先看到项目需求和项目效果图后,应该能够基本了解到本文是否能够对你产生帮助。因为笔者在写该项目的时候,在查询一些资料的时候,也参考了一部分博客,而搜到的博客文章内容真真是良莠不齐。很多情况下,搜索到的标题乍一看,好像是自己需要的,但是内容长篇大论,需要笔者花费时间阅读之后,才发现这根本不是自己需要的;更有甚者,"挂着羊头卖狗肉",除了标题,内容乱写一通,和标题根本无半毛钱关系。(请原谅我吐槽一番)鉴于此,我相信很多的读者和笔者一样,在根据关键词搜索博客文章时,内心之中一定有了实现功能后的效果图或者看到最终项目效果图后就能够知道是不是自己需要的,再决定要不要花费时间来阅读。因此,笔者把项目效果图放在最前面,读者来到本文之后,看到效果图就能知道和内心之中希望实现的效果图是不是一样的或者类似可以进行借鉴的,如果是一样的或可以进行借鉴的,那么笔者很高兴帮助到你;如果不是,读者也不用花费时间通篇阅读完博客之后,才发现不是自己需要的文章,也能够节省一部分的时间。
项目整体说明:
1、线上已有运行了一段时间的数据表,不是对通过Django模型新建数据表,而是对已经存在的数据表进行操作
2、数据表关联关系复杂,希望通过自定义SQL来查询展示数据。即:数据表关联关系不理想,无法满足一对一关联、一对多关联(外键)、多对多关联三种关联关系之中的任何一种(Django模型只支持这三种关联关系,而且多对多关系需要使用中间表的形式,如果你不太理解这句话,请先自行百度下,多对多表关系模型是怎样设计的)
而笔者面临的需求是:三表关联查询,有三个表user、session、message。user表的guest_id和session的guest_id相关联,session表的talk_id和message表的talk_id相关联,
而且session表的talk_id和message表的talk_id,可能是一对一关系,也可能是一对多关系,还可能是多对多关系,总之不符合Django模型中的关联关系,如果强行使用,会发生想象不到的问题,这样情况下,只能自行编写自定义查询的SQL,而不能使用Django的模型对象来进行查询
3、环境:
Django 2.0.13
Linux Centos 6.5
MySQL 5.6
Python 3.4
uWSGI 2.0.17
nginx 1.10.2
Django与Python版本对应关系(读者不一定非要和笔者使用的相同版本的环境,但是一定要使用符合对应关系版本的软件,不然会发生预料不到的状况)
Django version Python versions
1.8 2.7、3.2、3.3、3.4、3.5
1.9、1.10 2.7、3.4、3.5
1.11 2.7、3.4、3.5、3.6
2.0 3.4、3.5、3.6
2.1 3.5、3.6、3.7
4、需要的知识
前端(了解)
Python(掌握)
MySQL(了解)
Linux(了解)
这里根据的是此表单项目所需知识所占比例来计算的,实际上笔者自己还是一名DBA,哈哈
项目目录:
第一部分:基础
1.MVC&MTV模式介绍
2.安装Django
3.创建Django项目
4.项目文件说明
5.Django数据库连接配置
第二部分:Django前后端交互数据处理
1.实现用户查询表单功能
2.实现url请求数据后端处理功能
第三部分:Django+uwsgi+nginx 项目部署
1.WSGI、uwsgi、uWSGI介绍及安装
2.Django+uWSGI+nginx关系
3.项目部署
第一部分:
如果读者这部分已经有了足够的了解,那么可以直接跳过进行第二部分的参考
1.MVC&MTV模式介绍
1.软件设计规范,将业务处理逻辑、数据查询处理、界面展示代码分离
2.MVC对应MTV
Model(模型):是应用程序中用于处理应用程序数据逻辑的部分;通常模型对象负责在数据库中存取数据;负责处理数据
View(视图):是应用程序中处理数据显示的部分(对应html文件);通常视图是依据模型(Model)数据创建的;负责界面展示
Controller(控制器):是应用程序中处理用户交互的部分;通常控制器负责从视图(View)读取数据,控制用户输入,并向模型发送数据;负责业务逻辑
MVC处理框架:
用户请求(url),通过Controller发送给Model,Model处理完数据通过Controller发送给View,View经过渲染,返回给用户
MTV处理框架:
Django相较于MVC多了一个url分发器(urls.py),作用是将url请求分发给不同的view处理,view再调用相应的Model和Template
2.安装Django
[root@backup ~]# /home/python3/bin/pip3 install Django==2.0.13(当然了,网上也有使用Python虚拟环境的)
...
Successfully installed Django pytz
Cleaning up...
3.创建Django项目
[root@backup ~]# cd /home/python3/ (进入到想要创建Django项目的目录下,执行命令后,没有任何输出信息,即为成功创建Django项目,这里是:user_form)
[root@backup python3]# ./bin/python3 /home/python3/bin/django-admin.py startproject user_form
4.项目文件说明
[root@backup python3]# tree user_form/
user_form/
├── manage.py Django命令行管理工具
├── static 自行创建,存放css、js等静态文件
├── templatags 自行创建,存放自定义的模板过滤器
├── templates 自行创建,存放html文件
└── user_form
├── __init__.py 一个空文件,它告诉Python这个目录应该被看做一个Python包
├── settings.py 项目的配置文件
├── urls.py url分发器
└── wsgi.py 全名:Web Server GateWay Interface,Web服务器网关接口,是Django项目与WSGI兼容的Web服务器入口,在部署Django+uwsgi+nginx时使用
5.Django数据库连接配置
默认情况下,Django使用的是sqlite数据库,现在要改为连接远程的MySQL数据库(当然了,也支持其他数据库)
[root@backup ~]# /home/python3/bin/pip3 install pymysql
1.修改项目目录下的__init__.py文件
import pymysql #因为Python3使用的数据库连接驱动为pymysql,而__init__是Python的一个构造方法,可以启到初始化的用途,在导入模块时自动触发
pymysql.install_as_MySQLdb()
2.修改项目目录下的settings.py文件
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'xxx',
'USER':'xxxx',
'PASSWORD':'xxxx',
'HOST':'xxx',
'PORT':'3306',
}
}
第二部分:
1.实现用户查询表单功能
1)配置settings.py
第一个需要调整的地方是57行(不同Django版本可能会稍有不同),这是为了让Django知道到哪里去查找我们的html文件
57 'DIRS': [os.path.join(BASE_DIR, 'templates')],
第二个需要调整的地方是28行(不同Django版本可能会稍有不同),这是因为Django默认只能通过127.0.0.1访问,加上这个可以让任意地址访问Django项目,当然了,测试阶段如此,后期我们还会调整
28 ALLOWED_HOSTS = ['*']
2)配置url分发器,用来接收用户的url请求,还记得吗?(MTV框架)
cat /home/python3/user_form/user_form/urls.py
from django.contrib import admin
from django.urls import path
from . import search
urlpatterns = [
path('admin/', admin.site.urls),
path('user_search/',search.user_search),
]
红色部分是我们自行配置的,user_search表示用户请求的部分,而search.user_search表示search模块中user_search的处理函数,from . import search 表示和urls.py同一级目录导入
3)配置用户请求逻辑处理部分,相当于View
cat /home/python3/user_form/user_form/search.py
#coding: utf-8
from django.http import HttpResponse
from django.shortcuts import render_to_response
def user_search(request):
return render_to_response('user_search.html')
4)配置html模板
cat /home/python3/user_form/templates/user_search.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户信息搜索</title>
</head>
<body>
<form action="/search4" method="get"> 这是最为重要的部分,前面我们只是请求了html,只涉及到前端的部分,但实际情况往往是需要将前端的请求数据传到后端进行处理后,然后返回的,search4就是后端处理函数
<input type="text" name="q" placeholder="请输入查询手机号"><br/>
<input type="text" name="startTime" placeholder="请输入查询日期 如: 20190916"><br/>
<input type="submit" value="用户聊天记录查询" ><br/>
</form>
</body>
</html>
2.实现url请求数据后端处理功能
前面虽然实现了 用户查询表单功能 的部分,但是实际上,现在很多的网站都是动态网站,是需要和后端数据库进行交互的,所以,这部分笔者来实现这部分的需求
1)处理前端html传输过来的数据部分
cat /home/python3/user_form/user_form/search.py
#coding: utf-8
from django.http import HttpResponse
from django.shortcuts import render_to_response
import pymysql
#用户查询表单提交数据部分
def user_search(request):
return render_to_response('user_search.html')
#将表单数据进行后端处理的部分
def search4(request):
try:
request.encoding = 'utf-8'
if request.GET['q'] is '' or request.GET['startTime'] is '':
return HttpResponse('您是否忘记了输入查询手机号或者查询日期?')
else:
names = request.GET['q'].strip()
startTime = request.GET['startTime'].strip()
db = pymysql.connect(host='xxx', user='xxx', passwd='xxx', db='xxx', charset='utf8')
cursor = db.cursor()
sql = 'SELECT a.guest_name,a.mobile,a.weixin,a.qq,a.email,b.se,b.kw,b.referer,b.land_page,' \
'b.guest_area,b.talk_time,b.talk_page,' \
'c.msg_type,c.msg,c.worker_id,c.worker_name ' \
'FROM userInfo%s a INNER JOIN session%s b ON a.guest_id = b.guest_id ' \
'INNER JOIN message%s c ON b.talk_id = c.talk_id WHERE a.guest_name LIKE "%%%s%%"' % (startTime,startTime,startTime,names)
cursor.execute(sql)
result = cursor.fetchall()
if result:
return render_to_response('form.html', {'raw': result}) result会返回一个二元数组
else:
return HttpResponse('很抱歉,没有匹配的查询结果,请您检查输入的手机号是否正确!')
except Exception as e:
return HttpResponse(e)
2)渲染从后端返回的处理数据(俗称:套模板)
cat /home/python3/user_form/templates/form.html
渲染内容较多,笔者只选择其中重要的部分进行讲解
{% load staticfiles %} #引用静态文件,在后面我会说明它的用途
{% load msg_type %} #引用自定义过滤器,在后面我会说明它的用途
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
xxx
<!-- Bootstrap -->
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}"> #引用静态文件,settings.py文件中需要配置
xxx
</head>
<body>
xxx
<div>
<div class="form-group">
<label for="exampleInputName2" class="col-sm-2 control-label normal">对话时间</label>
<div class="col-sm-10">
<input type="text" class="form-control" value="{{ raw.0.10|riqi }}" readonly> #{{Python引用变量的模板语法,这里为取值第一个元祖下标为10的元素,并交由日期过滤器处理,还记得raw返回的是一个二维元祖吗?}}
</div>
</div>
<div>
<label for="exampleInputName2" class="col-sm-2 control-label normal">来源页面</label>
<div>
<input type="text" value="{{ raw.0.7 }}" readonly>
</div>
xxx
</body>
</html>
以上就是最为核心的处理部分,笔者在这里列出一些常见的问题和额外的数据处理(比如过滤器的二次处理),希望对你有所帮助
1.如果你的页面出现了如下的问题,而不是笔者在博客开始时展现的效果图,那么,毫无疑问,你的样式引用失败了
解决方法也很简单,请自行在settings.py文件中的末尾位置,配置你的静态文件所在的目录(笔者的是static,还记得吗?)
cat /home/python3/user_form/user_form/settings.py
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
STATIC_URL = '/static/'
2.格式化时间戳的问题。如图所示,我希望查询出来的数据直接显示成 2019-06-20 14:06:27 格式,而不是时间戳的形式,这样来说,对用户更加的友好不是。类似这种将查询返回的数据进行二次处理的函数,被称为过滤器。类似这样的需求还有很多,笔者只讲这一个做个示例
首先是过滤器的settings.py的配置,在大概66行的地方,填写如下配置,必须和你返回渲染模板引用的过滤器名称相同。如:form.html开头引用的 {% load msg_type %},还记得吧?
54 TEMPLATES = [
55 {
xxx
66 'libraries':{
67 'msg_type':'templatetags.msg_type',
68 },
其次是自定义Django过滤器,并将其注册到Django过滤器中,然后就可以在返回渲染模板中使用该过滤器了。如:form.html开头引用的
{% load msg_type %} 引用自定义过滤器
{{ raw.0.10|riqi }} 使用自定义过滤器
cat /home/python3/user_form/templatetags/msg_type.py
@register.filter
def riqi(shijian):
shijian = int(shijian)
return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(shijian))
第三部分:
1.WSGI、uwsgi、uWSGI介绍及安装
2.Django+uWSGI+nginx关系
3.项目部署
1.WSGI、uwsgi、uWSGI介绍及安装
WSGI,全名:Web Server Gateway Interface(Web服务器网关接口)。简单来说,WSGI相当于一个管道,一边连着Web服务器(如:nginx),另一边连着用户的应用(如:Django)。通过此管道,协议之间可以进行转换。而uWSGI是一个Web服务器,它实现了uwsgi和wsgi两种协议。(关于协议内容,有兴趣的读者请自行百度)
这个是笔者从网上找到的比较形象的一张示意图,以作参考:
安装uwsgi:
/usr/local/python3/bin/pip3 install uwsgi==2.0.17
2.Django+uWSGI+nginx关系
如上图所示,Server表示nginx、apache等Web服务器;App表示你的应用(如:笔者的Django项目);通过WSGI可以将应用和Web服务器结合起来,只让uWSGI处理动态请求,而静态请求让nginx处理即可,毕竟nginx非常擅长静态内容的处理
3.项目部署
创建uwsgi配置文件
pwd
/home/python3/user_form
cat uwsgi.ini
[uwsgi]
socket=127.0.0.1:8088 配置这个,只能和nginx结合使用,而且需要和nginx的配置地址相同,让nginx反代8088的地址,这也是本文的目的,Django + uWSGI + nginx 项目
#http=192.168.32.3:8088 配置这个,启动uWSGI服务,可以直接使用 http://192.168.32.3:8088 地址进行访问,因为uWSGI本身也是一个Web服务器
chdir=/home/python3/user_form Django项目路径
wsgi-file=user_form/wsgi.py 顾名思义,wsgi file
processes=4 maximum number of worker processes
threads=2
master=true
pidfile=uwsgi.pid
daemonize=uwsgi.log
vacuum = true clear environment on exit
配置nginx
cat /usr/local/nginx/conf/nginx.conf (每个人的nginx路径都不一样,别照搬;而且笔者假设你已经安装了nginx;绿色的是和uWSGI相关的配置信息)
xxx
error_log /usr/local/nginx/logs/error.log;
events {
worker_connections 1024;
}
http {
include 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 /usr/local/nginx/logs/access.log;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
upstream django {
server 127.0.0.1:8088; 需要和uwsgi.ini 文件中配置的相同
}
server {
listen 80;
server_name lzb1.com;
root /usr/local/python3/project/user_form; Django项目路径
location / {
include uwsgi_params; 这里的uwsgi_params是从 /usr/local/nginx/conf/ 路径下拷贝到Django项目路径下的,用途是 用于nginx 和 uwsgi 之间的请求格式的转换
uwsgi_pass django;
}
location /static {
alias /usr/local/python3/project/user_form/static/; static静态文件路径,毕竟静态文件完全可以经由nginx来处理,而不必经过uWSGI
}
}
}
启动/关闭uWSGI、nginx
pwd
/home/python3/user_form
/usr/local/python3/bin/uwsgi --ini uwsgi.ini 启动
/usr/local/python3/bin/uwsgi --stop uwsgi.pid 关闭
/usr/local/nginx/sbin/nginx -t 语法检查
/usr/local/nginx/sbin/nginx 启动
/usr/local/nginx/sbin/nginx -s stop 关闭
netstat -ntlp | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1425/nginx
tcp 0 0 127.0.0.1:8088 0.0.0.0:* LISTEN 1413/uwsgi
配置Windows hosts文件
192.168.32.3 lzb1.com
访问:
http://lzb1.com/user_search/
至此,Django + uWSGI+ nginx 用户表单查询项目,从简单的MVC&MTV模式介绍、Django安装,到实现用户查询表单功能、url请求数据后端处理功能,再到最后的将项目部署到linux,使其成为一个成型的项目,已经全部完成。
题外:
因为这是笔者第一次使用Python写成的可以上线使用的项目,文章中难免可能会有一些理解不到位的地方,请观看的读者在下方留言指正!同时,俗语讲:"万事开头难",对于第一次独立写成的项目,除了喜悦感和成就感溢于言表之外;写项目过程之中的困难和弯路,也着实令人苦恼;写作本文,一方面记录笔者自己的成长过程和项目成果,另一方面,也为那些正在苦恼类似表单项目怎么写,或者将来也要写类似项目的读者提供一个思路,使其少走一些弯路,希望可以帮到你
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。