from django import forms
from app01 import models
class BookModelForm(forms.ModelForm):
#必須是這個類名
class Meta:
# 告訴Django這個form類和那個model類對應
model = models.Book
# 告訴Django這個form類里面有哪些字段
fields = "__all__"
widgets = {
"publish_date": forms.widgets.DateInput(
# 給日期字段添加日期類型
attrs={"type": "date"}
)
}
labels = {
"title": "書名",
"price": "價格",
"publish_date": '出版日期',
"publisher": "出版社名稱",
"authors": "作者"
}
error_messages = {
"title": {
"required": "書名不能為空"
}
}
# 通過修改類的初始化方法達到批量添加共同屬性的目的
def __init__(self, *args, **kwargs):
super(BookModelForm, self).__init__(*args, **kwargs)
# for field_name in self.base_fields:
for field in iter(self.fields):
self.fields[field].widget.attrs.update({
'class': 'form-control'
})
class Meta:
model, # 對應Model的
fields=None, # 字段
exclude=None, # 排除字段
labels=None, # 提示信息
help_texts=None, # 幫助提示信息
widgets=None, # 自定義插件
error_messages=None, # 自定義錯誤信息(整體錯誤信息from django.core.exceptions import NON_FIELD_ERRORS)
field_classes=None # 自定義字段類 (也可以自定義字段)
localized_fields=('birth_date',) # 本地化,如:根據不同時區顯示數據
model_form_obj = XXOOModelForm() //實例化對象
model_form_obj.is_valid() // 校驗數據
model_form_obj.errors.as_json() //錯誤
model_form_obj.clean() //同Form組件中的屬性
model_form_obj.cleaned_data // 同Form組件中的屬性
def add_book(request):
if request.method == "POST":
#直接傳request.POST,進行ModelForm的實例化傳參
form_obj = forms.BookModelForm(request.POST)
if form_obj.is_valid(): # 校驗數據
form_obj.save() #直接就可以保存數據到數據庫,包括多對多,多對一,一對一的關系
return redirect("/book_list/")
#ModelForm實例化對象
form_obj = forms.BookModelForm()
return render(request, "v2/add_book.html", locals())
def edit_book(request, pk):
book_obj = models.Book.objects.filter(id=pk).first()
#form_obj通過instance設置初始化的值,例如,圖書管理系統中的編輯書籍功能,
#點擊編輯后跳轉到編輯書籍頁面,跳轉后需要用要編輯的書籍信息填充頁面對應信息。
#不同於Form組件的是,ModelForm直接就可以傳實例化的對象,而不需要將對象轉化成字典的形式傳。
form_obj = forms.BookModelForm(instance=book_obj)
return render(request, "v2/edit_book.html", locals())
ModelForm用於更新 :ModelForm(request.POST, instance=book_obj)
def edit_book(request, pk):
book_obj = models.Book.objects.filter(id=pk).first()
if request.method == "POST":
#修改數據時,直接可以將用戶數據包request.POST傳進去,
#再傳一個要修改的對象的示例,ModelForm就可以自動完成修改數據了。
form_obj = forms.BookModelForm(request.POST, instance=book_obj)
if form_obj.is_valid(): // 數據校驗
form_obj.save() // 直接保存
return redirect("/book_list/")
#form_obj通過instance設置初始化的值,例如,圖書管理系統中的編輯書籍功能,
#點擊編輯后跳轉到編輯書籍頁面,跳轉后需要用要編輯的書籍信息填充頁面對應信息。
#不同於Form組件的是,ModelForm直接就可以傳實例化的對象,而不需要將對象轉化成字典的形式傳。
form_obj = forms.BookModelForm(instance=book_obj)
return render(request, "v2/edit_book.html", locals())
- ModelForm ---- 中小型應用程序。因為ModelForm是依賴於models的。
- Form ------- 大型應用程序
- 表結構:
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=12)
address = models.TextField()
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=12)
gender = models.SmallIntegerField(
choices=((0, '女'), (1, '男'), (2, '保密'))
)
age = models.IntegerField()
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2) # 0~999.99
publish_date = models.DateField()
publisher = models.ForeignKey(to="Publisher", on_delete=models.CASCADE)
authors = models.ManyToManyField(to="Author")
def __str__(self):
return self.title
- ModelForm類:
from django import forms
from app01 import models
class BookModelForm(forms.ModelForm):
class Meta:
# 告訴Django這個form類和那個model類對應
model = models.Book
# 告訴Django這個form類里面有哪些字段
fields = "__all__"
widgets = {
"publish_date": forms.widgets.DateInput(
# 給日期字段添加日期類型
attrs={"type": "date"}
)
}
labels = {
"title": "書名",
"price": "價格",
"publish_date": '出版日期',
"publisher": "出版社名稱",
"authors": "作者"
}
error_messages = {
"title": {
"required": "書名不能為空"
}
}
# 通過修改類的初始化方法達到批量添加共同屬性的目的
def __init__(self, *args, **kwargs):
super(BookModelForm, self).__init__(*args, **kwargs)
# for field_name in self.base_fields:
for field_name in iter(self.fields):
field = self.base_fields[field_name]
field.widget.attrs.update({
"class": "form-control",
})
- views 視圖函數:
from django.shortcuts import render,redirect
from app01 import modelform
from app01 import models
def book_list(request):
book_list = models.Book.objects.all()
return render(request, 'book_list.html', {'book_list': book_list})
def add_book(request):
if request.method == "POST":
# modelform 直接可以將從前端拿到的數據組request.POST
#當參數傳給實例化的Modelform
form_obj = modelform.BookModelForm(request.POST)
# 調用is_valid()方法校驗數據
if form_obj.is_valid():
# 直接保存到數據庫中
form_obj.save()
return redirect("/book_list/")
modelform_obj = modelform.BookModelForm()
return render(request, 'add_book.html', {"modelform_obj": modelform_obj})
def edit_book(request,pk):
book_obj = models.Book.objects.filter(id=pk).first()
if request.method == "POST":
#修改數據時,直接可以將用戶數據包request.POST傳進去,
#再傳一個要修改的對象的示例,ModelForm就可以自動完成修改數據了。
form_obj = modelform.BookModelForm(request.POST, instance=book_obj)
if form_obj.is_valid():
form_obj.save()
return redirect("/book_list/")
# form_obj通過initial設置初始化的值,例如,圖書管理系統中的編輯書籍功能,
# 點擊編輯后跳轉到編輯書籍頁面,跳轉后需要用要編輯的書籍信息填充頁面對應信息。
# 不同於Form組件的是,ModelForm直接就可以傳實例化的對象,而不需要將對象轉化成字典的形式傳。
form_obj = modelform.BookModelForm(instance=book_obj)
#locals()是將本地數據鍵值對的簡寫形式
return render(request, "edit_book.html", locals())
- book_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>書籍列表</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-offset-2">
<a href="/add_book/">添加書籍</a>
<table border="1">
<thead>
<tr>
<th>序號</th>
<th>id</th>
<th>書名</th>
<th>價格</th>
<th>出版日期</th>
<th>出版社</th>
<th>作者</th>
<th>操作</th>
</tr>
</thead>
{% for book in book_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ book.id }}</td>
<td>{{ book.title }}</td>
<td>{{ book.price }}</td>
<td>{{ book.publish_date }}</td>
<td>{{ book.publisher }}</td>
<td>{{ book.authors.all }}</td>
<td>
<a href="/edit_book/{{ book.id }}/">編輯</a>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
</body>
</html>
- add_book.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加書籍</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-offset-3">
<form role="form" action="" method="post">
{% csrf_token %}
{% for modelform in modelform_obj %}
<p>
{{ modelform.label }}
{{ modelform }}
</p>
{% endfor %}
<button type="submit" class="btn btn-success">提交</button>
</form>
</div>
</div>
</div>
</body>
</html>
- edit_book.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加書籍</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-offset-3">
<form role="form" action="" method="post">
{% csrf_token %}
{% for filed in form_obj %}
<p>
{{ filed.label }}
{{ filed }}
</p>
{% endfor %}
<button type="submit" class="btn btn-success">提交</button>
</form>
</div>
</div>
</div>
</body>
</html>
- ModelForm增加了Form組件和對應數據庫之間的聯系,進而簡化了Form類的代碼
- ModelForm繼承了Form組件中的所有方法的同時,簡化了前端獲取數據和對應數據庫之間的數據對接,不需要在對數據的內容做過多的操作。
- 批量添加樣式:
通過重寫ModelForm類的init方法來實現。
# 通過修改類的初始化方法達到批量添加共同屬性的目的
def __init__(self, *args, **kwargs):
super(BookModelForm, self).__init__(*args, **kwargs)
# for field_name in self.base_fields:
for field in iter(self.fields):
self.fields[field].widget.attrs.update({
'class': 'form-control'
})