Django Model View Template 之間的簡單交互 (二)

前言

接續前文,上一篇文章主要涉及了 Django 項目的基礎配置等,這篇主要涉及數據庫相關的 ORM ,也就是 Django 中的 Model 的使用,MVT 三層之間的交互html

教程基本都是東拼西湊的,防止有些東西表述不許確,由於我以前寫 JavaScript 比較多。可是裏邊注入了本身的理解,儘可能講清楚。前端

基礎環境

  1. Pycharm 2018
  2. Django 2.0.3
  3. Python 3.6.4
  4. mxonline start 分支

Django Model 配置

代替使用原生的 SQL 語句操做數據庫。python

原生 SQL 語句操做數據庫

# {BASE_DIR}/apps/message/models.py
import MySQLdb
def book_list(request):
    db = MySQLdb.connect(user="me", db="mydb", password="secret", host="localhost")
    cursor = db.cursor()
    cursor.execute('SELECT name FORM books ORDER BY name')
    names = [row[0] for row in cursor.fetchall()]
    db.close()

配置 Django Model

具體的一些細節知識下面會進行敘述。這裏只是展現一下如何配置。mysql

# {BASE_DIR}/apps/message/models.py

# 從 Django 中引入 models
from django.db import models


# Create your models here.
class UserMessage(models.Model):
    name = models.CharField(max_length=20, verbose_name=u"用戶名")
    email = models.EmailField(verbose_name=u"郵箱")
    address = models.CharField(max_length=100, verbose_name=u"聯繫地址")
    message = models.CharField(max_length=500, verbose_name=u"留言信息")

    class Meta:
        verbose_name = u"用戶留言信息"
        verbose_name_plural = verbose_name

model 建立完成,接下來是生成數據表。git

生成數據表

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

而後查看數據庫是否是生成了表。github

以前有十個表,分別是:ajax

+----------------------------+
| Tables_in_test_django      |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+
10 rows in set (0.00 sec)

如今:sql

+----------------------------+
| Tables_in_test_django      |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| message_usermessage        |
+----------------------------+
11 rows in set (0.00 sec)
mysql> desc message_usermessage;
+---------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra          |
+---------+--------------+------+-----+---------+----------------+
| id      | int(11)      | NO   | PRI | NULL    | auto_increment |
| name    | varchar(20)  | NO   |     | NULL    |                |
| email   | varchar(254) | NO   |     | NULL    |                |
| address | varchar(100) | NO   |     | NULL    |                |
| message | varchar(500) | NO   |     | NULL    |                |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.04 sec)

對應上面 Model 中的字段,完美~shell

注意事項

  1. ChartField 必須指定 max_length。

ORM 功能介紹

稍候會有完整的 Model 例子。數據庫

字段 Field

每個模型均可以包含有任意數量的字段,每一個字段都會對應數據表中的一個字段,咱們須要指定字段的屬性。

name = models.CharField(max_length=20, verbose_name=u"用戶名")

上述字段的名稱是 name,類型是 models.CharField。對應到 MySQL 數據中是 varchar 類型。varchar 類型的字段都是須要去指定一個長度值,對應到 Django 的 ORM 模型上就是 max_length 屬性。

字段參數

下面列舉一下目前筆者在開發中用到的一些字段:

  1. max_length:指定字段的長度值,接受一個數字,CharField 必須指定最大長度, TextField 不須要。
  2. verbose_name:字段標籤的可讀名稱,接受一個字符串。若是不指定,Django 會從字段名稱去推斷默認的詳細名稱,建議每個字段都進行指定。
  3. default:字段默認值。
  4. null:是否能夠爲 null,接受 True 或者 False
  5. blank: 是否能夠爲空,一樣接受 True 或者 False
  6. primary_key:若是設置爲 Ture,則該字段置爲模型主鍵,若是模型中沒有指定主鍵,則 Django 會自動爲模型添加一個主鍵,默認爲 id
  7. help_text:爲 HTML 表單文本提供單文本標籤。
  8. choices:一組字段選項,提供這一項的時候,默認對應的表單不見是選擇字段的盒子,而不是標準文本字段。

