一.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>