1. 程式人生 > >Django搭建部落格(八):進階:form與 model配合使用

Django搭建部落格(八):進階:form與 model配合使用

一、使用情景

在我們的後臺管理頁面中需要一個表單來提交和修改部落格,按照上一篇講的,我們可以這麼使用:

先定義一個 Form類,包括標題、標籤和內容三個欄位:

class ArticleForm(forms.Form):
    title = forms.CharField(label='標題', max_length=50)
    tags = forms.CharField(label='標籤', max_length=50)
    content = TextFiled(label='內容')

然後在頁面中就可以直接使用 form,在提交表單時,我們還需要將各個欄位賦值給 model的對應欄位。

在修改文章的頁面我們需要先將表格填充好,再渲染頁面。

這時我們的表單還只有幾個欄位,工作量並不大,但是如果表單的欄位增加到十幾個,工作量就有點大了。

幸好 Django為我們提供了 ModelForm 類,可以根據已存在的 Model類來自動地建立 Form 類。

二、使用 ModelForm

使用 ModelForm 很簡單,我們只需要建立一個元類並給對應的屬性賦值即可,如下:

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'tags', 'content']

我們可以通過 fields 來確定需要輸入的欄位,也可以通過 exclude 來設定不需要輸入的欄位。

這樣當我們提交表單之後,只需要呼叫 ArticleFormsave 方法即可將新增的部落格儲存到資料庫中去。

不過我們這裡有兩個欄位沒有新增到 form表單中去,所以在呼叫 save 方法時會報錯,這時只需過載 save 方法即可:

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'tags', 'content']
    
    def save(self, commit=True):
        key = abs(hash(self.instance.title))
        date = datetime.datetime.now().strftime('%Y-%m-%d')
        self.instance.key = key
        self.instance.date = key
        
        self.instance.save()
        
        return self.instance

在檢視函式中我們可以這樣使用:

def addArticle(request):
    if request.method == 'GET':
        form = ArticleForm()
        return render(
            request,
            'myblog/add_article.html',
            {'pagedata':
                 {'form':form}
            }
        )
    elif request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('article_list'))
        else:
            return render(
                request,
                'myblog/add_article.html',
                {'pagedata':
                     {'form': form}
                }
            )

在編輯文章的頁面,我們可以直接將查詢到的 Post 類傳遞給 ArticleForminstance 引數。

instance 引數將會賦值給 ArticleForminstance 屬性,我們上面過載 save 方法時就用到了 instance 屬性。

def modifyArticle(request, key):
    if request.method == 'GET':
        post_list = Post.objects.filter(key=key)
        if len(post_list) == 0:
            return HttpResponse('文章不存在')
        else:
            article_form = ArticleForm(instance=post_list[0])

            ... ...

如果想指定某個欄位的樣式,可以通過 Meta 類的 widgets 屬性來指定,如下:

class TagInput(widgets.Input):
    input_type = 'text'
    template_name = 'myblog/widgets/input.html'

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'tags', 'content']
        
        widgets = {
            'tags': TagInput
        }

    def save(self, commit=True):
        ... ...

我們來看看效果:

8516750-2ca418855e6a352d.PNG