Django3.0新鮮出爐!全面解讀新特性,ASGI真香實(shí)錘,不來(lái)了解一下?

真的機(jī)緣巧合!

image

寫(xiě)這篇文章完全是機(jī)緣巧合,想想已經(jīng)好長(zhǎng)時(shí)間沒(méi)有關(guān)注過(guò)Django了,雖然Django一直霸占著Python Web開(kāi)發(fā)界的王座,但是由于各種原因自從使用Asyncio以來(lái)一直使用Aiohttp這個(gè)框架。碰巧因?yàn)橹皩?xiě)了幾天的《2019逆向復(fù)習(xí)系列》,腦子里充斥著“逆向”,“逆向”,“逆向”。今天想換換思路寫(xiě)點(diǎn)其他的文章,偶然間看到前兩天Django 3.0版本推出,簡(jiǎn)單看了下Django 3.0的新特性,看到Django 3.0正式版本終于支持ASGI了,內(nèi)心真是一陣澎湃,當(dāng)時(shí)放棄Django去選擇其他的異步框架也是因?yàn)樗恢С之惒?,現(xiàn)在它終于完全擁抱異步了,我也就可以重拾Django,嘗嘗鮮啦!

新特性解讀

下面我們簡(jiǎn)單的來(lái)看看Django 3.0的新特性,其中ASGI是最讓人激動(dòng)的,我們放在最后講。

Python兼容性

Django雖然之前沒(méi)有支持異步開(kāi)發(fā),但是在Python版本支持方面,它一向是比誰(shuí)都積極,從Django 2.0版本剛推出開(kāi)始,官方就已經(jīng)宣布停止對(duì)Python 2.X版本的支持了,那個(gè)時(shí)候才是兩年前?。《F(xiàn)在,Django 3.0正式推出,它只支持Python 3.6以上的版本,對(duì)于使用Python 3.5的各位大兄弟們,抱歉,Django 2.2.x系列是最后一個(gè)支持Python 3.5的系列。

數(shù)據(jù)庫(kù)的支持

在數(shù)據(jù)庫(kù)支持方面,一方面Django 3.0將放棄對(duì)PostgreSQL 9.4版本和Oracle 12.1版本的支持。但是另一方面Django 3.0將支持使用MariaDB 10.1或更高版本的數(shù)據(jù)庫(kù)。對(duì)于開(kāi)發(fā)者來(lái)說(shuō),最初上手Django框架一般是Django+MySQL/PostgreSQL來(lái)搞Web,現(xiàn)在可以借此機(jī)會(huì)嘗試下MariaDB,相比于PostgreSQL,MariaDB更類似與MySQl,而且MariaDB相比MySQL來(lái)說(shuō)會(huì)有更多的存儲(chǔ)引擎類型和稍微快一點(diǎn)的查詢效率,所以對(duì)于基于MySQL作為存儲(chǔ)引擎的后端開(kāi)發(fā),可以嘗試切換成MariaDB。更多的對(duì)比可以參考mariadb-vs-mysql。

PostgreSQL的排斥約束

新ExclusionConstraint類允許在PostgreSQL上添加排除約束。使用Meta.constraints選項(xiàng)將約束添加到模型 。
ExclusionConstraint定義類普通的約束定義類似

class ExclusionConstraint(*, name, expressions, index_type=None, condition=None)?

同樣的,我們也可以使用Meta.constraints把約束加入Model

from django.contrib.postgres.fields import DateTimeRangeField, RangeOperators
from django.db import models
from django.db.models import Q

class Room(models.Model): # 建議房間模型
    number = models.IntegerField()

class Reservation(models.Model): # 建立預(yù)約模型
    room = models.ForeignKey('Room', on_delete=models.CASCADE) # 級(jí)聯(lián)外鍵
    timespan = DateTimeRangeField() # 新建兩個(gè)字段
    cancelled = models.BooleanField(default=False)

    class Meta: # 定義約束
        constraints = [
            ExclusionConstraint( # 排斥約束
                name='exclude_overlapping_reservations',
                expressions=[ # timespan字段不在函數(shù)范圍內(nèi)排斥
                    ('timespan', RangeOperators.OVERLAPS),
                    ('room', RangeOperators.EQUAL),
                ],
                condition=Q(cancelled=False),
            ),
        ]

