天天看點

django 快速入門

Django是Python語言編寫的一個全棧式Web架構,可以幫助我們快速編寫一個具有資料庫功能、增删查改、背景管理等功能的網站。假如你隻需要一些很簡單的功能,使用flask可能是個更好的選擇。但是如果你想快速實作一個XX管理系統,那麼用Django絕對是個好辦法。本文參考了Django官方文檔的 Tutorials 。另外我這裡用的終端是Powershell,如果有些指令不能運作,去掉前面的

.\

快速開始

安裝Django

首先安裝Django包,現在Django已經到了2.0版本,如果還在使用1.11請盡快更新。舊版本以後隻修複bug,不會添加新功能。

pip install django
           

建立項目

Django安裝好之後,會附帶一個指令行工具

django-admin

,可以幫助我們管理Django項目。我們可以使用下面的指令建立一個新的Django項目模闆。這樣會建立

django_sample

檔案夾,項目檔案就在其中。另外需要注意項目檔案夾最好是個性化一點的,不要和django、sys這樣的第三方庫或者python系統庫重名。

django-admin startproject hello_django
           

建立好項目之後,我們進入項目檔案夾中。用下面的指令就可以運作Django項目了。預設情況下,我們可以通過

http://127.0.0.1:8000/

來通路正在運作的項目。由于沒有任何頁面,是以會顯示這麼一個調試視窗。

python manage.py runserver
           
django 快速入門

運作成功

建立app

在Django項目中,app表示更小的一個功能機關,比方說在一個部落格管理系統中,對部落格的增删查改等功能就應該聚合在一個app中。進入項目目錄中,用

startapp

指令建立app。

cd .\hello_django\
django-admin startapp hello
           

這時候項目目錄結構應該類似這樣。

django 快速入門

目錄結構

為了讓django包含建立的app,我們還需要激活app。打開配置檔案,找到

INSTALLED_APPS

,然後把我們建立的app配置添加進去,這樣django才能使用我們的app。

INSTALLED_APPS = [
    'hello.apps.HelloConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
           

模型層

設定資料庫

打開配置檔案

settings.py

,找到資料庫一行,可以看到如下的配置。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
           

如果我們這時候使用

python .\manage.py migrate

指令生成資料庫表,就會在項目中出現一個

db.sqlite3

檔案,這就是預設的資料庫檔案,使用IDEA右鍵點選并選擇

As DataSource

就可以将其作為資料庫打開。然後我們會看到生成了10多個資料庫表,這是Django程式存儲資料生成的表。

django 快速入門

django系統表

除了sqlite資料庫,django還支援POstgreSQL、MySQL、Oracle這幾個資料庫。如果添加第三方後端支援,還可以使用SQL Server、IBM DB2等資料庫。例如我現在準備使用PostgreSQL資料庫,就修改為下面的配置。這時候NAME屬性的意義就是資料庫的名字。另外必須確定資料庫事先存在,django可以自動建立表,但是不能自動建立資料庫。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'test',
        'USER': 'postgres',
        'PASSWORD': '12345678',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}
           

建立模型

django支援ORM模型,也就是說我們可以不使用SQL語句就對資料進行增删查改。我們要做的就是在模型中指定和資料庫的關系。

打開hello app中的

models.py

檔案,然後添加下面兩個模型。這兩個模型是寵物和主人的關系。如果使用過其他ORM架構比如Hibernate之類的話,對這種結構應該非常熟悉。我們在定義模型的時候指定每一個字段的名字、長度、是否唯一等資訊。值得注意的是,如果需要的值隻可能是幾個固定值,可以定義一個元組(該元組有一對值構成,第一個值是實際存在資料庫中的值,第二個是給人類顯示的友好可讀值),然後傳入

choices

參數。

models.ForeignKey

用來指定外鍵限制,還有一些其他的對應關系例如多對多、一對一等就不介紹了。

from django.db import models

class Owner(models.Model):
    GENDER = (
        ('M', 'MALE'),
        ('F', 'FEMALE')
    )
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=30, unique=True)
    gender = models.CharField(max_length=1, choices=GENDER)
    birthday = models.DateField()


class Pet(models.Model):
    TYPE = (
        ('C', 'Cat'),
        ('D', 'Dog')
    )
    id = models.AutoField(primary_key=True)
    owner = models.ForeignKey(Owner, on_delete=models.CASCADE)
    name = models.CharField(max_length=50)
    type = models.CharField(max_length=1, choices=TYPE)

           

生成并應用遷移檔案

上面我們建立了兩個模型,實際上,隻要我們對模型進行了更改,就應該使用下面的指令生成這些更改。

python manage.py makemigrations hello
Migrations for 'hello':
  hello\migrations\0001_initial.py
    - Create model Owner
    - Create model Pet
           

并且在

migration

檔案夾中生成了對應的遷移檔案。

如果想知道遷移檔案會具體生成什麼樣的SQL語句,可以調用下面的指令。這裡的序号是遷移序号,每次對模型進行更改都會生成一個新的遷移檔案,想檢視哪個檔案生成的SQL語句,就指定哪個序号。

