iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 18
0
Modern Web

From Django 1.11 to Django 2.1 系列 第 18

Day18 : Django ModelForm

到目前為止,我們已經了解 Django MVT 的 架構 以及 特色

接下來,我們便能夠延伸這些架構,來讓我們完成更多的事情

回想一下,現今網路這麼蓬勃發展,走到哪裡都可以看到各式各樣的文章及留言,但有時候,一篇文章底下的留言肯定是比文章內容還要精采的,有時候除看留言,你為了要帶動風向,自己也會留下足跡

Anyway ^^"

今天要帶大家來了解如何透過 Django 製作一個 Model Form


[正文開始]

我們先在 vendor/ 建立 forms

from django import forms

from .models import Vendor, Food

class VendorForm(forms.ModelForm):
    class Meta:
        model = Vendor
        fields = '__all__'
        

model : 我要使用哪一個 Model
fileds : 使用 Model 的哪些欄位

建立好之後,再到 views 對這一個 Model Form 做處理

from .forms import VendorForm # 要記得 import 相對應的 Model Form 唷!

# 針對 vendor_create.html
def vendor_create_view(request):
    form = VendorForm(request.POST or None)
    if form.is_valid():
        form.save()

    context = {
        'form' : form
    }
    return render(request, "vendors/vendor_create.html", context)

is_vaild : 建立在 form 底下的方法,可以用來驗證資料是否正確

並到 templates 新增 vendor_create.html

# 為了展示給大家看,這裡的code並不完整
{% extends "base.html" %}
{% block title %} My store {% endblock %}
{% block content%}
<h2> Vendor Create</h2>
<form method='POST'>
  {{ form.as_p }}
<input type="submit" value="save" />
</form>
{% endblock %}

這裡的 form 相信大家不陌生了,它就是透過 views 回傳的 Dict,但是後方的 as_p 是新的夥伴,而它就是 Django 提供給 forms 顯示的一種方式,目前總共有 3 種方式,分別是

  • as_table
  • as_p
  • as_ul

而它所代表的意思便是,我們的 form 要透過 HTML 的 <tr> or <p> or <li> 來裝飾

值得注意的一點是,這個 form 只是方便大家辨識所用,但實際上它並沒有包覆著 標籤,所以這一個部分要自己完成唷!

最後!! 還有一件重要的事情要做,要記得到 urls.py 設定 Route

urlpatterns = [
    path('', views.showtemplate),
    path('create', views.vendor_create_view), # 新增
]

上述的設定都完成之後,到http://127.0.0.1:8000/vendor/create便能看到這樣的畫面
https://ithelp.ithome.com.tw/upload/images/20181018/20111829bvv77FXfmu.jpg

蛤? 不想看到英文,那你可以這麼做 ^^"
修改 forms

from django.utils.translation import gettext_lazy as _ # 新增

class VendorForm(forms.ModelForm):
    class Meta:
        model = Vendor
        fields = '__all__'
        # 新增 labels 對應
        labels = {
            'vendor_name': _('攤販名稱'),
            'store_name' : _('店名'),
            'phone_number' : _('電話'),
            'address' : _('地址'),
        }

如此一來便能夠克服預設是顯示 變數名稱 的問題了!
https://ithelp.ithome.com.tw/upload/images/20181018/20111829woOeOVDJBQ.jpg

接著,你試著 新增 Vendor
https://ithelp.ithome.com.tw/upload/images/20181018/20111829vuDJbI65my.jpg

然後馬上就被 Django 佛逼鄧(forbidden) 了
https://ithelp.ithome.com.tw/upload/images/20181018/20111829FvaN5o3RH6.jpg

原因就是,為了避免發生 CSRF 的攻擊,Django提供了一個簡單的方法可以幫你做驗證

# 新增 {% csrf_token %} 
{% extends "base.html" %}
{% block title %} My store {% endblock %}
{% block content%}
<h2> Vendor Create</h2>
<form method='POST'>
  {% csrf_token %} 
  {{ form.as_p }}
<input type="submit" value="save" />
</form>
{% endblock %}

接著新增 Vendor 就不會有問題了
https://ithelp.ithome.com.tw/upload/images/20181018/20111829R0e6JJve6n.jpg

接著去 http://127.0.0.1:8000/vendor/ 可以看到我們的攤販就成功新增一筆了!
https://ithelp.ithome.com.tw/upload/images/20181018/201118299ZWEY15klN.jpg

但是你會發現,在我們新增 攤販 之後,畫面沒有作任何更動,會讓你開始懷疑.... 我剛剛有新增成功嗎?!

其實是有成功的 ^^ (畢竟我們在 顯示介面 有看到新增一筆資料)

但是後續的動作並沒有處理好,因此,我們應該將成功新增的資料作 清空 的動作

修改 views

def vendor_create_view(request):
    form = VendorForm(request.POST or None)
    if form.is_valid():
        form.save()
        form = VerdorForm() # 清空 form

    context = {
        'form' : form
    }
    return render(request, "vendors/vendor_create.html", context)

除此一來,我們便能夠在新增完資料之後,又能將畫面清空囉 ^^


今天主要透過我們建立的 Model 的模板 來新增一個 Model Form,而它的好處便是,我們能直接對這一個資料庫做處理,而今天我們便完成了 CREATE 的事情!

你說,Django 相當的好用又強大,對吧!

今天我們就講到這裡,明天見~

每天問著自己 : 你想要什麼? 然後一步步前進,逐漸強大 From BY


上一篇
Day17 : Django 插拔性
下一篇
Day19 : Django Form
系列文
From Django 1.11 to Django 2.1 30

1 則留言

0
to790303
iT邦新手 5 級 ‧ 2019-07-27 17:13:22

您好,想請問一下我已經在vendor_create裡面新增了csrf_token這一段,但在網頁上新增店家資訊時,還是顯示forbidden的資訊,請問是為什麼呢?

Lee iT邦新手 5 級 ‧ 2019-08-10 13:21:03 檢舉

給的訊息太少我無法確定,不過我是把{% csrf_token %}打成{{ csrf_token }}

自己在抽絲剝繭檢查一下吧

weilc iT邦新手 5 級 ‧ 2020-03-28 15:02:39 檢舉

我新增 {% csrf_token %} 後一樣無法
再檢查圖中那幾項也是一樣結果
p.s 我是用django 3.0.4

我要留言

立即登入留言