利用Django通用類視圖(class-based view)編寫數據驅動(ModeForm)WEB程序整理

最近在學習Django,官方文檔介紹地十分詳細。可是「大而全」就不免會有些不夠速成,和咱們這個浮躁的互聯網時代格格不入,因此我就整理了這個文檔。就像coolshell說的,一泡屎的時間就能夠看完。css


框架的好處就是,它已經爲用戶處理了絕大多數的場景中的重複代碼,提供了封裝好的接口,使得咱們在開發中十分方便。在web開發中,咱們經常遇到的一個場景就是:頁面發起一個請求,後端執行相應的處理(修改數據、查詢數據、插入數據等操做),再予以返回。html

對於這些場景,Django提供了幾個class-based view來處理:python

  • ListViewweb

  • UpdateViewshell

  • CreateView數據庫

  • DeleteViewdjango

這幾個類視圖分別對應着查詢ListView、更新UpdateView、建立CreateView、刪除DeleteView這幾個操做。在總體上就能夠分爲查看、修改兩個類型。下面,咱們來經過一個例子來展示一下這幾個View怎麼使用。假設咱們須要實現一個用於ssh驗證的web服務。用戶經過頁面能夠新建、查看、修改用於ssh登錄驗證的內容(user、port、password、key)。bootstrap

Model

既然是數據驅動的WEB,首先就必需要有數據。
針對於咱們的需求,數據庫設計以下:segmentfault

class SSHAuth(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50, unique=True)
    password = models.CharField(max_length=50, blank=True)
    privateKey = models.FileField(upload_to='sshKey', blank=True)
    user = models.CharField(max_length=30, blank=True)
    port = models.IntegerField(blank=True)

    # python3用__str__
    def __unicode__(self):
        return u'%s' % self.name

這裏涉及到文件上傳,想要了解能夠參考個人另外一篇整理文檔後端

查詢視圖

ListView

對應官網文檔
首先,從最簡單的展現開始。ListView能夠經過你給出的model以及想要展現的model中的field,在對應的數據庫中查詢出對應的對象存放在List對象中,並傳遞給template渲染。這個view只實現了get方法,它只接受get請求。也符合它用於查看數據的需求。在代碼中,咱們只須要指定它對應的模板,對應的model就能夠了。

view

from django.views.generic.edit import CreateView


class SSHAuthListView(ListView):

    template_name = 'app_name/sshauth_list.html'
    model = SSHAuth

說明:
上面我沒有給出filed的值,默認就是SSHAuth這個model中的全部filed都將被展現。
其實template_name也能夠不特別給出。若是你在Django設置settings.py中的TEMPLATES下配置了'APP_DIRS': True 的話,Django默認會去渲染/project/app_name/templates/app_name/sshauth_list.html這個文件。

url

