Python除了學習基礎知識之外,最常用的三大塊就是數據挖掘分析
,人工智能
,Web開發
,今天就介紹下Python全棧工程師必備的知識點之一Web開發
簡介
Web整體框架
Web框架:
別人已經設定好的一個Web網站模板,你學習它的規則,然後“填空”或“修改”成你自己需要的樣子。
其它基於Python的Web框架,如Tornado、Flask、Django
都是在這個範圍內進行增刪裁剪的。例如Tornado
用的是自己的異步非阻塞通信協議,Flask
則只提供了最精簡和基本的框架,Django
直接使用WSGI
通信協議,並實現了大部分Web應用相關的功能。
圖1 Web框架
Web服務器架構(uWSGI)
什麼是WSGI?(上圖黃色部分)
這裏畫的黃色WSGI
是統稱而已,其實本身是有幾個部分組合而成。
uWSGI是一個Web服務器
,它實現了WSGI協議、uwsgi、http等協議
。Nginx中HttpUwsgiModule
的作用是與uWSGI
服務器進行交換。
要注意 WSGI / uwsgi / uWSGI
這三個概念的區分。
WSGI
是一種Web服務器網關接口。它是一個Web服務器(如nginx,uWSGI等服務器)與web應用(如用Flask框架寫的程序)通信的一種規範。uwsgi
是一種線路協議而不是通信協議,在此常用於在uWSGI服務器與其他網絡服務器(Nginx)的數據通信。- 而
uWSGI
是實現了uwsgi
和WSGI
兩種協議的Web服務器。 - uwsgi協議是一個uWSGI服務器自有的協議,它用於定義傳輸信息的類型(type of information),每一個uwsgi packet前4byte爲傳輸信息類型描述,它與WSGI相比是兩樣東西。
圖2 Web服務器架構
Nginx
通俗易懂的理解下Nginx
1.靜態HTTP服務器
首先它是一個http服務器,可以將服務器上的靜態文件(html,圖片)通過http協議展現給客戶端
2.反向代理和負載均衡
這兩個特性都是相輔相成的,想象下,如果沒有ng,客戶端可以直接通過http協議訪問某網站的應用服務器。如果加上ng,就類似ng成爲了一個代理服務器,而且是反向代理服務器。(正向代理就是我們OC中寫的代理,反向代理可以理解爲給10086打電話)。當網站訪問量大,一臺服務器不夠用,就會把應用部署到多臺服務器上,大量用戶分配給多臺機器,掛一臺也不影響其他。
3.反向代理和虛擬主機
有的網站訪問量大就需要負載均衡。但是小公司前期沒很多訪問量,一臺服務器也夠了,會將多個網站部署到同一臺服務器上。例如aaa.com和bbb.com兩個網站部署在同一臺服務器,兩個域名解析到同一個IP,訪問各自的應用網站,就像兩個服務器一樣,這就是所謂的虛擬主機
個人通俗的來理解下:在開始入門之前先了解下,咱們一般都是用Nginx和uWSGI進行部署我們的Django應用。首先這裏客戶端請求,進入Nginx,如果是靜態資源,直接讀取,其他轉發進入uWSGI
web服務容器,首先和左側和Nginx交互的時候實現了uwsgi
協議,右側和Django應用交互的時候實現了WSGI
協議,這就是三個名詞的基本理解了。
Python服務器類比Java
- 獨立WSGI server(實現了Http服務器功能) + Python Web應用程序
- 例如:Gunicorn,uWSGI + Django,Flask
- 獨立Servlet引擎(Java應用服務器)(實現了Http服務器功能) + Java Web應用程序
- 例如:Jetty,Tomcat + SpringMVC,Struts2
Python和Java服務器共同點
WSGI server(例如Gunicorn和uWSGI)
- WSGI server服務器內部都有組建來實現Socket連接的創建和管理。
- WSGI server服務器都實現了Http服務器功能,能接受Http請求,並且通過Python Web應用程序處理之後返回動態Web內容。
Java應用服務器(Jetty和Tomcat)
- Java應用服務器內部都有Connector組件來實現Socket連接的創建和管理。
- Java應用服務器都實現了Http服務器功能,能接受Http請求,並且通過Java Web應用程序處理之後返回動態Web內容。
Django 整體架構
圖3 Django MTV模型組織
當一個通過上面的Ngnix
和uWSGI
轉發後最後請求Django
站點的時候,下面是Django系統決定執行哪個Python代碼的算法:
- 我們創建的項目
startproject xxx
,有個根的root conf,一般會從ROOT_URLCONF
該字段讀取,但是如果有個HttpResponse對象有urlconf屬性(set by middleware),這個值就會被替換掉(Django中間件全過程解析) - Django加載匹配模塊是根據
urlpatterns
參數的,該參數是django.urls.path()
或者django.url.re_path()
組成的列表 - Django依次匹配URL,匹配到第一個就停下來
- 一旦匹配到,會根據
conf
模塊下是繼續分發還是直接調用執行函數 - 如果匹配失敗,拋出異常,調用內置的錯誤view模塊顯示
6.成功後執行View裏面的函數,分別能綁定model和template,model對應ORM操作數據庫,template用於接收model數據,渲染結果。
7.處理完後原理返回到客戶端。
圖1
是整體架構,圖2
是對應圖1WSGI
部分詳細結構圖,圖3
是Django的MTV整體架構圖。
以下就是Python的Web開發技術棧。如果一個人開發,前端這些技術必須掌握,Web服務器搞懂Nginx
和uWSGI
,公共組件按需取捨,全部用pip
進行安裝,類似OC的cocoapods
,Django自帶了幾種ORM數據庫後端,本地開發SQLIte即可,但是如果你要部署到服務器,MySQL服務器就必須掌握。
開發入門
1.安裝虛擬環境
which python3
cd Desktop
mkdir Hello
virtualenv -p /usr/local/bin/python3 venv
source venv/bin/activate
# 或者 . venv/bin/activate
# deactive 關閉虛擬環境
pip install django==2.2.4
2.創建項目
django-admin startproject mysite
mkdir templates
這裏我們創建了一個主工程文件mysite
,templates如果你是用IDE啓動的話默認安利給你的文件夾,也就是MVT
模型中的T。manager.py
就是項目管理腳本。
python manager runserver
可以看到啓動了DJango服務器。
3.創建app 配置Pycharm參數
python manager.py startapp login
這裏我們要編寫稍微完整一點的Demo,用Pycharm來接管整個工程,如果你創建項目直接用Pycharm也行,但是有些你從Github下載下來的項目,你用Pycharm打開加工的話,一樣需要了解一點基本的配置,不然連一點提示都沒有,下面就是完整的配置。
1.模板文件提示,Pythcharm----Preference-----Language&Framework-----Python Template Languages設置成Django
,這樣模板文件就有了模板提示
2.代碼提示,資源跳轉 Pythcharm----Preference-----Language&Framework-----Django------設置參數
3.templates
文件設置,右擊----Make Directory as-----Template Folder
文件夾變成紫色,同時需要在Settings.py
中設置查找路徑
4.venv
文件設置,右擊----Make Directory as-----Exclusion
變成橙色
5.根目錄設置,右擊----Make Directory as-----SourcesRoot
變成藍色
編寫路由
此時我們的項目有一個主工程mysite
,一個子工程Applogin
,首先打開mysite/urls.py
文件處理總路由入口
from django.contrib import admin
from django.urls import path, include, re_path
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^', include('login.urls', namespace='login'))
]
這裏我們主工程一般不做處理,直接轉發到對應的模塊,比如這裏轉發到login
模塊的urls.py
去匹配,但是我們需要在settings.py
中註冊login
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'login'
]
然後在login
模塊中創建一個urls.py
進行匹配
from django.urls import re_path
from . import views
app_name = 'login'
urlpatterns = [
re_path(r'^index$', views.index, name='mysite_index'),
]
編寫視圖
from django.http import HttpResponse
def index(request):
return HttpResponse('Hello world')
返回HTML模板
上面只是簡單介紹了從路由到View視圖處理完的一套流程,下面接入HTML模板進行演示
首先在根目錄新建一個文件夾static
,創建一個index.css
出來,然後再templates
下面新建一個index.html
。
這兩個文件都需要在settings.py
中設置查找路徑
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',
],
},
},
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
修改視圖返回值,用模板進行渲染
from django.shortcuts import render
def index(request):
context = {}
context['content'] = 'Hello world'
return render(request, 'index.html',context)
模板頁面加載靜態資源以及讀取數據的方式
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'index.css' %}">
</head>
<body>
<h1>{{ content }}</h1>
</body>
</html>
啓動服務
python manage.py runserver
輸入127.0.0.1:8000/index
就能看到我們的Hello World
完整Demo
描述一個用表單提交數據,然後展示出來的框架Demo
設計頁面
# 表單頁面
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'index.css' %}">
</head>
<body>
<h1>登錄</h1>
<form action="{% url 'login:mysite_submit' %}" method="post">
{% csrf_token %}
用戶:<input type="text" name="username">
密碼:<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
# 結果頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% for user in lists %}
姓名:{{ user.username }}
密碼:{{ user.password }}
<br>
{% endfor %}
</ul>
</body>
</html>
模型設計
from django.db import models
class UserInfo(models.Model):
username = models.CharField(max_length=20)
password = models.CharField(max_length=20)
模型設計好之後,我們需要生成遷移文件以及遷移到數據庫建表
python manager.py makemigrations
和 python manager.py migrate
編寫路由
# 加多一條提交的路由
from django.urls import re_path
from . import views
app_name = 'login'
urlpatterns = [
re_path(r'^$', views.index, name='mysite_index'),
re_path(r'^submit$', views.submit, name='mysite_submit')
# re_path(r'^detail/(\d+)/$', views.blog_details, name='blog_details'),
]
編寫View
# 處理邏輯
from django.shortcuts import render
from django.http import HttpResponse
from .models import UserInfo
def index(request):
context = {}
context['content'] = 'Hello world'
return render(request, 'index.html',context)
def submit(request):
if request.POST:
username = request.POST.get('username')
password = request.POST.get('password')
user, created = UserInfo.objects.get_or_create(username=username, password=password)
if created:
user.save()
lists = UserInfo.objects.all()
return render(request, 'result.html', context={'lists': lists })
這裏寫邏輯的時候我們可以進到shell
模式進行測試
python manage.py shell
>>> from login.models import UserInfo
>>> x = UserInfo.objects.all()
>>> x
<QuerySet []>
>>> str(x.query) # 查看對應的sql
'SELECT "login_userinfo"."id", "login_userinfo"."username", "login_userinfo"."password" FROM "login_userinfo"'
編寫Admin顯示的模型
from django.contrib import admin
from .models import UserInfo
@admin.register(UserInfo)
class UserInfoAdmin(admin.ModelAdmin):
list_display = ['pk','username','password']
創建超級管理員
python manage.py createsuperuser
隨後就可以通過127.0.0.1:8000/admin
進入後臺管理頁面,其中能看到我們之前處理admin.py
得到的條目,可以添加或者刪除數據,博客後臺就這麼搞定了。
啓動服務
python manager.py runserver
疑惑
針對這個簡單的Demo,也羅列了用到的一些知識點,下面已經單獨寫了博客分析了
模板標籤
可以看到很多類似的 {% csrf_token %}
和 {% static 'index.css' %}
的東西,這個其實就是模板標籤,簡單理解就是左邊那個是函數,有沒有右側代表函數是否帶參數,很顯然,static就帶參數。我們來模擬一個用途
首先保證你的App被註冊進入了,然後再models.py的同級目錄下創建一個Python包
上面的最基本的自定義Tag,首先在模塊裏面必須包含一個register的模塊級變量,纔可以通過裝飾器註冊tag標籤,使用如下
{% load login_tags %}
......
<h1>登錄{% get_comment_count '1000' %}</h1>
......
CSRF Token作用
裝飾器
內置模塊App
內置中間件 (MIDDLEWARE)
部署前準備 (數據庫遷移)
部署前準備 (靜態資源蒐集)
總結:上面介紹了Django Web開發最基本的框架,開發階段靜態資源不需要單獨處理,只需要指定路徑即可,部署的時候我們會通過腳本把靜態資源蒐集到一個目錄下,配置給到Nginx進行管理。開發階段的數據庫可以用SQLIte進行,不需要單獨的其他配置,等到部署之前,需要按上面的教程遷移到Mysql,其中涉及到一些坑已經有詳細介紹,跟着做就好了,特別注意Mysql的字符編碼集和校對規則就好了,不然數據不兼容是最難受的。本地部署前準備後就需要買個服務器進行部署了,時間不多,下次在詳述如何用Nginx和uWSGI部署到Center OS服務器。
以下是空餘時間陸陸續續寫的博客框架,放在Github了,有興趣的可以研究下傳送門
參考文檔:
Nginx