form介紹
form主要功能: 頁面可用的HTML標籤,對用戶提交的數據進行校驗,保留上次輸入內容
普通註冊
1、html頁面
reg.html
<form action="/reg/" method="post" novalidate>
{% csrf_token %}
<div>
用戶名: <input type="text" name="username">
</div>
<div>
密碼: <input type="password" name="pwd">
<span>{{ error.pwd }}</span>
</div>
<input type="submit" value="提交">
</form>
2、urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('reg/', views.register),
]
3、views.py
def register(request):
error_msg = {"pwd": "", "username": ""}
if request.method == "POST":
username = request.POST.get("username")
pwd = request.POST.get("pwd")
if len(pwd) < 6:
error_msg["pwd"] = "長度不能小於6"
return render(request, "reg.html", {"error": error_msg})
使用form註冊
1、html頁面
<form action="/regs2/" method="post" novalidate>
{% csrf_token %}
{{ form_obj.as_p }} {# 生成html頁面 #}
{{ form_obj.errors.pwd }} {# 打印錯誤提示 #}
<input type="submit" value="提交">
</form>
2、 urls.py與 普通註冊的一樣
3、views.py
from app01 import formd
def register2(request):
form_obj = formd.RgeForm()
if request.method == "POST":
form_obj = formd.RgeForm(request.POST) # django自動生成的 html頁面
print(form_obj)
#<tr><th><label for="id_name">用戶名:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="name" maxlength="16" required id="id_name" /></td></tr>
return render(request, "reg2.html", {"form_obj": form_obj})
4、formd.py
在項目中創建一個formd.py文件
from django import forms # 引用forms模塊
# 創建註冊函數
class RgeForm(forms.Form):
name = forms.CharField(
label="用戶名",
max_length=16, # 最大長度以及錯誤提示
error_messages={
"max_length": "最大長度16"
}
)
pwd = forms.CharField(
label="密碼",
min_length=6,
error_messages={
"required": "不能爲空",
"invalid": "格式錯誤",
"min_length": "最少6位",
}
)
form的功能: 來源: https://www.cnblogs.com/liwenzhou/p/8747872.html
• 前端頁面是form類的對象生成的 -->生成HTML標籤功能
• 當用戶名和密碼輸入爲空或輸錯之後 頁面都會提示 -->用戶提交校驗功能
• 當用戶輸錯之後 再次輸入 上次的內容還保留在input框 -->保留上次輸入內容
1.1、error_messages
錯誤重寫
error_messages={
"required": "不能爲空", # 當請求爲空時提示
"invalid": "格式錯誤", # 格式錯誤
"min_length": "最少6位", # 最小長度
"max_length":" 最大N位" # 最大長度
}
1.2、password
pwd = forms.CharField(
label="密碼",
min_length=6,
error_messages={
"required": "不能爲空",
"invalid": "格式錯誤",
"min_length": "最少6位",
},
# widget=forms.widgets.PasswordInput() # 插件widgets
)
不加 widget=forms.widgets.PasswordInput()
加上widget=forms.widgets.PasswordInput()
增加類
pwd = forms.CharField(
label="密碼",
min_length=6,
error_messages={
"required": "不能爲空",
"invalid": "格式錯誤",
"min_length": "最少6位",
},
widget=forms.widgets.PasswordInput(
attrs={"class":"ap1"}
)
)
1.3選擇框
choices 單選框
hobby221 = forms.ChoiceField(
choices=((1,"吃飯"), (2,"睡覺"),(3,"做夢"),),
label="愛好",
initial=1,
widget=forms.widgets.Select()
)
MultipleChoiceField 多選框
hobby2 = forms.MultipleChoiceField(
choices=((1, "吃飯"), (2, "睡覺"), (3, "做夢"),),
label="多選愛好",
initial=3, # 初始化選擇框
widget=forms.widgets.SelectMultiple()
)
單選CheckboxInput
keep = forms.ChoiceField(
label="是否記住密碼",
initial="checked",
widget=forms.widgets.CheckboxInput()
)
多選框 CheckboxSelectMultiple
keep2 = forms.MultipleChoiceField(
choices=((1, "吃飯"), (2, "睡覺"), (3, "做夢"),),
label="多選愛好",
initial="checked", # 初始化選擇框
widget=forms.widgets.CheckboxSelectMultiple()
)
css中可以直接去掉li的點
2、實例
2.1、實例(form簡化版註冊)
1、Html頁面
<link rel="stylesheet" href="/static/bootstrap_3.3.7_css_bootstrap.min.css">
<div class="container">
<div class="row form-top">
<div class="col-md-5 col-sm-offset-3">
<form action="/reg/" method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label for={{ form_obj.name.id_for_label }}>{{ form_obj.name.label }}</label>
{{ form_obj.name }}
<span class="help-block">{{ form_obj.name.errors.0 }}</span>
</div>
<div class="form-group">
<label for={{ form_obj.passwd.id_for_label }}>{{ form_obj.passwd.label }}</label>
{{ form_obj.passwd }}
<span class="help-block">{{ form_obj.passwd.errors.0 }}</span>
</div>
<input type="submit" value="提交">
</form>
</div>
</div>
</div>
2、urls.py
urlpatterns = [
path("reg/", views.reg),
]
3、html_form.py
在應用下創建html_form.py文件
# 導入模塊,並且繼承引用
from django import forms
class RegForm(forms.Form):
name = forms.CharField(
label="帳號:",
min_length=6,
error_messages={
"min_length": "最小長度爲6",
"required": "輸入不能爲空",
},
widget=forms.widgets.Input(
attrs=({"class":"form-control"})
)
)
passwd = forms.CharField(
label="密碼",
min_length=6,
max_length=16,
error_messages={
"min_length": "最小長度爲6",
"max_length": "超過最大長度",
"required": "輸入不能爲空",
},
widget=forms.widgets.PasswordInput(
attrs=({"class":"ap1 form-control"})
),
)
4、models.py文件 創建一個用戶註冊使用的數據庫
from django.db import models
# Create your models here.
class UserRegister(models.Model):
name = models.CharField(max_length=16, unique=True, null=False)
passwd = models.CharField(max_length=16, null=False)
控制檯下使用
python manage.py makemigrations
python manage.py migrate 創建數據庫
5、views.py 視圖函數
from django.shortcuts import render, redirect, HttpResponse
from login.html_forms import RegForm
from login import models
def reg(request):
form_obj = RegForm() # 初始化類
if request.method == "POST": # 當它是post時才執行這個
form_obj = RegForm(request.POST)
if form_obj.is_valid(): # 當輸入的檢驗通過時才繼續往下執行
# cleaned_data (當校驗通過時forms字典,類似於各種request.POST.get("xxxxxx"))
form_register_list = form_obj.cleaned_data
# 獲取用戶是否存在數據庫中,如果存在就返回註冊界面,如果不存在就創建
ret = models.UserRegister.objects.filter(name=form_register_list.get("name"))
print(ret)
if ret:
return redirect("/reg/")
else:
models.UserRegister.objects.create(**form_register_list)
return HttpResponse("註冊成功")
return render(request, "reg.html", {"form_obj": form_obj})
2.2、校驗判斷用戶及密碼
1、html頁面
<div class="container">
<div class="row form-top">
<div class="col-md-5 col-sm-offset-3">
<form action="/reg/" method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label for={{ form_obj.name.id_for_label }}>{{ form_obj.name.label }}</label>
{{ form_obj.name }}
<span class="help-block">{{ form_obj.name.errors.0 }}</span>
</div>
<div class="form-group">
<label for={{ form_obj.pwd.id_for_label }}>{{ form_obj.pwd.label }}</label>
{{ form_obj.pwd }}
<span class="help-block">{{ form_obj.pwd.errors.0 }}</span>
</div>
<div class="form-group">
<label for={{ form_obj.re_pwd.id_for_label }}>{{ form_obj.re_pwd.label }}</label>
{{ form_obj.re_pwd }}
<span class="help-block">{{ form_obj.re_pwd.errors.0 }}</span>
</div>
<input type="submit" value="提交">
</form>
</div>
</div>
</div>
2、urls.py 不變
3、html_forms.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django import forms
from login import models
from django.core.exceptions import ValidationError
class RegForm(forms.Form):
name = forms.CharField(
label="帳號:",
min_length=6,
error_messages={
"min_length": "最小長度爲6",
"required": "輸入不能爲空",
},
widget=forms.widgets.Input(
attrs=({"class": "form-control"})
)
)
pwd = forms.CharField(
label="密碼",
min_length=6,
max_length=16,
error_messages={
"min_length": "最小長度爲6",
"max_length": "超過最大長度",
"required": "輸入不能爲空",
},
widget=forms.widgets.PasswordInput(
attrs=({"class":"form-control"}),
# 失敗不清空
render_value=True,
),
)
re_pwd = forms.CharField(
label="確認密碼",
min_length=6,
max_length=16,
error_messages={
"min_length": "最小長度爲6",
"max_length": "超過最大長度",
"required": "輸入不能爲空",
},
widget=forms.widgets.PasswordInput(
attrs=({"class":" form-control"}),
render_value=True,
),
)
# 鉤子函數,調用hasattr反射函數
def clean_name(self):
name = self.cleaned_data.get("name")
ret = models.UserRegister.objects.filter(name=name)
if ret:
raise ValidationError("用戶已存在")
return name
# 鉤子函數, 獲取兩次密碼,並讓它相比較
def clean(self):
pwd = self.cleaned_data.get("pwd")
re_pwd = self.cleaned_data.get("re_pwd")
print(self.cleaned_data)
if pwd != re_pwd:
# 如果不添加add_error那麼 print(form.error) <ul class="errorlist"><li>__all__<ul class="errorlist nonfield"><li>二次密碼不一致</li></ul></li></ul>
self.add_error("pwd", ValidationError("兩次密碼不一致"))
raise ValidationError("二次密碼不一致")
return self.cleaned_data
4、view.py
from django.shortcuts import render, redirect, HttpResponse
from login.html_forms import RegForm
from login import models
# Create your views here.
def cz_login(request):
print(request.GET)
return render(request, "index.html")
def reg(request):
form_obj = RegForm()
if request.method == "POST":
form_obj = RegForm(request.POST) # 實例化將數據輸入
if form_obj.is_valid():
form_register_list = form_obj.cleaned_data
form_register_list.pop("re_pwd")
models.UserRegister.objects.create(**form_register_list)
return HttpResponse("註冊成功")
print(form_obj.errors)
return render(request, "reg.html", {"form_obj": form_obj})
最終效果
2.3、使用form提交的大致完整註冊界面
目錄文件
1、settings.py
# 靜態文件定義
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
# auth擴展模塊,如果手動定義需要增加這個
AUTH_USER_MODEL = 'app01.UserInfo'
2、formd.py 定義forms 生成html頁面
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django import forms
from app01 import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
class RgeForm(forms.Form):
username = forms.CharField(
label="用戶名",
max_length=16,
error_messages={
"required": "帳號不能爲空",
"max_length": "最大長度16",
},
widget=forms.widgets.Input(
attrs={
"class": "form-control",
}
)
)
password = forms.CharField(
label="密碼",
min_length=6,
error_messages={
"required": "不能爲空",
"invalid": "格式錯誤",
"min_length": "最少6位",
},
widget=forms.widgets.PasswordInput(
attrs={
"class":"form-control",
},
render_value=True, # 密碼如果輸入錯誤,不清空
)
)
re_password = forms.CharField(
label="確認密碼",
min_length=6,
error_messages={
"required": "不能爲空",
"invalid": "格式錯誤",
"min_length": "最少6位",
},
widget=forms.widgets.PasswordInput(
attrs={
"class":"form-control",
},
render_value=True,
)
)
phone = forms.CharField(
label="手機號碼",
min_length=11,
max_length=11,
validators=[RegexValidator(r'^[1][1-9]+$',"格式錯誤")],
error_messages={
"required": "不能爲空",
# "invalid": "格式錯誤",
"min_length": "最少11位",
"max_length": "最大11位",
},
widget=forms.widgets.TextInput(
attrs={
"class":"form-control",
}
)
)
email = forms.CharField(
label="郵箱",
min_length=11,
max_length=11,
error_messages={
"required": "不能爲空",
},
widget=forms.widgets.TextInput(
attrs={
"class":"form-control",
}
)
)
# 判斷密碼是否一致, 如果不一致增加錯誤提示
def clean(self):
password = self.cleaned_data.get("password")
re_password = self.cleaned_data.get("re_password")
if password != re_password:
self.add_error("password","二次密碼不一致")
raise ValidationError("二次密碼不一致")
return self.cleaned_data
# 判斷用戶是否存在
def clean_username(self):
username = self.cleaned_data.get("username")
ret = models.UserInfo.objects.filter(username=username)
if ret:
self.add_error("username","用戶已存在")
raise ValidationError("用戶已存在")
return username
3、html頁面 reg2.html
<head>
<meta charset="UTF-8">
<title>reg</title>
<link rel="stylesheet" href="/static/bootstrap/bootstrap-3.3.1.min.css">
<style>
.form-top {
margin-top: 50px;
}
</style>
</head>
<body>
<div class="container">
<div class="row form-top">
<div class="col-md-6 col-md-offset-3">
<form action="/regs2/" method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label for={{ form_obj.username.id_for_label }}>{{ form_obj.username.label }}</label>
{{ form_obj.username }}
<span class="help-block">{{ form_obj.username.errors.0 }}</span>
</div>
<div class="form-group">
<label for={{ form_obj.password.id_for_label }}>{{ form_obj.password.label }}</label>
{{ form_obj.password }}
<span class="help-block">{{ form_obj.password.errors.0 }}</span>
</div>
<div class="form-group">
<label for={{ form_obj.re_password.id_for_label }}>{{ form_obj.re_password.label }}</label>
{{ form_obj.re_password }}
<span class="help-block">{{ form_obj.password.errors.0 }}</span>
</div>
<div class="form-group">
<label for={{ form_obj.phone.id_for_label }}>{{ form_obj.phone.label }}</label>
{{ form_obj.phone }}
<span class="help-block">{{ form_obj.phone.errors.0 }}</span>
</div>
<div class="form-group">
<label for={{ form_obj.email.id_for_label }}>{{ form_obj.email.label }}</label>
{{ form_obj.email }}
<span class="help-block">{{ form_obj.email.errors.0 }}</span>
</div>
<input type="submit" value="提交">
</form>
</div>
</div>
</div>
4、views.py
from django.shortcuts import render, redirect, HttpResponse
from app01 import formd
from app01 import models
# Create your views here.
def register2(request):
form_obj = formd.RgeForm()
if request.method == "POST":
form_obj = formd.RgeForm(request.POST) # django自動生成的 html頁面
print(form_obj) #<tr><th><label for="id_name">用戶名:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="name" maxlength="16" required id="id_name" /></td></tr>
if form_obj.is_valid(): # 如果返回true就繼續執行
form_userinfo_list = form_obj.cleaned_data
form_userinfo_list.pop("re_password")
models.UserInfo.objects.create_user(**form_userinfo_list)
return HttpResponse("用戶註冊成功")
return render(request, "reg2.html", {"form_obj": form_obj})
5、models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserInfo(AbstractUser):
"""
用戶擴展表
"""
phone = models.CharField(max_length=11, null=True) # 允許爲空
addr = models.CharField(max_length=200, null=True)
def __str__(self):
return self.phone
MVC 說明
MTV 說明
FAQ
在settings.py中修改
LANGUAGE_CODE = "zh-hans" 後臺會顯示爲中文 當時間會提前8小時
\# TIME_ZONE = 'UTC' 將UTC修改成上海時間就能解決
TIME_ZONE='Asia/Shanghai'