過(guò)濾器表達(dá)式?

這個(gè)變動(dòng)是在QuerySet過(guò)濾器中的,現(xiàn)在BooleanField可以直接在QuerySet過(guò)濾器中使用輸出的表達(dá)式,而不必首先注釋,然后針對(duì)注釋進(jìn)行過(guò)濾。

模型字段選擇的枚舉

在之前的Django版本,我們?cè)趍odel的field字段需要枚舉的時(shí)候通常需要這么做

from django.utils.translation import gettext_lazy as _

class Student(models.Model): # 定義模型

    class YearInSchool(models.TextChoices): # 定義TextChoices類
        FRESHMAN = 'FR', _('Freshman')
        SOPHOMORE = 'SO', _('Sophomore')
        JUNIOR = 'JR', _('Junior')
        SENIOR = 'SR', _('Senior')
        GRADUATE = 'GR', _('Graduate')

    year_in_school = models.CharField( # 引用TextChoices類作為枚舉選擇
        max_length=2,
        choices=YearInSchool.choices,
        default=YearInSchool.FRESHMAN,
    )

    def is_upperclass(self):
        return self.year_in_school in {YearInSchool.JUNIOR, YearInSchool.SENIOR}

從上面可以看出,Django中沒(méi)有特定的枚舉字段,需要我們手動(dòng)去指定,而在Django 3.0中,自定義枚舉類型TextChoices,IntegerChoices和Choices現(xiàn)在作為一個(gè)的方式來(lái)定義Field.choices。為文本和整數(shù)字段提供了類型TextChoices 和IntegerChoices類型。在 Choices類允許定義為其他具體的數(shù)據(jù)類型兼容的枚舉。這些自定義枚舉類型支持人類可讀的標(biāo)簽,可以通過(guò)枚舉或其成員上的屬性來(lái)翻譯和訪問(wèn)這些標(biāo)簽。舉個(gè)例子,上面的代碼我們可以這么來(lái)寫(xiě):


class Student(models.Model):
    FRESHMAN = 'FR'
    SOPHOMORE = 'SO'
    JUNIOR = 'JR'
    SENIOR = 'SR'
    GRADUATE = 'GR'
    YEAR_IN_SCHOOL_CHOICES = [
        (FRESHMAN, 'Freshman'),
        (SOPHOMORE, 'Sophomore'),
        (JUNIOR, 'Junior'),
        (SENIOR, 'Senior'),
        (GRADUATE, 'Graduate'),
    ]
    year_in_school = models.CharField(
        max_length=2,
        choices=YEAR_IN_SCHOOL_CHOICES,
        default=FRESHMAN,
    )

    def is_upperclass(self):
        return self.year_in_school in {self.JUNIOR, self.SENIOR}

大家看,是不是方便了許多,現(xiàn)在有個(gè)特定的Choice字段來(lái)供我們選擇,整個(gè)代碼的思路就更清晰了。

次要特性

上面列舉的是主要變動(dòng)和新增的新特性,下面介紹的是次要的特性。

django.contrib.admin?
  • 增加了對(duì)admin_order_field屬性屬性,支持ModelAdmin.list_display。
  • 新ModelAdmin.get_inlines()方法允許根據(jù)請(qǐng)求或模型實(shí)例指定內(nèi)聯(lián)。
  • Select2庫(kù)從4.0.3版本升級(jí)到4.0.7。
  • jQuery從3.3.1版本升級(jí)到3.4.1。
django.contrib.auth?
  • 新增reset_url_token屬性,其中PasswordResetConfirmView允許指定顯示為密碼重置URL組件的令牌參數(shù)。
  • 添加了BaseBackend類,以簡(jiǎn)化身份驗(yàn)證后端的自定義。
  • 添加了get_user_permissions()方法,類似于現(xiàn)在的get_group_permissions()方法。
  • createsuperuser現(xiàn)在變化為當(dāng)非交互模式下未提供相應(yīng)的命令行參數(shù)時(shí),退回到密碼和必填字段的環(huán)境變量。
  • REQUIRED_FIELDS現(xiàn)在支持ManyToManyField。
  • 新UserManager.with_perm()方法將返回具有指定權(quán)限的用戶。
  • PBKDF2密碼哈希器的默認(rèn)迭代計(jì)數(shù)從150,000增加到180,000。