字段類型

  1. CharField:用來定義短到中等長度的字段字符串,必須指定 max_length 屬性
  2. TextField:用於大型的任意長度字符串,不強制要求指定 max_length 屬性,指定的 max_length 僅僅當該字段以表單顯示纔會使用,不會再數據庫級別進行強制執行。
  3. IntegerField:用於存儲整形數據,在用於表單中驗證輸入的值須要時整數。
  4. FloatField:用於存儲浮點型數據
  5. DateField 和 DateTimeField:用於存儲/表示日期和日期/時間信息(分別是Python.datetime.date和datetime.datetime對象。這些字段能夠另外代表(互斥)參數auto_now=Ture (在每次保存模型時將該字段設置爲當前日期),auto_now_add(僅設置模型首次建立時的日期)和default(設置默認日期,能夠被用戶覆蓋)。通常筆者選擇的默認日期是 datetime.now
  6. EmailField:用來存儲和驗證電子郵件地址。
  7. FileField:用於上傳文件,須要提供 upload_to 指定上傳到的地方。
  8. ImageField:和上傳文件表現基本類似,會額外進行是否爲圖像的驗證。
  9. AutoField:是一種 IntegerField 自增的特殊類型,若是模型沒有指定主鍵的話,此類型的主鍵將自動添加到模型中。
  10. ForeignKey:外鍵,用於指定與另外一個數據庫模型的一對多關係。關係 「一」 側是包含密鑰的模型。和 flask 指定外鍵的方式不一樣。
  11. ManyToManyField:用於指定多對多關係,例如,一本書能夠有幾種類型,每種類型能夠包含幾本書)。在咱們的圖書館應用程序中,咱們將很是相似地使用它們ForeignKeys,可是能夠用更復雜的方式來描述組之間的關係。這些具備參數on_delete來定義關聯記錄被刪除時會發生什麼(例如,值models.SET_NULL將簡單地設置爲值NULL)。筆者用的不是不少。

元數據

經過聲明 class Meta 來聲明模型級別的元數據

class UserMessage(models.Model):
    # Config Field
        
    class Meta:
        ordering = ["id"]
       verbose_name = u"用戶留言信息"
       verbose_name_plural = verbose_name

這裏最有用的功能是能夠指定模型返回數據時候的默認的順序,更多的文檔能夠查看這裏

方法

一個模型也能夠有方法,最基本的使用就是定義一個標準的 Python 類方法: __str__

class UserMessage(models.Model):
    # Config Field
    
    # Config Meta
    
    def __str__(self):
       return self.message

這樣爲每一個對象返回一我的類可讀的字符串。固然還有其餘高級的使用,往後再說

完整的 model

# {BASE_DIR/apps/message/models.py}

from django.db import models


# Create your models here.
class UserMessage(models.Model):
    name = models.CharField(max_length=20, verbose_name=u"用戶名")
    email = models.EmailField(verbose_name=u"郵箱")
    address = models.CharField(max_length=100, verbose_name=u"聯繫地址")
    message = models.CharField(max_length=500, verbose_name=u"留言信息")

    class Meta:
        ordering = ["id"]
        verbose_name = u"用戶留言信息"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.message

使用 Django ORM

以前已經定義好了數據模型的字段(Field)、元數據(Meta)、方法(Method)等。如今要作的是把頁面上提交過來的數據經過 ORM 來存放到數據庫中,經過 ORM 來進行數據的 CURD 操做。

建立數據

templates 中已經建立了 message_form.html 模板文件,如今進行修改,修改 formaction 目標地址:

<form action="/" method="post" class="smart-green">

這裏根據本身配置的 Url 來自行決定,因爲筆者配置的是 /,因此這裏就配置成這個樣子。

這裏指定的是使用 form 的原生事件 post 事件進行提交,可是在實際的開發中,爲了實現更精確的控制,咱們經常不會使用原生事件,而更傾向於使用 ajax 進行提交,固然這裏的重點不是前端的邏輯,重點在於 Django 後端邏輯的處理,顧不贅述。

接下來的任務就是:拿到 POST 發來的數據,而後存入數據庫中。

存儲數據

以前使用 Django 的 ORM 進行了數據庫中數據表的配置,如今使用 Django 的 ORM 將數據保存到數據庫中。

在 Django 中,咱們使用不是傳統的 MVC 架構,咱們使用的是一種叫 MVT 的方式。不一樣的 Template(模板) 呈現不一樣的 View。咱們將在 View(請求視層)中獲取用戶提交的數據,以及將從 Model(數據層) 中得到的數據傳遞給 Template(模板層)

MVT 的概念自己就來自於 Django 框架,下面進行代碼的展現:

# {BASE_DIR/apps/message/views.py}
from django.shortcuts import render  # 引入 render 方法
from .models import UserMessage      # 引入以前配置好的 Model


# Create your views here.

def get_form(request):
    if request.method == 'POST':
        name = request.POST.get('name', '')
        message = request.POST.get('name', '')
        address = request.POST.get('address', '')
        email = request.POST.get('email', '')
        user_message = UserMessage()
        user_message.name = name
        user_message.message = message
        user_message.address = address
        user_message.email = email
        user_message.save()
    return render(request, 'message_form.html')

