Django之form進階和ModelForm

一.form進階

1.字段批量添加樣式:

def __init__(self,*args,**kwargs):
    super(BookForm,self).__init__(*args,**kwargs)
    for field in self.fields.values():
        field.widget.attrs.update({'class':'form-control'})
解釋:
	1.fields.values:所有的值  字段名是key 
	2.widget.attrs.update :字典中更新一條記錄

2.form版本圖書管理系統:
校驗類BookForm:

from django import forms
class BookForm(forms.Form):
    title = forms.CharField(
        max_length=32,
        min_length=12,
        label='書名',
        )
    publishDate = forms.DateField(
        label='出版日期',
        widget=forms.widgets.TextInput(attrs={'type':'date'})
    )
    price = forms.DecimalField(
        max_digits=5,
        decimal_places=2,
        label='價格',

    )
    publishs = forms.ModelChoiceField(  #如果想用數據庫中數據進行展示需要用model
        label='出版社',
        queryset=app02.models.Publish.objects.all(),  #直接把所有數據查出來
        widget=forms.widgets.Select()
    )
    authors = forms.ModelMultipleChoiceField(  
        label='作者',
        queryset=app02.models.Author.objects.all(),
        widget=forms.widgets.SelectMultiple(),
    )

前端頁面:
在這裏插入圖片描述
視圖函數中:

添加書籍:

# 添加數據
def add_book(request):
    if request.method == 'GET':
        book_forms = BookForm()
        return render(request, 'many_test/book_add.html', {'book_forms':book_forms})
    else:
        book_forms = BookForm(request.POST)
        if book_forms.is_valid():
            print(book_forms.cleaned_data)  #通過的數據
            authors = book_forms.cleaned_data.pop('authors')  #將多對多的數據取出來
            new_book = app02.models.Book.objects.create(**book_forms.cleaned_data)
            new_book.authors.add(*authors) #保存多對多的關係
            return redirect('app03:show_book')
        else:
            print(book_forms.errors)  #錯誤信息
            return render(
            request, 'many_test/book_add.html',
             {'book_forms': book_forms}) #如果有錯誤將頁面再返回 此時book_forms是有值的

		#以前的寫法:
        # authors = request.POST.getlist('authors')
        # all_data = request.POST.dict()
        # del all_data['csrfmiddlewaretoken']
        # del all_data['authors']
        # book_obj = app02.models.Book.objects.create(**all_data)
        # book_obj.authors.add(*authors)
        # return redirect('app03:show_book')

展示書籍:

# 展示書籍
def show_book(request):
    start = 0
    book_list = app02.models.Book.objects.all() 
    paginator = Paginator(book_list, 2)  # 創建一個panginator對象
    page = request.GET.get('page', 1)
    currentPage = int(page)
    if currentPage != 1:
        start = (currentPage - 1) * 2
    try:
        book_list = paginator.page(page)
    except PageNotAnInteger:
        book_list = paginator.page(1)  # 這個是對你的分頁的數據進行取值  去除你的分頁過後的第一頁
    except EmptyPage:
        book_list = paginator.page(paginator.num_pages)  # 分頁數
    return render(
        request, 'manytable/show_book.html',
        {'paginator': paginator, 'book_list': book_list, 'currentPage': currentPage, 'start': start})

編輯書籍:

# 編輯書籍
def edit_book(request, book_id):
    book_obj = app02.models.Book.objects.filter(pk=book_id)
    print(book_obj.values())
    if request.method == 'GET':
        book_forms = BookForm(book_obj.values()[0])
        return render(request, 'many_test/book_edit.html', {'book_forms': book_forms,'book_obj':book_obj})
    else:
        pass

編輯書籍頁面效果:
可以看到我們用form去做編輯時沒有將出版社和作者信息給選中,如果要選中的話就需要用我們之前的那種判斷方式,比較麻煩,所以這塊需要用到下面的ModelForm來解決。
在這裏插入圖片描述

刪除書籍:

# 刪除書籍
def delete_book(request, book_id):
    app02.models.Book.objects.filter(pk=book_id).delete()
    return redirect('app03:show_book')

二.ModelForm

組件的功能就是把model和form組合起來,會把所有的字段信息轉換成forms裏面的字段(上面定義的BookForm),校驗規則就是我們數據庫中定義的,但是我們也可以在ModelForm裏面自己定義,這樣就會覆蓋我們model裏面的那個字段。
創建ModelForm類:

from django.forms import ModelForm