表格
  • 表單集可以通過(guò)can_order設(shè)置ordering_widget屬性或覆蓋來(lái)控制在訂購(gòu)表單時(shí)使用的小部件。
文件存儲(chǔ)
  • Storage.get_alternative_name()如果已經(jīng)存在帶有上載名稱的文件,則新方法允許自定義生成文件名的算法。
國(guó)際
  • 增加了LANGUAGE_COOKIE_HTTPONLY,LANGUAGE_COOKIE_SAMESITE和LANGUAGE_COOKIE_SECURE參數(shù)來(lái)設(shè)置HttpOnly,SameSite以及Secure對(duì)語(yǔ)言的cookie標(biāo)志。這些設(shè)置的默認(rèn)值和之前的版本相同。
  • 添加了對(duì)烏茲別克語(yǔ)的支持和翻譯。

有關(guān)于Django 3.0新特性的解讀就是這樣,具體更詳細(xì)的解讀大家可以看看官方的News

重點(diǎn)關(guān)注ASGI

介紹完了Django 3.0新特性之后呢要重點(diǎn)關(guān)注ASGI了,要完全理解ASGI恐怕一篇文章是不夠的,所以下次我會(huì)再出一篇文章來(lái)重點(diǎn)介紹一下ASGi,這篇我們簡(jiǎn)單了解下ASGi以及看看它在Django 3.0中是如何去使用的。

什么是ASGI?

要想了解什么是ASGI,那就要了解什么是WSGI,要想了解什么是ASGI,那就要了解什么是CGI。

  • CGI就是(通用網(wǎng)關(guān)接口, Common Gateway Interface/CGI),舉個(gè)例子就是正常的客戶端發(fā)送HTTP請(qǐng)求到服務(wù)端,服務(wù)端經(jīng)過(guò)某些請(qǐng)求處理,再構(gòu)建出符合HTTP的響應(yīng)返回,這個(gè)過(guò)程中的處理程序就是CGI,可以看下圖所示:


    image
  • 了解了什么是CGI之后,那什么是WSGi呢?引用維基上的解釋為,Web服務(wù)器網(wǎng)關(guān)接口(Python Web Server Gateway Interface,WSGI),其實(shí)作用和CGI的差不多,即在WSGI服務(wù)器和WSGI應(yīng)用之間起調(diào)解作用,
    一句話概括,其實(shí)可以說(shuō)WSGI就是基于Python的以CGI為標(biāo)準(zhǔn)做一些擴(kuò)展。
  • 既然WSGi是這樣,那ASGi又是什么呢?ASGI的A其實(shí)就是Async,也就是異步的意思,理解起來(lái)就是異步的WSGI,它產(chǎn)生的原因是因?yàn)樵谌缃馱eb環(huán)境越來(lái)越復(fù)雜的情況下,有很多WSGI不支持的協(xié)議,例如WebSocket,HTTP2等等并且WSGI是基于同步的服務(wù),因此針對(duì)這些情況,Django團(tuán)隊(duì)(哈哈,沒(méi)想到是他們吧?。┦讋?chuàng)了ASGi的概念,也是因?yàn)樗麄儾粷M足于Django基于WSGI的種種低效表現(xiàn),ASGI模式將Django作為原生異步應(yīng)用程序運(yùn)行,原有的WSGI模式將圍繞每個(gè)Django調(diào)用運(yùn)行單個(gè)事件循環(huán),以使異步處理層與同步服務(wù)器兼容。

