什么是 django自帶的admin系統(tǒng)
- Django 最強(qiáng)大的部分之一是自動生成的Admin 界面。它讀取模型數(shù)據(jù)來提供一個強(qiáng)大的、生產(chǎn)環(huán)境就緒的界面,使內(nèi)容提供者能立即用它向站點(diǎn)中添加內(nèi)容。
- 它可以快速的開發(fā)出一個后臺管理界面
如何開啟admin系統(tǒng)
- 確保在
settings.py
中的INSTALLED_APPS
安裝了'django.contrib.admin'
- 在
INSTALLED_APPS
中添加了四個依賴的app
,
django.contrib.auth
,
django.contrib.contenttypes
,
django.contrib.messages
,
django.contrib.sessions
。
image.png - 在模板上下文中添加以下依賴
django.contrib.auth.context_processors.auth
,django.contrib.messages.context_processors.messages
image.png - 在中間件中添加以下依賴
django.contrib.auth.middleware.AuthenticationMiddleware
,django.contrib.messages.middleware.MessageMiddleware
。
image.png - 運(yùn)行命令
python manage.py createsuperuser
創(chuàng)建一個超級用戶,然后輸入超級用戶的用戶名和密碼。創(chuàng)建的用戶是保存在auth_user表中 -
使用該命令創(chuàng)建的用戶是一個超級管理員用戶,它擁有所有的權(quán)限,需要妥善保管image.png
- 如果沒有通過migrate,需要先同步migrate
- 在瀏覽器中輸入
127.0.0.1:8000/admin/
進(jìn)入admin
登錄界面。輸入剛剛創(chuàng)建的用戶名和密碼,進(jìn)入admin管理界面。 -
admin 界面默認(rèn)是英文,如需要修改成中文,修改settings中的屬性,
ps: 控制這個語言展示的模塊叫i18n,i18n實際就是國際化,就代表支持多種語言的功能
image.png
界面效果圖:image.png
image.png
自定義admin:
- 把需要管理的模型添加到
admin
中:
首先要在INSTALLED_APPS
中添加對應(yīng)的應(yīng)用,然后在應(yīng)用的admin.py
中注冊,有2中方法注冊,方法二常用
方法一:
class ArticleAdmin(admin.ModelAdmin):
pass
admin.site.register(Article, ArticleAdmin)
方法二:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
from .models import *
# Register your models here.
@admin.register(Classesnumber)
class ClassesnumberAuth(admin.ModelAdmin):
pass
- 修改app顯示名稱:
image.png
所有跟app相關(guān)的內(nèi)容配置,可以實現(xiàn)一個Appconfig
類的子類來完成,django一般會默認(rèn)在apps.py
中建立一個
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.apps import AppConfig
class TestappConfig(AppConfig):
name = 'TestApp'
- 然后在apps.py對應(yīng)的子類中配置
verbose_name
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.apps import AppConfig
class TestappConfig(AppConfig):
name = 'TestApp'
verbose_name = u'練習(xí)項目'
- 我們只需要指定一下即可,需要管理的
__init__.py
中配置如下:
from .apps import *
default_app_config = 'TestApp.apps.TestappConfig'
- 修改模型顯示的名稱:
設(shè)置model中的元屬性即可
class Meta:
verbose_name = u"班號"
verbose_name_plural = u"班號列表"
效果:
注意:要有數(shù)據(jù) verbose_name才展示出來,否則顯示的是復(fù)數(shù)形式。
- 修改模型列表的展示:
在models.py
中對應(yīng)類添加一個__unicode__
方法(py3中使用的是__str__
),返回需要展示的字符串(注意需要返回字符串,否則Python將拋出一個TypeError 錯誤,并提示:”coercing to Unicode: need string or buffer, int found” ),如把return self.id
改為return str(self.s_id)
或者返回name
比如要展示班級名稱:
#`models.py
def __unicode__(self):
return self.name
- 修改展示的列表項,即模型中其他字段內(nèi)容,可以在admin.py中用
list_display
修改展示的列表項
#admin.py
@admin.register(Classesgrade)
class ClassesgradeAuth(admin.ModelAdmin):
list_display = ['name', 'create_time', 'update_time', 'number']
- Admin類管理
list_display
:可以修改展示的列表項
search_fields
:可以提供搜索的查找項
list_filter
:可以提供一個過濾的表
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
from .models import *
# Register your models here.
@admin.register(Classesnumber)
class ClassesnumberAuth(admin.ModelAdmin):
pass
@admin.register(Classesgrade)
class ClassesgradeAuth(admin.ModelAdmin):
list_display = ['id','name', 'create_time', 'update_time', 'number']
#提供搜索的查找項(模糊搜索),幾個則是或or的關(guān)系
search_fields = ['id','name']
#提供一個過濾的表,如果多個,則且and的關(guān)系
list_filter = ['id','name']
注意:list_display不支持多對多的,需要處理下:/
#admin.py
@admin.register(Student)
class StudentAuth(admin.ModelAdmin):
#list_display不能顯示多對多的
list_display = ('id', 'name', 'age', 'sex', 'classesno','teachers_list')
#然后自己定義個字段名來代替teacher在teachers_list中顯示即可。因為待會我們要寫一個同名方法來獲取teacher的里的值。
def teachers_list(self,obj):
return [a.name for a in obj.teacher.all()] #獲取老師所有對象,然后再迭代獲取對應(yīng)名稱組成列表
teachers_list.short_description = u'老師'
# filter_horizontal = ['teacher']# filter_horizontal是用來編輯狀態(tài)下的teacher頁面的。
search_fields,在使用 Django admin 系統(tǒng)中的搜索時可能會出現(xiàn)“related Field has invalid lookup: icontains”錯誤,主要原因是外鍵查詢是需要指定相應(yīng)的字段的。外鍵不應(yīng)該只是一個model,而該是另一個表的明確的一個字段。所以我們需要指定特定的字段 "本表外鍵字段__外鍵所在表需查詢字段"。
更多操作:
參考文檔:
https://docs.djangoproject.com/en/1.11/ref/contrib/admin/
https://yiyibooks.cn/xx/Django_1.11.6/ref/contrib/admin/index.html其它:
在admin操作后臺的時候,如果選擇多對多對象,需要ctrl+ 鼠標(biāo)點(diǎn)擊完全多選。
auth系統(tǒng):
- auth系統(tǒng)是django內(nèi)置一個的一個app,它是專門用于管理用戶權(quán)限的一個組件;
- 創(chuàng)建一個用戶:
from django.contrib.auth.models import User
,然后使用create_user
來創(chuàng)建一個用戶。
from django.contrib.auth.models import User
User.objects.create_user(**kwargs)
- 驗證用戶
from django.contrib.auth import authenticate
#authenticate接受兩個參數(shù),用戶名 username 和 密碼 password ,并在密碼對給出的用戶名合法的情況下返回一個 User 對象,如果密碼不合法。authenticate()返回None。
user = authenticate(username='john', password='secret')
if user is not None:
# 這個用戶存在數(shù)據(jù)庫中
else:
# 用戶名或者密碼錯誤
- 登錄
from django.contrib.auth import authenticate, login
def post(self, request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
#authenticate() 只是驗證一個用戶的證書而已。而要登錄一個用戶,使用 login() 。該函數(shù)接受一個 HttpRequest 對象和一個 User 對象作為參數(shù)并使用Django的會話( session )框架把用戶的ID保存在該會話中。
login(request, user)
# 登錄成功
else:
# 用戶名或者密碼錯誤
- 注銷
from django.contrib.auth import logout
def get(self, request)
logout(request) # 當(dāng)執(zhí)行完logout,實際就是清除了session中的user信息
#它接受一個HttpRequest對象并且沒有返回值,所以,因為沒有返回值,需要返回一個頁面。
- 登錄驗證
from django.contrib.auth.mixins import LoginRequiredMixin
class Show(LoginRequiredMixin, View):
login_url = "/account/login/" #如果沒有登錄成功,則跳轉(zhuǎn)至內(nèi)部定義的login_url,否則會跳轉(zhuǎn)到`settings.LOGIN_URL`指定的URL中。即先找內(nèi)部再找外部
#注意登錄驗證是用于一些只有登錄了才能看的到的頁面,但是可能存在一些直接輸入url也可以看到這個頁面,
#只不過沒對應(yīng)值而已,這樣是不安全的,所以在進(jìn)入這些頁面前需要進(jìn)行驗證,以避免直接輸入url的情況,
#如果驗證已經(jīng)登錄成功的則進(jìn)入對應(yīng)頁面,沒有則通過使用LoginRequiredMixin來實現(xiàn)與login_required相同的行為,#如果沒有登錄成功,則跳轉(zhuǎn)至內(nèi)部定義的login_url,否則會跳轉(zhuǎn)到`settings.LOGIN_URL`指定的URL中。即先找內(nèi)部再找外部
- 修改密碼,即找回密碼
from django.contrib.auth.models import User
u = User.objects.get(username='john') #獲取對象
u.set_password('new password') #保存可以用u.password = make_password(new password)
u.save() #保存
User模型常用屬性和方法:
username
:用戶名。
email
:郵箱。
groups
:多對多的組。
user_permissions
:多對多的用戶權(quán)限。
is_staff
: 指明這個用戶是否可以進(jìn)入管理站點(diǎn)。
is_active
: 是否激活,判斷該用戶是否可用。
is_superuser
: 是否是超級用戶。
last_login
: 上次登錄時間。
date_joined
: 注冊時間。
is_authenticated
: 是否驗證通過了。
is_anonymous
:是否是匿名用戶。
set_password(raw_password)
: 設(shè)置密碼,傳原生密碼進(jìn)去。
check_password(raw_password)
: 檢查密碼。
has_perm(perm)
: 判斷用戶是否有某個權(quán)限。
has_perms(perm_list)
: 判斷用戶是否有權(quán)限列表中的某個列表。
- Permission權(quán)限:
1.在模型中添加,需要控制權(quán)限的模型中添加權(quán)限,即通過這些權(quán)限,能做什么事情:
class Task(models.Model):
class Meta:
permissions = (
("view_task", "查看任務(wù)權(quán)限"),
("change_task_status", "修改任務(wù)權(quán)限"),
("close_task", "關(guān)閉任務(wù)權(quán)限"),
)
2.在代碼中添加權(quán)限
from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(
codename='can_publish',
name='Can Publish Posts',
content_type=content_type, #必填。一個指向django_content_type數(shù)據(jù)庫表,對于每一個Django模型,在這個表里面都有一個記錄對應(yīng)。
)
一般在模型中增加,畢竟只有那么一次
- 給用戶賦相應(yīng)權(quán)限
1.代碼中:
permission = Permission.objects.get(name=u'查看商品信息')#對應(yīng)auth_permission表中
myuser.user_permissions.set([permission_list]) # 設(shè)置一個權(quán)限列表
myuser.user_permissions.add(permission, permission, ...) # 添加一個權(quán)限
myuser.user_permissions.remove(permission, permission, ...) # 刪除多個權(quán)限
myuser.user_permissions.clear() # 清理所有權(quán)限
# 以上操作都需要save,因為他們都是一個數(shù)據(jù)庫操作
myuser.has_perm('foo.add_bar'
-
后臺管理系統(tǒng)中image.png
- 權(quán)限驗證
from django.contrib.auth.mixins import PermissionRequiredMixin
class MyView(PermissionRequiredMixin, View):
# 單個權(quán)限
permission_required = 'polls.can_vote'
# 多個權(quán)限,且的關(guān)系
permission_required = ('polls.can_open', 'polls.can_edit')
- Group模型:
- 所屬包
django.contrib.auth.models.Group
- 創(chuàng)建
Group
:必須傳一個name
參數(shù)進(jìn)去。 - Group`操作:
group.permissions.set([permission_list]) # 設(shè)置這個組包含的權(quán)限列表
group.permissions.add(permission, permission, ...) # 添加一個權(quán)限到這個組
group.permissions.remove(permission, permission, ...) # 從這個組中刪除一個權(quán)限
group.permissions.clear() # 清理這個組的權(quán)限
myuser.groups.set([group_list]) # 設(shè)置一些組
myuser.groups.add(group, group, ...) # 添加某些組
myuser.groups.remove(group, group, ...) # 刪除某些組
myuser.groups.clear() # 清理所有租
一般情況下,我們都不會手工添加對應(yīng)的權(quán)限,都會通過models配置對應(yīng)的權(quán)限
學(xué)以致用
- 使用django的auth組件,完成登錄、注冊、注銷頁面;
- 使用auth組件的權(quán)限,添加一個主頁,主頁展示商品列表,并設(shè)置一個權(quán)限才能訪問;
- 使用admin組件,添加商品列表的數(shù)據(jù);
- 需求分析
需要使用Django的auth組件,則不要單獨(dú)建立user模型,使用自帶的組件進(jìn)行操作就可以了。 - 在
forms.py
建立注冊表單類,其中名稱,價格,商品詳細(xì)信息:
# -*- coding: utf-8 -*-
from django import forms
from django.contrib.auth.models import User
class RegisterForm(forms.Form):
userName = forms.CharField(label=u'用戶名',min_length = 3,max_length = 20)
userPassword = forms.CharField(label=u'登錄密碼',min_length= 6,max_length = 20,error_messages = {'min_length':u'密碼至少6位','max_length':u'密碼最長20位'})
userConfirmPassword = forms.CharField(label=u'確認(rèn)密碼',min_length = 6,max_length = 20,error_messages = {'min_length':u'密碼至少6位','max_length':u'密碼最長20位'})
userEmail = forms.EmailField(label=u'郵箱')
def clean_userName(self):
userName = self.cleaned_data['userName']
user = User.objects.filter(username = userName)
if user:
raise forms.ValidationError(u'用戶名已存在')
return userName
def clean_userConfirmPassword(self):
userPassword = self.cleaned_data['userConfirmPassword']
userConfirmPassword = self.cleaned_data['userConfirmPassword']
if userPassword != userConfirmPassword:
raise forms.ValidationError(u'兩次密碼不一致')
return userPassword
class ResetPasswordForm(forms.Form):
userName = forms.CharField(label=u'用戶名',min_length = 3,max_length = 20)
userPassword = forms.CharField(label=u'登錄密碼', min_length=6, max_length=20,error_messages={'min_length': u'密碼至少6位', 'max_length': u'密碼最長20位'})
userConfirmPassword = forms.CharField(label=u'確認(rèn)密碼',min_length = 6,max_length = 20,error_messages = {'min_length':u'密碼至少6位','max_length':u'密碼最長20位'})
def clean_userName(self):
userName = self.cleaned_data['userName']
user = User.objects.filter(username = userName)
print(user)
if not user:
raise forms.ValidationError(u'用戶名不存在')
return userName
def clean_userConfirmPassword(self):
userPassword = self.cleaned_data['userPassword']
userConfirmPassword = self.cleaned_data['userConfirmPassword']
print(userPassword,userConfirmPassword)
if userPassword != userConfirmPassword:
raise forms.ValidationError(u'兩次密碼不一致')
return userPassword
注冊頁面sign_up.html
效果:
注冊成功效果:
登錄頁面
sign_in.html
效果:登錄成功,跳轉(zhuǎn)到首頁
index.html
:訪問主頁
home.html
:具有添加權(quán)限的頁面:
添加商品
addProduct.html
,成功之后返回商品展示頁面:注銷退出,返回登錄界面:
找回密碼
resetpassword.html
,成功之后返回登錄界面:- urls.py:
# -*- coding:utf-8 -*-
from django.conf.urls import url,include
from auth_study import views
urlpatterns = [
url(r'^register/$', views.Register.as_view(),name='register'),
url(r'^login/$',views.Login.as_view(),name='login'),
url(r'^index/$',views.Index.as_view(),name='index'),
url(r'^logout/$',views.Logout.as_view(),name='logout'),
url(r'^resetpassword/$',views.ResetPassword.as_view(),name='resetpassword'),
url(r'^home/$', views.Home.as_view(), name='home'),
url(r'^addProduct/$', views.AddProduct.as_view(), name='addProduct')
]
- 視圖views.py:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render,redirect,reverse
from django.contrib.auth.models import User,Permission
from django.views import View
from .forms import *
from django.http import HttpResponse
from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.mixins import LoginRequiredMixin,PermissionRequiredMixin
from .models import Product
import TestApp
from TestApp.models import *
# Create your views here.
#注冊功能
class Register(View):
def get(self,request):
return render(request,'sign_up.html')
def post(self,request):
form = RegisterForm(request.POST)
print(form.is_bound)
if form.is_valid():
userName = form.cleaned_data['userName']
userPassword = form.cleaned_data['userPassword']
userConfirmPassword = form.cleaned_data['userConfirmPassword']
userEmail = form.cleaned_data['userEmail']
#create_user可以由Django自動將密碼加密,而create還需要先將密碼自己加密再給
user = User.objects.create_user(username=userName,email=userEmail,password=userPassword)
#給用戶添加權(quán)限,多對多關(guān)系,用add添加
user.user_permissions.add(Permission.objects.get(codename='view_products'))
user.save() #需要save,因為他們都是一個數(shù)據(jù)庫操作
return HttpResponse(u'注冊成功,請返回<a href="/auth/login">登錄</a>')
else:
return render(request,'sign_up.html',locals())
#登錄功能
class Login(View):
def get(self,request):
return render(request,'sign_in.html')
def post(self,request):
userName = request.POST.get('userName')
userPassword = request.POST.get('userPassword')
print(userName,userPassword)
#驗證用戶,它接受兩個參數(shù),用戶名 username 和 密碼 password,認(rèn)證只有是否激活跟用戶名密碼。
user = authenticate(username = userName,password = userPassword)
#并在密碼對給出的用戶名合法的情況下返回一個 User 對象。 如果密碼不合法,authenticate()返回None。
if user is not None:
if user.is_active:
#登錄,向session中添加SESSION_KEY, 便于對用戶進(jìn)行跟蹤:
login(request,user)
# 如果調(diào)用login方法以后,
# request對象就會激活user屬性,這個屬性不管登錄或者未登錄都是存在
return redirect(reverse('index'))
else:
message = u'該用戶未激活'
else:
message = u'用戶名或密碼錯誤'
return render(request,'sign_in.html',locals())
class Index(LoginRequiredMixin,View): #登錄驗證,主要用于比如說直接輸入地址情況。
# 如果需要指定單獨(dú)的跳轉(zhuǎn),則該類中指定login_url屬性
# 如果需要指定全局的,則在settings中指定LOGIN_URL屬性
login_url = '/auth/login/'#沒有登錄則指定跳轉(zhuǎn)
def get(self,request):
print(request.COOKIES)
return render(request, 'index.html', locals())
#注銷功能
class Logout(View):
def get(self,request):
#注銷用戶,這個方法就會把我們的session跟cookie清理掉
logout(request)
message = u'注銷成功'
return render(request,'sign_in.html',locals())
#重置密碼
class ResetPassword(View):
def get(self,request):
return render(request,'resetpassword.html')
def post(self,request):
form = ResetPasswordForm(request.POST)
if form.is_valid():
username = form.cleaned_data['userName']
userPassword = form.cleaned_data['userPassword']
user = User.objects.get(username=username)
print(user)
if user:
user.set_password(userPassword)
user.save()
return render(request, 'sign_in.html', locals())
return render(request, 'resetpassword.html', locals())
#展示主頁
class Home(PermissionRequiredMixin,View):
#單個權(quán)限
permission_required = 'auth_study.view_products'
#多個權(quán)限,要同時具有,且的關(guān)系,元祖或列表都可
# permission_required = ['auth_study.view_products','auth_study.update_products']
#上面?zhèn)€相當(dāng)于全局的,只有滿足了上面權(quán)限中的一個就可以進(jìn)入下面的get了,否則就跳轉(zhuǎn)到setting配置的LOGIN_URL去了
def get(self,request):
print('get...',request.user.user_permissions.all())
#has_perm(perm): 判斷用戶是否有某個權(quán)限。
#has_perms(perm_list): 判斷用戶是否有權(quán)限列表中的某個列表。
if request.user.has_perm('auth_study.view_products'):
products = Product.objects.all()
if request.user.has_perm('auth_study.add_products'):
canAdd = True #判斷有沒有添加權(quán)限,然后置為True,頁面去判斷是否顯示相關(guān)
else:
message = '沒有查看商品的權(quán)限'
return render(request,'home.html',locals())
#添加商品
class AddProduct(View):
def get(self,request):
return render(request,'addProduct.html')
def post(self,request):
print('post')
name = request.POST.get('username')
price = request.POST.get('price')
detail = request.POST.get('detail')
print(name,price,detail)
product = Product.objects.create(name = name,price = price,detail= detail)
if product:
return HttpResponse('添加商品成功<a href="/auth/home/"></a>')
return HttpResponse('添加商品失敗<a href="/auth/home/"></a>')
- 頁面html:
#注冊頁面sign_up.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注冊界面</title>
</head>
<body>
<div>
<h1>注冊</h1>
<form action="/auth/register/" method="post">
{% csrf_token %}
用 戶 名:<input type="text" name="userName" placeholder="用戶名"/>
登錄密碼:<input type="password" name="userPassword" placeholder="登錄密碼"/>
確認(rèn)密碼:<input type="password" name="userConfirmPassword" placeholder="確認(rèn)密碼"/>
郵 箱:<input type="email" name="userEmail" placeholder="郵箱"/>
<input type="submit" value="注冊"/>
</form>
</div>
{{ form.errors }} <!--如果注冊錯誤則顯示對應(yīng)的錯誤 -->
</body>
</html>
#登錄頁面sign_in.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄界面</title>
</head>
<body>
{{ message }}
<h1>登錄</h1>
<form action="/auth/login/" method="post">
{% csrf_token %}
用 戶 名:<input type="text" name="userName"/>
登錄密碼:<input type="password" name="userPassword"/>
<input type="submit" value="登錄"/>
</form>
<a href="/auth/resetpassword/">找回密碼</a>
</div>
</body>
</html>
#首頁頁面index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首頁</title>
<style>
*{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div style="margin-top:20px;color: black;font-size: 20px;line-height: 20px;text-align: center;";>
歡迎{{user.username}} {{user.email}} {{user.is_authenticated}}登錄成功!
<br/>
<a href="/auth/home/">主頁</a>
<a href="/auth/logout/">退出</a>
</div>
</body>
</html>
#主頁home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>查看老師信息</title>
</head>
<body>
<h2>{{user.username}}主頁</h2>
{% for product in products %}
<p>
名稱:{{ product.name }}<br/>
詳細(xì)信息:{{product.detail}}<br/>
價格:{{product.price}}<br/>
</p>
{% endfor %}
{{ message }}
{% if canAdd %} <!--判斷有沒有添加權(quán)限 -->
<a href="/auth/addProduct/">添加商品</a>
{% endif %}
</body>
</html>
#添加商品addPruduct.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加商品</title>
</head>
<body>
<form action="/auth/addProduct/" method="post">
{% csrf_token %}
名稱:<input type="text" name="username"/>
價格:<input type="text" name="price"/>
詳細(xì)信息: <textarea name="detail"></textarea>
<input type="submit" value="添加">
</form>
</body>
</html>
#找回密碼resetpassword.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>找回密碼</title>
</head>
<body>
<h1>找回密碼</h1>
<form action="/auth/resetpassword/" method="post">
{% csrf_token %}
用 戶 名:<input type="text" name="userName"/>
重置密碼:<input type="password" name="userPassword"/>
確認(rèn)密碼:<input type="password" name="userConfirmPassword"/>
<input type="submit" value="確認(rèn)"/>
</form>
</div>
{{form.errors}}
</body>
</html>