python manage.py sqlmigrate hello 0001
           

結果應該類似下面這樣。

BEGIN;
--
-- Create model Owner
--
CREATE TABLE "hello_owner" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(30) NOT NULL UNIQUE, "gender" varchar(1) NOT NULL, "birthday" date NOT NULL);
--
-- Create model Pet
--
CREATE TABLE "hello_pet" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(50) NOT NULL, "type" varchar(1) NOT NULL, "owner_id" integer NOT NULL REFERENCES "hello_owner" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "hello_pet_owner_id_a7d7b3df" ON "hello_pet" ("owner_id");
COMMIT;
           

當然這隻是生成了遷移檔案,并沒有真正應用到資料庫中。如果要引用到資料庫,再次使用migrate指令即可。這時候再次檢視資料庫,就會發現多了hello_owner和hello_pet兩個表,正好對應我們的兩個模型。

python manage.py migrate
           

資料操作

用下面的指令打開django Shell。

python manage.py shell
           

如果不想使用指令,也可以設定

DJANGO_SETTINGS_MODULE

環境變量的項目的

settings.py

檔案,然後在python解釋器中設定django shell。

>>> import django
>>> django.setup()
           

不管是用哪種方法,都可以打開shell,在這裡面就可以使用API操作資料了。首先引入我們的模型。

In [1]: from hello.models import Owner, Pet
           

增加一些資料。

In [4]: o1=Owner(name='zhang3',birthday='1992-5-7',gender='M')
In [5]: o1.save()
In [6]: o2=Owner(name='limei',birthday='1996-6-8',gender='F')
In [7]: o2.save()
In [8]: p1=Pet(owner=o1,name='lele',type='D')
In [9]: p1.save()
           

下面是一些查詢例子,get函數查詢單個模型,filter函數查詢多個模型,all函數查詢所有模型。

In [7]: Pet.objects.all()
In [8]: Pet.objects.get(id=1)
In [11]: Owner.objects.get(name='zhang3')
In [14]: Owner.objects.filter(gender='M')
In [18]: Owner.objects.count()
           

上面的隻能執行精确查找某個字段,如果需要更複雜的可以使用雙下劃綫加查詢謂詞的形式。詳細文檔參考

https://docs.djangoproject.com/en/2.0/topics/db/queries/#field-lookups-intro
In [20]: Owner.objects.filter(name__startswith='z')
In [22]: Owner.objects.filter(birthday__year__lte='1994')
In [30]: Owner.objects.filter(name__contains='5')
           

删除某個對象。

In [31]: p2.delete()
           

為了調試更友善,我們還可以在這兩個模型上添加str函數。這樣調試的時候就更加易讀了。

class Owner(models.Model):

    def __str__(self):
        return f'Owner(id:{self.id}, name:{self.name}, gender:{self.gender}, birthday:{self.birthday}'


class Pet(models.Model):

    def __str__(self):
        return f'Pet(id:{self.id}, name:{self.name}, type:{self.type}'
           

Django Admin

Django Admin可以幫助我們快速管理背景資料。首先需要建立一個管理者賬戶。

python manage.py createsuperuser
           

建立完成後,通過

http://127.0.0.1:8000/admin/

通路管理者界面并輸入剛才設定的管理者和密碼,會看到如下的界面。

django 快速入門

管理者界面

這裡目前什麼都沒有,我們需要将模型注冊到Admin中。打開

admin.py

檔案,輸入下面的内容。

from django.contrib import admin

# Register your models here.
from .models import Owner, Pet

admin.site.register(Owner)
admin.site.register(Pet)

           

這樣一來,就可以在管理者界面中管理模型了。

django 快速入門

管理模型

頁面和視圖

路由

首先在app的

views.py

中添加一個新的視圖。不過按照Spring MVC的分層,我覺得這裡的這些視圖叫控制器似乎更合理一些,不過既然這個檔案都叫做view,那麼我也叫它視圖吧。

from django.http import HttpResponse

def index(request):
    return HttpResponse('hello')

           

然後在app中建立一個

urls.py

檔案,寫入以下内容。

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
]
           

然後在項目的

urls.py

檔案中添加app中設定的路徑,除了admin頁面的路徑之外,其他路徑都應該使用include函數引入。

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', include('hello.urls'))
]
           

然後通路

http://127.0.0.1:8000/hello/

,應該就可以看到顯示的字元串了。

路徑參數

如果路由是帶路徑參數的,那麼使用

<類型:變量名>

文法。

urlpatterns = [
    path('', views.index, name='index'),
    path('hello/<str:name>', views.hello, name='hello')
]
           

對應的參數作為視圖函數的第二個參數。

def hello(request, name):
    return HttpResponse(f'hello, {name}')
           

這樣,通路

http://127.0.0.1:8000/hello/hello/yitian

就可以看到對應的輸出了。

使用模闆

在app中建立

templates/hello

檔案夾,然後在其中建立

index.html

檔案,檔案内容如下。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>首頁</title>
</head>
<body>
<h1>Hello,{{ name }}</h1>
</body>
</html>
           

