您好,登錄后才能下訂單哦!
項目需求和項目效果圖:
提供給用戶一個查詢表單,用戶輸入需要查詢的手機號和日期后,就會得到相應的查詢結果。
用戶查詢表單
查詢結果效果圖
為什么要先把項目需求和項目效果圖寫在最開始的位置呢?
原因很簡單,為了節省讀者不必要的時間!讀者先看到項目需求和項目效果圖后,應該能夠基本了解到本文是否能夠對你產生幫助。因為筆者在寫該項目的時候,在查詢一些資料的時候,也參考了一部分博客,而搜到的博客文章內容真真是良莠不齊。很多情況下,搜索到的標題乍一看,好像是自己需要的,但是內容長篇大論,需要筆者花費時間閱讀之后,才發現這根本不是自己需要的;更有甚者,"掛著羊頭賣狗肉",除了標題,內容亂寫一通,和標題根本無半毛錢關系。(請原諒我吐槽一番)鑒于此,我相信很多的讀者和筆者一樣,在根據關鍵詞搜索博客文章時,內心之中一定有了實現功能后的效果圖或者看到最終項目效果圖后就能夠知道是不是自己需要的,再決定要不要花費時間來閱讀。因此,筆者把項目效果圖放在最前面,讀者來到本文之后,看到效果圖就能知道和內心之中希望實現的效果圖是不是一樣的或者類似可以進行借鑒的,如果是一樣的或可以進行借鑒的,那么筆者很高興幫助到你;如果不是,讀者也不用花費時間通篇閱讀完博客之后,才發現不是自己需要的文章,也能夠節省一部分的時間。
項目整體說明:
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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。