Django匆匆一眼卻解答了多年疑惑

dongfanger發表於2020-12-04

Django 是 Python 的 一款 Web 開發框架,另外還有 Tornado,Flask,Twisted。為什麼我要選擇學 Django?原因很簡單,上家公司來了個網易的測開,就是用 Django 開發的測試平臺。

這位測開沒多久就離職去騰訊了,我啥也沒學到,看了他的程式碼,很多是寫的 Vue 程式碼,哭啊。

Django 誕生於 2003 年的秋天,由 Lawrence Journal-World 報紙的程式設計師 Adrian Holovaty 和 Simon Willison 編寫而成。新聞編輯室的開發節奏是非常快的,正因如此,Django 相比於其他框架的特點就是短、平、快。這也符合 Python 的風格。時至今日,Django 已經發展到了 3.1.3 版本。本系列將基於這一版本的官方文件,邊學習邊實踐,整理成文,分享給大家。

Django 系列不是教程,而是學習筆記、心得體會、踩坑記錄,內容編排上可能會有點亂。需要看教程請閱讀官方文件,水平有限,實在抱歉。

Django 遵循 MVC 架構模式,所以接下來就看看如何使用 Django 完成 Web 開發。特別注意,本文的內容不具有實操性,看看即可。

定義 model

model 是資料模型,定義了資料庫的表和欄位。

例如:

from django.db import models

class Reporter(models.Model):
    full_name = models.CharField(max_length=70)

    def __str__(self):
        return self.full_name

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

    def __str__(self):
        return self.headline

通過類和屬性,分別定義了 2 張表 Reporter 和 Article,以及它們的欄位(Reporter 1 個欄位,Article 4 個欄位)。

這其實就是 ORM,即 Object Relational Mapping,物件關係對映,把程式程式碼中的物件對映到關係型資料庫中,不用寫 SQL,就可以直接運算元據了。ORM 實現了資料持久化。我們都知道程式是執行在記憶體中的,跑完就沒了。為了把資料儲存下來,就需要使用 ORM 技術把記憶體中的資料(程式物件)存到關係型資料庫中,進而轉移到磁碟上。Django 自帶了一個 ORM,開箱即用。

資料遷移

使用 2 條命令,就可以把 model 遷移到資料庫中:

$ python manage.py makemigrations
$ python manage.py migrate

執行完成後,就會在資料庫中按照 model 定義的表名、欄位名、約束條件等,建立表結構。

資料操作

接著就可以在程式中寫程式碼運算元據了。為了直觀看到結果,這裡以命令列形式進行演示:

# 匯入已建立的 models
>>> from news.models import Article, Reporter

# 查詢表 Reporter 為空
>>> Reporter.objects.all()
<QuerySet []>

# 例項化物件,建立 1 條資料,表 Reporter 的欄位是 full_name
>>> r = Reporter(full_name='John Smith')

# 必須顯式呼叫 save() 函式,才會真正寫資料到資料庫
>>> r.save()

# 儲存後就有 id 了
>>> r.id
1

# 查詢表 Reporter 有資料了
>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>

# 訪問物件屬性
>>> r.full_name
'John Smith'

# Django 提供了 get() 函式來支援更多查詢方式
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Reporter matching query does not exist.

# 給表 Article 新增 1 條資料
# 有 4 個欄位 pub_date, headline, content, reporter
# reporter=r,用 Reporter 物件賦值
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
...     content='Yeah.', reporter=r)
>>> a.save()

# 表 Article 也有資料了
>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>

# a.reporter 可以賦值給 r
>>> r = a.reporter
>>> r.full_name
'John Smith'

# r 也可以訪問 Article
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>

# 可以藉助 filter() 函式按條件過濾資料
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>

# 賦值後呼叫 save() 函式更新資料
>>> r.full_name = 'Billy Goat'
>>> r.save()

# 使用 delete() 函式刪除物件,資料庫這條資料也會被刪除
>>> r.delete()

自帶 Admin 後臺

一般不會用它。

設計 URLs

我們是通過 URL 傳送請求的,服務端程式做處理,處理的函式叫做回撥函式。Django 在 urls.py 檔案中編寫 URL 和回撥函式的對映關係。例如:

from django.urls import path

from . import views

urlpatterns = [
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<int:pk>/', views.article_detail),
]

path() 的第一引數是 URL,這裡使用了 <> 引數標籤來獲取 URL 中的資料,然後傳入到回撥函式中。第二個引數是回撥函式,位於 views 中。

如果請求 URL “/articles/2005/05/39323/”,Django 就會獲取引數值後呼叫回撥函式:

news.views.article_detail(request, year=2005, month=5, pk=39323)

Django 在啟動載入時就會把這些 path 編譯為正規表示式,查詢速度飛快。匹配到第一個後就會停止查詢,呼叫回撥函式。如果找完了都沒有,就會呼叫 404 這個特殊 view,表示沒找到。

編寫 views

在 views 中編寫回撥函式。每個回撥函式只做 1 件事,要麼返回包含響應的 HttpResponse 物件,要麼丟擲異常,如 Http404 。例如:

from django.shortcuts import render

from .models import Article

def year_archive(request, year):
    a_list = Article.objects.filter(pub_date__year=year)
    context = {'year': year, 'article_list': a_list}
    return render(request, 'news/year_archive.html', context)

return render() 函式會返回一個 HttpResponse 物件。

注意,這個例子用到的是 Django 自帶的模板引擎。所謂模板引擎,就是前端的 HTML 模板,裡面的資料可以寫成變數,從後端動態獲取。除了內建的這個,還有其他模板引擎如 Thymeleaf、FreeMarker 等。不過這些使用都很少了。現在流行前後端分離,後端不需要寫 HTML,只提供 RESTful 介面就可以了。說到 RESTful,就不得不提另外一個 Django 的衍生框架 DRF(Django REST Framework)。一步一步來,先學好了 Django,才能更好理解 DRF。

內建模板引擎

暫時不做介紹。

小結

本文以 Web 後臺為例,講解了從 model,到 ORM,到資料操作,到 URL 對映,到 views 回撥函式的編寫鏈路。實際操作會複雜得多。以前學其他框架有點懵,寫這篇文章,倒是讓我明白了 MVC 這一套是這麼一回事。

參考資料:

https://docs.djangoproject.com/en/3.1/intro/overview/

相關文章