具體可以淺顯的理解為這樣:在ASGI中,將一個(gè)網(wǎng)絡(luò)請(qǐng)求劃分成三個(gè)處理層面,最前面的一層,interface server(協(xié)議處理服務(wù)器),負(fù)責(zé)對(duì)請(qǐng)求協(xié)議進(jìn)行解析,并將不同的協(xié)議分發(fā)到不同的Channel(頻道);頻道屬于第二層,通??梢允且粋€(gè)隊(duì)列系統(tǒng)。頻道綁定了第三層的Consumer(消費(fèi)者)。比如說(shuō),HTTP協(xié)議的頻道綁定了HTTP的消費(fèi)者,當(dāng)有新的HTTP請(qǐng)求過(guò)來(lái)時(shí),interface server將該請(qǐng)求分發(fā)到HTTP頻道,HTTP 頻道綁定的HTTP消費(fèi)者對(duì)該請(qǐng)求進(jìn)行處理,將處理結(jié)果返回給HTTP頻道,最終傳回給客戶端。


image

Django+ASGI+Uvicorn實(shí)戰(zhàn)

ASGI既然是基于WSGI擴(kuò)展開(kāi)發(fā)的,那么使用的方法和WSGI類似,我們同樣需要一個(gè)application對(duì)象,然后使用應(yīng)用服務(wù)器把這個(gè)對(duì)象啟動(dòng)起來(lái),就像使用Gunicorn/UWsgi啟動(dòng)WSGI一樣,這樣我們使用Uvicorn,Uvicorn是基于uvloop和httptools的ASGI服務(wù)器,它理論上是Python中最高性能的框架了,我們首先下載它

pip install uvicorn

對(duì)于一個(gè)典型的Django項(xiàng)目,調(diào)用Uvicorn如下所示

uvicorn myproject.asgi:application

然后進(jìn)程監(jiān)聽(tīng)一個(gè)8000端口,我們就這樣很輕易的基于ASGI開(kāi)發(fā)了Django的實(shí)戰(zhàn)項(xiàng)目了。


作者相關(guān)

號(hào)主介紹

多年反爬蟲(chóng)破解經(jīng)驗(yàn),AKA“逆向小學(xué)生”,沉迷數(shù)據(jù)分析和黑客增長(zhǎng)不能自拔,虛名有CSDN博客專家和華為云享專家。

私藏資料

嘔心瀝血從浩瀚的資料中整理了獨(dú)家的“私藏資料”,公眾號(hào)內(nèi)回復(fù)“私藏資料”即可領(lǐng)取爬蟲(chóng)高級(jí)逆向教學(xué)視頻以及多平臺(tái)的中文數(shù)據(jù)集

小學(xué)生都推薦的好文

2019年末逆向復(fù)習(xí)系列之今日頭條WEB端_signature、as、cp參數(shù)逆向分析

2019年末逆向復(fù)習(xí)系列之百度指數(shù)Data加密逆向破解

2019年末逆向復(fù)習(xí)系列之努比亞Cookie生成逆向分析

2019年末逆向復(fù)習(xí)系列之淘寶M站Sign參數(shù)逆向分析

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Python語(yǔ)言特性 1 Python的函數(shù)參數(shù)傳遞 看兩個(gè)如下例子,分析運(yùn)行結(jié)果: 代碼一: a = 1 def...
    伊森H閱讀 3,175評(píng)論 0 15
  • # Python 資源大全中文版 我想很多程序員應(yīng)該記得 GitHub 上有一個(gè) Awesome - XXX 系列...
    小邁克閱讀 3,122評(píng)論 1 3
  • Python語(yǔ)言特性 1 Python的函數(shù)參數(shù)傳遞 看兩個(gè)如下例子,分析運(yùn)行結(jié)果: 代碼一: a = 1 def...
    時(shí)光清淺03閱讀 566評(píng)論 0 0
  • 談?wù)揥EB編程的時(shí)候常說(shuō)天天在寫(xiě)CGI,那么CGI是什么呢?可能很多時(shí)候并不會(huì)去深究這些基礎(chǔ)概念,再比如除了CGI...
    __七把刀__閱讀 2,305評(píng)論 2 11
  • 休息
    鉗子ada閱讀 186評(píng)論 0 0

友情鏈接更多精彩內(nèi)容