class BookModelForm(ModelForm):
	#title = forms.CharField(max_length=16) 如果這裏也定義了一個title,那就會把你數據庫裏面的title給替換掉
    class Meta: #原類Meta(規定寫法,並注意首字母是大寫的)
        model = app02.models.Book   #指定book表 全部轉換成上面BookForm裏面的校驗數據
        fields = '__all__'          #指定表裏面的所有的字段  告訴Book表將表裏面所有的字段信息全部給我生成forms裏面的字段
        exclude = ['title'],        #排除
        error_messages = {          #錯誤信息
                'title':{'required':'不能爲空!!'},
                'price':{'required':'不能爲空!!'},
                'publishs':{'required':'不能爲空!!'},
                'publishDate':{'required':'不能爲空!!'},
                'authors':{'required':'不能爲空!!'},
                         },
        help_texts = {'title':'書名!'}     #幫助信息
        widgets = {}                        #添加樣式

    #全局鉤子
    def clean(self):
        pass

    # 局部鉤子
    def clean_title(self):
        value = self.cleaned_data.get('title')
        if '666' in value:
            raise ValidationError('敏感詞彙!!666')
        else:
            return value
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for field in self.fields.values():
            field.widget.attrs.update({'class':'form-control'})

ModelForm版本圖書管理系統:
添加書籍:

# 添加數據
def add_book(request):
    if request.method == 'GET':
        book_model_form = BookModelForm()
        return render(request, 'many_test/book_add.html', {'book_model_form':book_model_form})
    else:
        book_model_form = BookModelForm(request.POST)
        if book_model_form.is_valid():
            print(book_model_form.cleaned_data)
            book_model_form.save()  #直接保存 因爲上面定義了model = app02.models.Book
            return redirect('app03:show_book')
        else:
            print(book_model_form.errors)
            return render(request, 'many_test/book_add.html', {'book_model_form': book_model_form})

書籍展示:

# 展示書籍
def show_book(request):
    start = 0
    book_list = app02.models.Book.objects.all() 
    paginator = Paginator(book_list, 5)  # 創建一個panginator對象
    page = request.GET.get('page', 1)
    currentPage = int(page)
    if currentPage != 1:
        start = (currentPage - 1) * 5
    try:
        book_list = paginator.page(page)
    except PageNotAnInteger:
        book_list = paginator.page(1)  # 這個是對你的分頁的數據進行取值  去除你的分頁過後的第一頁
    except EmptyPage:
        book_list = paginator.page(paginator.num_pages)  # 分頁數
    return render(
        request, 'many_test/book_show.html',
        {'paginator': paginator, 'book_list': book_list, 'currentPage': currentPage, 'start': start})

編輯書籍:

# 編輯書籍
def edit_book(request, book_id):
    book_obj = app02.models.Book.objects.filter(pk=book_id)
    book_obj = book_obj.first()
    if request.method == 'GET':
        book_model_form = BookModelForm(instance=book_obj) #需要指定給那個實例編輯
        return render(request, 'many_test/book_edit.html', {'book_model_form': book_model_form,'book_obj':book_obj})
    else:
        book_model_form = BookModelForm(
        request.POST,instance=book_obj) #這裏也需要指定一下,不然下面的save會新增加一條
        if book_model_form.is_valid():
            book_model_form.save()
            return redirect('app03:show_book')
        else:
            return render(request, 'many_test/book_edit.html',
                          {'book_model_form': book_model_form, 'book_obj': book_obj})

刪除書籍:

# 刪除書籍
def delete_book(request, book_id):
    app02.models.Book.objects.filter(pk=book_id).delete()
    return redirect('app03:show_book')

html文件:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    {% for bookform in book_model_form %}
        <div>
        <label for="{{ bookform.id_for_label }}">{{ bookform.label }}</label>
        {{ bookform }}
        <span style="color: red;font-size: 14px">{{ bookform.errors.0 }}</span>
        </div>
    {% endfor %}
    <input type="submit">
</form>
</body>
</html>

實際上我們的編輯和添加頁面是內容是重複的,可以做一個base模板,用incloud調用就行了:
base:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% for bookform in book_model_form %}
        <div>
        <label for="{{ bookform.id_for_label }}">{{ bookform.label }}</label>
        {{ bookform }}
        <span style="color: red;font-size: 14px">{{ bookform.errors.0 }}</span>
        </div>
    {% endfor %}
</body>
</html>

add_book:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
</head>
<body>
<h1>添加書籍</h1>
<form action="" method="post">
    {% csrf_token %}
    {% include 'many_test/base.html' %}

    <input type="submit">
</form>
</body>
</html>

edit_book:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
</head>
<body>
<h1>編輯書籍</h1>
<form action="" method="post">
    {% csrf_token %}
    {% include 'many_test/base.html' %}
    <input type="submit">
</form>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章