然後修改view.py檔案,将hello視圖修改為下面的樣子。再次通路就可以看到這次成功的傳回了網頁。

from django.http import HttpResponse
from django.template import loader

def hello(request, name):
    template = loader.get_template('hello/index.html')
    context = {'name': name}
    return HttpResponse(template.render(context, request))
           

django還提供了快捷render函數可以簡化這個傳回模闆的常見過程。

from django.http import HttpResponse
from django.shortcuts import render

def hello(request, name):
    context = {'name': name}
    return render(request, 'hello/index.html', context)
           

有些同學可能有疑問,為什麼模闆檔案夾中還要在建立一個hello子檔案夾呢?這是由于django的檔案搜尋機制所導緻的。當搜尋模闆檔案的時候django會從所有app的templates檔案夾中搜尋,但是并不會區分它們,是以如果在多個app中有相同的檔案名,django會使用找到的第一個。是以為了區分它們我們隻能自己多建立一層檔案夾用于區分。

和flask一樣,django預設使用Jinja2模闆,關于jinja2的文法請查閱相關文檔,這裡就不在詳細說明了。

頁面中使用URL

當我們在頁面中需要使用路徑的時候,不要寫死路徑,最好使用url标簽。例如下面這樣的。

<a href="{% url 'hello' '張三' %}">你好,張三</a>
           

這裡url标簽中指定的名稱是urls.py檔案中路徑的name參數。

path('hello/<str:name>', views.hello, name='hello')
           

當項目中存在多個app的時候,需要使用命名空間來區分。做法很簡單,在urls.py檔案中添加app_name屬性。

app_name = 'hello'
urlpatterns = [
    path('', views.index, name='index'),
    path('hello/<str:name>', views.hello, name='hello')
]
           

然後在标簽上添加用冒号分隔開的命名空間名稱即可。

<a href="{% url 'hello:hello' '張三' %}">你好,張三</a>
           

擷取表單參數

在頁面中添加如下一個表單。

{% csrf_token %}

标簽是django内建的功能,可以幫助我們防止csrf攻擊。

<form action="{% url 'hello:form' %}" method="post">
    {% csrf_token %}
    <label for="name">name</label>
    <input type="text" name="name" id="name">
    <br/>
    <label for="male">male</label>
    <input type="radio" name="gender" value="male" id="male">
    <label for="female">female</label>
    <input type="radio" name="gender" value="female" id="female">
    <br>
    <label for="age">age</label>
    <input type="text" name="age" id="age">
    <br>
    <input type="submit" value="submit">
</form>
           

然後添加下面一條路徑。

path('form', views.get_form, name='form')
           

最後添加處理函數,這個處理函數很簡單,僅僅傳回結果文本。需要擷取參數的時候,直接用request.POST即可,它是一個類似字典的對象,我們可以通過鍵來通路對應參數的值。

def get_form(request):
    form = request.POST
    return HttpResponse(f"name:{form['name']}, gender:{form['gender']}, age:{form['age']}")
           

靜态檔案

app内靜态檔案

對于樣式表等靜态檔案,如果是位于app内的,不需要額外設定。隻要在app内建立static檔案夾并将靜态檔案放入即可。之後在頁面中引用的時候添加下面的标簽即可。注意在使用static标簽之前,需要用

{% load static %}

加載它。

{% load static %}
    <link rel="stylesheet" href="{% static 'site.css' %}">
           

檔案結構類似下圖。

django 快速入門

靜态檔案結構

需要注意的是,由于前面介紹的django檔案搜尋機制,在靜态檔案夾中,我們最好在指定一級和app同名的檔案夾用來區分不同app間的靜态檔案。

項目公用靜态檔案

有些靜态檔案可能是多個app公用的,這時候需要進行一點額外設定。首先在和app同級的目錄建立static檔案夾并将靜态檔案放入。然後在配置檔案中添加額外的搜尋路徑配置。

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
]
           

還是由于django檔案搜尋機制,我們最好在靜态目錄中添加一個public子檔案夾和其他靜态檔案區分。

測試

django支援自動化測試,可以幫助我們快速查找bug。測試檔案應該寫到tests.py檔案中。下面是一個簡單的例子。

from django.test import TestCase


class SampleTest(TestCase):
    def test_true(self):
        self.assertTrue(True, 'is true')
           

TestCase基類含有各種斷言方法,可以幫我們進行判斷,這裡就不列舉了。

要運作測試的話,使用下面的指令。可以看到django還會自動建立和删除測試資料庫,非常友善。

PS D:\kang\PycharmProjects\python-study\hello_django> python .\manage.py test hello
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.015s

OK
Destroying test database for alias 'default'...
           

以上就是一點對于django架構的介紹。希望大家在看完之後可以對django架構有一些基本了解。本來我是準備照着官方文檔的教程來寫的,但是寫了一半感覺教程内容太多,沒辦法放到一篇文章中。是以就寫成了這麼一個虎頭蛇尾的文章。之後有時間我會慢慢寫文章,仔細介紹django的各個方面的内容。

下一篇: JUnit 5 簡介