經過 POST 方法提交的數據會存儲到 request 對象的 POST 屬性下邊,經過 Django 提供的 get 方法就能夠取到對應的字段。其中 get 接收兩個參數,分別是字段的名稱默認值

在取到 Template 提交過來的每個字段以後,就可使用 ORM 提供的方法將其存入數據庫中。

實例化引入的 Model,而後將以前定義的字段進行賦值,而後就能夠調用實例的 save() 方法將數據存入數據庫。

而後就能夠經過 Navicat 或者終端等方式查看數據是否保存到了數據庫中。

讀取數據

以前已經實現了數據的存儲,這部分將實現數據的讀取功能。

# {BASE_DIR/apps/message/views.py}
from django.shortcuts import render
from .models import UserMessage


# Create your views here.

def get_form(request):
    message = None
    all_message = UserMessage.objects.filter(name='test')
    if all_message:
        message = all_message[0]
    return render(request, 'message_form.html', {'my_message': message})

這裏會涉及到 Django 的 QuerySets(查詢集)相關知識,這裏撿着用的着的部分看一下。

首先先聲明 message,值爲 None,用於存儲取到的數據。

從本質上講,QuerySets 是給定對象模型(這裏是 UserModel)的對象列表(list),容許咱們從數據庫中讀取數據,選擇以及排序。經過這種方式操做的話,就能夠避免直接操做數據庫。從而抹平不一樣數據庫操做的差別,這部分由 Django 幫咱們來完成。

上面的代碼中有這樣的一句:

UserMessage.objects.filter(name='test')

做用是從數據庫中查找 name 值爲 test 的全部條目,返回的是一個 <QuerySet> 列表,並賦值給 all_message。同時咱們也能夠發現,QuerySet 能夠鏈式調用。相似於 JavaScript 中的 Promise

而後若是 all_message 不爲空的話,取出列表第一項,而後傳遞給 my_message 模板。

關於 QuerySet 的詳細知識,能夠查看 Django 的官方文檔的這一部分

渲染到模板

在上面步驟中,咱們將符合預設條件的數據從數據庫中取出來,傳遞到模板中,這裏的目標是將數據正確的顯示與渲染。部分語法相似於 ejs 模板的語法,但同時 Django 又在模板中內置了不少經常使用的函數。可是 Django 不像 Java 那樣,容許在模板中寫一些 Java 代碼,Django 的 Template 中不容許將 Python 代碼混進來。

因爲模板代碼過長,這裏只放一些關鍵部分的代碼,完整的代碼能夠查看文章對應的代碼倉庫。

<form action="{% url 'go_form' %}" method="post" class="smart-green">
    <label>
        <span>姓名 :</span>
        <input id="name" type="text" name="name" value="{% if my_message.name == 'test' %}test{% endif %}" class="error"
               placeholder="請輸入您的姓名"/>
    </label>
    <label>
        <span>留言 :</span>
        <textarea id="message" name="message" placeholder="請輸入你的建議">{{ my_message.message }}</textarea>
    </label>
    {% csrf_token %}
</form>

在上一篇文章中,提到過,path 接收 name 參數。在 template 中能夠經過 name 來取到對應的 url,方法以下:

action="{% url 'go_form' %}"

這樣作提供了另外一種獲取 url 的方式,當咱們由於某種緣由去修改了 url 地址以後,經過 name 還能找到它。

textarea 中,有這樣一段代碼:

{{ my_message.message }}

做用是取到傳入的 my_message 對象的 message 屬性取出來並顯示,因爲 html 基本屬於前端部分了,因此用前端的方式進行描述。

雙花括號(八字鬍)語法: {{...}} 在任何模板語言中都很常見,做用是將數據渲染到雙括號內部。

上面還有一部分代碼是這樣子的:

{% if my_message.name == 'test' %}test{% endif %}"

意思很好懂的,是吧。

具體的 Django 中模板的語法能夠查看官方文檔。

後記

這裏只是簡單的介紹了一下 Django 中 Model 層、View 層、以及 Template 層之間交互的部分知識,很簡略,不詳細。在每部分的後邊都附加了詳細的官方文檔地址。若是之後有時間了能夠對每部分進行詳細的闡述。

參考資料

  1. Python升級3.6 強力Django+殺手級Xadmin打造在線教育平臺
  2. MDN 的 Django教程 ———— 設計LocalLibrary模型
  3. Django 官方文檔 Model 部分
  4. Django Girls 教程
相關文章
相關標籤/搜索