Python Web框架Django從入門到放棄

在這裏插入圖片描述
在這裏插入圖片描述
Python除了學習基礎知識之外,最常用的三大塊就是數據挖掘分析,人工智能,Web開發,今天就介紹下Python全棧工程師必備的知識點之一Web開發

簡介

Web整體框架

Web框架: 別人已經設定好的一個Web網站模板,你學習它的規則,然後“填空”或“修改”成你自己需要的樣子。
其它基於Python的Web框架,如Tornado、Flask、Django都是在這個範圍內進行增刪裁剪的。例如Tornado用的是自己的異步非阻塞通信協議,Flask則只提供了最精簡和基本的框架,Django直接使用WSGI通信協議,並實現了大部分Web應用相關的功能。

圖1 Web框架
圖1

Web服務器架構(uWSGI)

什麼是WSGI?(上圖黃色部分)
這裏畫的黃色WSGI是統稱而已,其實本身是有幾個部分組合而成。

uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http等協議。Nginx中HttpUwsgiModule的作用是與uWSGI服務器進行交換。

要注意 WSGI / uwsgi / uWSGI 這三個概念的區分。

  1. WSGI是一種Web服務器網關接口。它是一個Web服務器(如nginx,uWSGI等服務器)與web應用(如用Flask框架寫的程序)通信的一種規範。
  2. uwsgi是一種線路協議而不是通信協議,在此常用於在uWSGI服務器與其他網絡服務器(Nginx)的數據通信。
  3. uWSGI是實現了uwsgiWSGI兩種協議的Web服務器。
  4. 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,如果是靜態資源,直接讀取,其他轉發進入uWSGIweb服務容器,首先和左側和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模型組織
在這裏插入圖片描述
當一個通過上面的NgnixuWSGI轉發後最後請求Django站點的時候,下面是Django系統決定執行哪個Python代碼的算法:

  1. 我們創建的項目startproject xxx,有個根的root conf,一般會從ROOT_URLCONF該字段讀取,但是如果有個HttpResponse對象有urlconf屬性(set by middleware),這個值就會被替換掉(Django中間件全過程解析
  2. Django加載匹配模塊是根據urlpatterns參數的,該參數是django.urls.path() 或者 django.url.re_path()組成的列表
  3. Django依次匹配URL,匹配到第一個就停下來
  4. 一旦匹配到,會根據conf模塊下是繼續分發還是直接調用執行函數
  5. 如果匹配失敗,拋出異常,調用內置的錯誤view模塊顯示
    6.成功後執行View裏面的函數,分別能綁定model和template,model對應ORM操作數據庫,template用於接收model數據,渲染結果。
    7.處理完後原理返回到客戶端。

圖1是整體架構,圖2是對應圖1WSGI部分詳細結構圖,圖3是Django的MTV整體架構圖。
以下就是Python的Web開發技術棧。如果一個人開發,前端這些技術必須掌握,Web服務器搞懂NginxuWSGI,公共組件按需取捨,全部用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 makemigrationspython 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作用

CSRF

裝飾器

裝飾器和偏函數

內置模塊App

六大模塊之ContentType App

內置中間件 (MIDDLEWARE)

中間件

部署前準備 (數據庫遷移)

SQLIte遷移成Mysql

部署前準備 (靜態資源蒐集)

靜態資源開發配置和部署蒐集

總結:上面介紹了Django Web開發最基本的框架,開發階段靜態資源不需要單獨處理,只需要指定路徑即可,部署的時候我們會通過腳本把靜態資源蒐集到一個目錄下,配置給到Nginx進行管理。開發階段的數據庫可以用SQLIte進行,不需要單獨的其他配置,等到部署之前,需要按上面的教程遷移到Mysql,其中涉及到一些坑已經有詳細介紹,跟着做就好了,特別注意Mysql的字符編碼集和校對規則就好了,不然數據不兼容是最難受的。本地部署前準備後就需要買個服務器進行部署了,時間不多,下次在詳述如何用Nginx和uWSGI部署到Center OS服務器。

以下是空餘時間陸陸續續寫的博客框架,放在Github了,有興趣的可以研究下傳送門

在這裏插入圖片描述
參考文檔:
Nginx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章