from django.conf.urls import patterns, url
from .view import SSHAuthListView
urlpatterns = patterns('',
    url(r'^sshAuth/$', SSHAuthListView.as_view(), name='listSSHAuth'),

template

<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Password</th>
            <th>PrivateKey</th>
            <th>User</th>
            <th>Port</th>
        </tr>
    </thead>
    <tbody>
    {% for item in object_list %}
        <tr>
            <td>{{ item.id }}</td>
            <td>{{ item.name }}</td>
            <td>{{ item.password }}</td>
            <td>{{ item.privateKey }}</td>
            <td>{{ item.user }}</td>
            <td>{{ item.port }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>

說明:
模板中的object_list對象就是view從model中取出的數據。以list的類型存儲着全部數據instance。這個'object_list'的變量名是Django默認提供的,也能夠人爲修改成你想要的變量名,詳細請看官網文檔。


修改視圖

接下來就是第二類修改視圖了。在web開發中約定俗成的規則是,對於查詢類的請求用get,對於修改類的請求用post。Django在設計的時候也遵循了這個原則,因此如下的每一個view中,都具備支持get和post的函數。

CreateVIew:

  • get——根據model提供一個空form

  • post——接收從get發來的請求,數據合法性校驗,插入數據庫

UpdateView:

  • get——根據model從數據庫取出實例,並渲染form

  • post——接收從get來的請求,數據合法性校驗,並更新數據庫

CreateView

對應官網文檔

view

class SSHAuthCreateView(CreateView):

    template_name = 'app_name/ssh_create.html'
    model = SSHAuth
    success_url = reverse_lazy('app_name:listSSHAuth')

說明:
model就是對應的數據庫,在get請求發送過來的時候,Django會根據model裏的字段個數、類型渲染form。而在post請求發送過來的時候,Django會根據model裏的field屬性去作合法性校驗(類型是否正確、字段是否必填等),在校驗成功之後重定向至success_url。

像上面的SSHAuthCreateView直接取model裏面的數據,在password輸入的時候input的type默認取的是text(由於model爲CharField)。可是咱們想要它是一個password的type。或者你想給它加入class屬性,用於指定css。這樣的話,就要自定製form。能夠本身寫一個form_class,而後在CreateView裏面添加這個form_class。

form

from django import forms
from .models import SSHAuth, Inventory


bootstrap_form_css_class = {"class": 'form-control'}

class SSHAuthBootstrapForm(forms.ModelForm):
    """
    Use Bootstrap css.
    An abstract base class.
    """
    class Meta:
        model = SSHAuth
        fields = ['name', 'password', 'privateKey', 'user', 'port']
        # add html class attribute to form's component.
        widgets = {
            'name': forms.TextInput(attrs=bootstrap_form_css_class),
            'password': forms.PasswordInput(attrs=bootstrap_form_css_class),
            'privateKey': forms.ClearableFileInput(attrs=bootstrap_form_css_class),    
            #ClearableFileInput提供對UpdateView的clear支持
            'user': forms.TextInput(attrs=bootstrap_form_css_class),
            'port': forms.TextInput(attrs=bootstrap_form_css_class),
        }

說明:
fields字段爲想要展現的字段,由於id是自增的主鍵,因此不作修改。widgets爲form的字段類型以及html屬性。其中的PasswordInput會將form中的該字段設爲password類型;而ClearableFileInput則是帶有清除文件功能的類型。

這樣,只須要在view當中加入這個form_class就能夠實現模板中渲染的form表單具備自定義的屬性了:

class SSHAuthCreateView(CreateView):

    template_name = 'app_name/ssh_create.html'
    form_class = SSHAuthBootstrapForm
    success_url = reverse_lazy('app_name:listSSHAuth')

url

url(r'^sshAuth/createItem/$', SSHAuthCreateView.as_view(), name='createSSHAuth'),

template

<form role="form" method="post" enctype="multipart/form-data" action="{% url 'app_name:createSSHAuth' %}">
    {% csrf_token %}
    {% for field in form %}
        {% if field.errors %}
            <div class="form-group has-error" >
        {% else %}
            <div class="form-group">
        {% endif %}
            {{ field.label_tag }}
            {{ field }}
        {% for error in field.errors %}
            <span class="label label-danger">{{ error }}</span>
        {% endfor %}
            </div>
    {% endfor %}
        <button type="submit" class="btn btn-primary">{% block btn_name %}{% endblock %}</button>
</form>

html

生成的html代碼以下:

<form role="form" method="post" enctype="multipart/form-data" action="/app_name/createItem">
            <input type='hidden' name='csrfmiddlewaretoken' value='*****' />
            
            
            <div class="form-group">
            
                <label for="id_name">Name:</label>
                <input class="form-control" id="id_name" maxlength="50" name="name" type="text" />
                
            </div>
            
            
            <div class="form-group">
            
                <label for="id_password">Password:</label>
                <input class="form-control" id="id_password" maxlength="50" name="password" type="text" />
                
            </div>
            
            
            <div class="form-group">
            
                <label for="id_privateKey">PrivateKey:</label>
                <input class="form-control" id="id_privateKey" name="privateKey" type="file" />
                
            </div>
            
            
            <div class="form-group">
            
                <label for="id_user">User:</label>
                <input class="form-control" id="id_user" maxlength="30" name="user" type="text" />
                
            </div>
            
            
            <div class="form-group">
            
                <label for="id_port">Port:</label>
                <input class="form-control" id="id_port" name="port" type="text" />
                
            </div>
            
            <button type="submit" class="btn btn-primary">Create</button>
        </form>

在渲染的時候,Django已經自動根據model、form_class自動處理了form的全部字段。包括type name id maxlength等屬性。


剩下的UpdateView以及DeleteView與CreateView的實現也是相相似的原理。須要注意的就是在view代碼中,即便是指定了form_class字段,並且form_class中也有指定model,可是仍是須要在view代碼裏給出model。具體實現再也不贅述。

相關文章
相關標籤/搜索