iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 26
0
Modern Web

From Django 1.11 to Django 2.1 系列 第 26

Day26 : Django - CBV (續)

Day25 所提到的 Class-Based Views (CBV),我們知道如何透過 Django 提供的模板來更快速地完成我們想要的網頁,今天我們就再繼續來聊聊 CBV 其他的模板吧!

今天要介紹的有

  • CreateView
  • UpdateView

廢話不多說,就讓我們直接進入主題吧 ^^


CreateView

首先,我們先在 views.py 建立一個 VendorCreateView:

from django.views.generic import CreateView
class VendorCreateView(CreateView):
    # form_class = VendorModelForm
    model = Vendor
    fields='__all__'
    template_name = 'vendors/vendor_create.html'

而我們建立的這一個 View 的方法有種 :

  • model + fields : 透過 我們所想要使用的 資料資料欄位來建立表格,透過我上面的範例,可以建立如下圖的view
    https://ithelp.ithome.com.tw/upload/images/20181026/20111829mi59RoDhGY.jpg
    如果把 fields 改成
fields= ['vendor_name', 'store_name']

https://ithelp.ithome.com.tw/upload/images/20181026/20111829PAFcQCMkxh.jpg
相信大家就一目瞭然了吧 ^^
下會附上 model 及 template 程式碼 供大家對照上面的範例

# model - Vendor
class Vendor(models.Model):
	vendor_name = models.CharField(max_length = 20) # 攤販的名稱
	store_name = models.CharField(max_length = 10) # 攤販店家的名稱
	phone_number = models.CharField(max_length = 20) # 攤販的電話號碼
	address = models.CharField(max_length = 100) # 攤販的地址
    ...略

# template - vendor_create.html
{% 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 %}

還有不要忘記了 urls.py 的設定!

from .views import (
    ...略
    VendorCreateView,
)
app_name = 'vendors'
urlpatterns = [
    path('', VendorListView.as_view(), name='index'),
    path('<int:pk>/', VendorDetailView.as_view(), name='vendor_id'),
    path('create/', VendorCreateView.as_view(), name='create'), # 新增
    ...略
]
  • form_class : 我們也可以透過綁定 ModelForm 的方式來更簡化撰寫的過程

更明確的說法是,其實 model 及 fields 這兩者都已經在 ModelForm 就已經撰寫完畢了,等於是你可以直接套用 ModelForm 的格式,這樣子的好處是更方便我們維護

此時我們的程式碼可以修改成這樣,VendorModelForm於下方供大家參考

# CreateView
class VendorCreateView(CreateView):
    form_class = VendorModelForm
    # model = Vendor
    # fields= ['vendor_name', 'store_name']
    template_name = 'vendors/vendor_create.html'
    
# modelForm 
class VendorModelForm(forms.ModelForm):
    class Meta:
        model = Vendor
        fields = '__all__'
            # fields = (
            #         'vendor_name',
            #         'store_name',
            #         'phone_number',
            #         'address',
            # )
        labels = {
            'vendor_name': _('攤販名稱'),
            'store_name' : _('店名'),
            'phone_number' : _('電話'),
            'address' : _('地址'),
        }

如此一來,短短的幾行程式碼,就能夠完成我們大部分的事情
https://ithelp.ithome.com.tw/upload/images/20181026/20111829oHtBXNNW1f.jpg

然後我們馬上就來新增資料吧! 然後這裡示範一個錯誤給大家了解
https://ithelp.ithome.com.tw/upload/images/20181026/201118293ZsOVLCgRU.jpg

在我們資料進行驗證,成功並儲存了之後,你必須要告訴它要轉到哪一個網址,所以在 model 必須定義 get_absolute_url(self)

# model - vendor
def get_absolute_url(self):
		return reverse("vendors:vendor_id", kwargs={"id": self.id})

我們再次試著儲存資料
https://ithelp.ithome.com.tw/upload/images/20181026/201118291gVDsxqqOk.jpg

然後就會成功轉到`127.0.0.1/int:pk/去囉 ^^
https://ithelp.ithome.com.tw/upload/images/20181026/20111829cEG7m61eXK.jpg

UpdateView

有了CreateView,要完成一個簡易的 UpdateView 會相當的簡單,我們一樣在 views.py 新增 VendorUpdateView

# from django.views.generic import UpdateView # 新增
class VendorUpdateView(UpdateView):
    form_class = VendorModelForm
    template_name = 'vendors/vendor_create.html'
    queryset = Vendor.objects.all() # 這很重要

之所以要加上 queryset 的原因是因為

UpdateView 會呼叫 get_object()

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(BaseUpdateView, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(BaseUpdateView, self).post(request, *args, **kwargs)

但是 CreateView 並不會呼叫 get_object()

    def get(self, request, *args, **kwargs):
        self.object = None
        return super(BaseCreateView, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = None
        return super(BaseCreateView, self).post(request, *args, **kwargs)

要更了解 Django 內建的類別,就要開始看 Source code,這些都是 one-time pain,有機會就把類別拿起來看吧 ^^

接著再將 urls.py 加入此行即可

from .views import (
    ...略
    VendorUpdateView,
)
app_name = 'vendors'
urlpatterns = [
    ...略
    path('<int:pk>/update/', VendorUpdateView.as_view(), name='update'), # 新增
    ...略
]

如此一來就能夠修改view囉!
https://ithelp.ithome.com.tw/upload/images/20181026/20111829Op64rw0782.jpg


本日小節

今天延後昨天的議題 CBV,CBV固然方便,但是因為繼承了很多類別,所以想要更深入的了解如何操作,就勢必要去看 Source code囉!

希望今天的內容對你有幫助 ^^ 我們明天見

哪怕路再長,哪怕受再多的傷,哪怕前方有阻擋,也要照亮 From 南西肯恩


上一篇
Day25 : Django Class-Based Views (CBV)
下一篇
Day27 : CBV vs. FBV
系列文
From Django 1.11 to Django 2.1 30

尚未有邦友留言

立即登入留言