Django的Form主要具備一下幾大功能:javascript
後臺邏輯(導包+建類)css
from django.shortcuts import render,redirect,HttpResponse from django import forms from django.forms import fields class F1Form(forms.Form): user=fields.CharField( required=True, min_length=6, max_length=16, error_messages={ 'required':'用戶名不能爲空', 'min_length':'至少爲6個字符', 'max_length': '最多爲16個字符', } ) pwd = fields.CharField( required=True, min_length=6, max_length=16, error_messages={ 'required': '密碼不能爲空', 'min_length': '至少爲6個字符', 'max_length': '最多爲16個字符', } ) age = fields.IntegerField( required=True, error_messages={ 'required': '年齡不能爲空', 'invalid': '年齡格式不正確', } ) email = fields.EmailField( required=True, min_length=6, max_length=18, error_messages={ 'required': '郵箱不能爲空', 'min_length': '至少爲6個字符', 'max_length': '最多爲18個字符', 'invalid': '郵箱格式不正確', } ) def f1(request): if request.method=="GET": obj=F1Form() return render(request,'f1.html',{'obj':obj}) else: obj = F1Form(request.POST) # 校驗是否成功 if obj.is_valid(): return redirect('http://www.baidu.com') else: return render(request,'f1.html',{'obj':obj})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.css"> </head> <body> <form id="fm" action="/f1.html" method="POST"> <p>{{obj.user}}{{ obj.errors.user.0 }}</p> <p>{{obj.pwd}}{{ obj.errors.pwd.0 }}</p> <p>{{obj.age}}{{ obj.errors.age.0 }}</p> <p>{{obj.email}}{{ obj.errors.email.0 }}</p> <input type="submit" value="提交"/> </form> <script src="/static/js/jquery-3.3.1.min.js"></script> </body> </html>
小試牛刀:實現一套「增刪改」 html
1:建立Model模型並生成數據表前端
from django.db import models # Create your models here. class UserInfo(models.Model): username=models.CharField(max_length=16) email = models.EmailField(max_length=16)
2:建立Form文件java
from django import forms from django.forms import fields class UserInfoForm(forms.Form): username = forms.CharField( required=True, max_length=16, error_messages={ "required": "姓名不能爲空", "max_length": '姓名最大長度不能超過16位' } ) email = forms.EmailField( required=True, min_length=6, error_messages={ "required": "郵箱不能爲空", "min_length": '郵箱最小長度不能低於6位', "invalid":"郵箱格式不正確" })
3:建立View文件並修改url配置 python
from django.shortcuts import render, redirect, HttpResponse from App01.models import UserInfo from App01.Forms.UserInfo import UserInfoForm def user_list(request): # 獲取用戶信息列表 obj = UserInfo.objects.all() return render(request, "FormTest/user_list.html", {"obj": obj}) def user_add(request): # 添加用戶 if request.method == 'GET': obj = UserInfoForm() return render(request, "FormTest/user_add.html", {"obj": obj}) else: obj = UserInfoForm(request.POST) if obj.is_valid(): UserInfo.objects.create(**obj.cleaned_data) return redirect('/user_list') else: return render(request, "FormTest/user_add.html", {"obj": obj}) def user_edit(request,nid): # 編輯用戶 if request.method == 'GET': enti = UserInfo.objects.filter(id=nid).first() obj = UserInfoForm({"username":enti.username,"email":enti.email}) return render(request, "FormTest/user_edit.html", {"obj": obj,"nid":nid}) else: obj = UserInfoForm(request.POST) if obj.is_valid(): UserInfo.objects.filter(id=nid).update(**obj.cleaned_data) return redirect('/user_list') else: return render(request, "FormTest/user_edit.html", {"obj": obj, "nid": nid}) def user_del(request): # 刪除用戶 if request.method=='GET': nid = request.GET.get("nid") UserInfo.objects.filter(id=nid).delete() return redirect("/user_list")
"""StudyForm URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.1/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path from django.conf.urls import url from App01.Views import FormTest urlpatterns = [ path('admin/', admin.site.urls), url(r'^user_list', FormTest.user_list), url(r'^user_add', FormTest.user_add), url(r'^user_edit-(\d+)', FormTest.user_edit), url(r'^user_del', FormTest.user_del), ]
4:HTML頁面 jquery
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <a href="/user_add">添加</a> <table id="tbStudentsList" class="table table-hover table-bordered"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>郵箱</th> <th>操做</th> </tr> </thead> <tbody> {% for row in obj %} <tr nid="{{ row.id }}"> <td>{{ row.id }}</td> <td>{{ row.username }}</td> <td>{{ row.email }}</td> <td> <a href="user_edit-{{ row.id }}">修改</a> | <a href="user_del?nid={{ row.id }}">刪除</a> </td> </tr> {% endfor %} </tbody> </table> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user_add/" method="post" novalidate> {% csrf_token %} <p>{{ obj.username }}{{ obj.errors.username.0 }}</p> <p>{{ obj.email }}{{ obj.errors.email.0 }}</p> <input type="submit" value="提交"/> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user_edit-{{ nid }}/" method="post" novalidate> {% csrf_token %} <p>{{ obj.username }}{{ obj.errors.username.0 }}</p> <p>{{ obj.email }}{{ obj.errors.email.0 }}</p> <input type="submit" value="提交"/> </form> </body> </html>
Form組件 進階篇git
Field required=True, 是否容許爲空 widget=None, HTML插件 label=None, 用於生成Label標籤或顯示內容 initial=None, 初始值 help_text='', 幫助信息(在標籤旁邊顯示) error_messages=None, 錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'} show_hidden_initial=False, 是否在當前插件後面再加一個隱藏的且具備默認值的插件(可用於檢驗兩次輸入是否一直) validators=[], 自定義驗證規則 localize=False, 是否支持本地化 disabled=False, 是否能夠編輯 label_suffix=None Label內容後綴 CharField(Field) max_length=None, 最大長度 min_length=None, 最小長度 strip=True 是否移除用戶輸入空白 IntegerField(Field) max_value=None, 最大值 min_value=None, 最小值 FloatField(IntegerField) ... DecimalField(IntegerField) max_value=None, 最大值 min_value=None, 最小值 max_digits=None, 總長度 decimal_places=None, 小數位長度 BaseTemporalField(Field) input_formats=None 時間格式化 DateField(BaseTemporalField) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 DurationField(Field) 時間間隔:%d %H:%M:%S.%f ... RegexField(CharField) regex, 自定製正則表達式 max_length=None, 最大長度 min_length=None, 最小長度 error_message=None, 忽略,錯誤信息使用 error_messages={'invalid': '...'} EmailField(CharField) ... FileField(Field) allow_empty_file=False 是否容許空文件 ImageField(FileField) ... 注:須要PIL模塊,pip3 install Pillow 以上兩個字典使用時,須要注意兩點: - form表單中 enctype="multipart/form-data" - view函數中 obj = MyForm(request.POST, request.FILES) URLField(Field) ... BooleanField(Field) ... NullBooleanField(BooleanField) ... ChoiceField(Field) ... choices=(), 選項,如:choices = ((0,'上海'),(1,'北京'),) required=True, 是否必填 widget=None, 插件,默認select插件 label=None, Label內容 initial=None, 初始值 help_text='', 幫助提示 ModelChoiceField(ChoiceField) ... django.forms.models.ModelChoiceField queryset, # 查詢數據庫中的數據 empty_label="---------", # 默認空顯示內容 to_field_name=None, # HTML中value的值對應的字段 limit_choices_to=None # ModelForm中對queryset二次篩選 ModelMultipleChoiceField(ModelChoiceField) ... django.forms.models.ModelMultipleChoiceField TypedChoiceField(ChoiceField) coerce = lambda val: val 對選中的值進行一次轉換 empty_value= '' 空值的默認值 MultipleChoiceField(ChoiceField) ... TypedMultipleChoiceField(MultipleChoiceField) coerce = lambda val: val 對選中的每個值進行一次轉換 empty_value= '' 空值的默認值 ComboField(Field) fields=() 使用多個驗證,以下:即驗證最大長度20,又驗證郵箱格式 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field) PS: 抽象類,子類中能夠實現聚合多個字典去匹配一個值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField) input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'] input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField) 文件選項,目錄下文件顯示在頁面中 path, 文件夾路徑 match=None, 正則匹配 recursive=False, 遞歸下面的文件夾 allow_files=True, 容許文件 allow_folders=False, 容許文件夾 required=True, widget=None, label=None, initial=None, help_text='' GenericIPAddressField protocol='both', both,ipv4,ipv6支持的IP格式 unpack_ipv4=False 解析ipv4地址,若是是::ffff:192.0.2.1時候,可解析爲192.0.2.1, PS:protocol必須爲both才能啓用 SlugField(CharField) 數字,字母,下劃線,減號(連字符) ... UUIDField(CharField) uuid類型 ...
其中經常使用的是:ajax
1:label
=
None
,用於生成Label標籤或顯示內容。但也有其侷限性,就是修改起來不方便。
正則表達式
{ obj.username.label }}
2:validators
=
[],自定義驗證規則。須要注意引入驗證模板
from django.core.validators import RegexValidator
3:自定義擴展
3.1 驗證某個字段,例如判斷用戶是否存在。經過clean_字段名
from django import forms from django.forms import fields from django.forms import widgets from django.core.exceptions import ValidationError from django.core.validators import RegexValidator class FInfo(forms.Form): username = fields.CharField(max_length=5, validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], ) email = fields.EmailField() def clean_username(self): #自定義方法 clean_字段名 #必須有返回值 value #若是出錯,就拋出異常ValidationError value = self.cleaned_data['username'] if "666" in value: raise ValidationError('用戶名已存在', 'invalid') return value
3.2 驗證多個字段,例如判斷用戶兩次輸入的密碼是否一致
class AccountInfoForm(forms.Form): username = fields.CharField( required=True, label='用戶名:', min_length=6, max_length=16, error_messages={ 'required': '用戶名不能爲空', 'min_length': '至少爲6個字符', 'max_length': '最多爲16個字符', } ) pwd = fields.CharField( label='密碼:', required=True, min_length=6, max_length=16, validators=[RegexValidator(r'^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$\%\^\&\*\(\)])[0-9a-zA-Z!@#$\%\^\&\*\(\)]{8,32}$','密碼過於簡單(包含數字、字母的8位以上數字)')], error_messages={ 'required': '密碼不能爲空', 'min_length': '至少爲6個字符', 'max_length': '最多爲16個字符', } ) confirmPwd = fields.CharField( label='確認密碼:', required=True, min_length=6, max_length=16, error_messages={ 'required': '密碼不能爲空', 'min_length': '至少爲6個字符', 'max_length': '最多爲16個字符', } ) email = fields.EmailField( label='郵箱:', required=True, min_length=6, max_length=18, error_messages={ 'required': '郵箱不能爲空', 'min_length': '至少爲6個字符', 'max_length': '最多爲18個字符', 'invalid': '郵箱格式不正確', } ) def clean(self): value_data = self.cleaned_data v1=value_data.get("pwd") v2=value_data.get("confirmPwd") if v1 != v2: self.add_error("confirmPwd", "密碼不一致") raise ValidationError("密碼不一致") return self.cleaned_data
三種ajax請求(jQuery封裝後的ajax+原生的ajax+僞ajax(form+iframe))
"""StudyForm URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.1/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path from django.conf.urls import url from App01.Views import FormTest,UploadTest,AjaxTest urlpatterns = [ path('admin/', admin.site.urls), url(r'^user_list', FormTest.user_list), url(r'^user_add', FormTest.user_add), url(r'^user_edit-(\d+)', FormTest.user_edit), url(r'^user_del', FormTest.user_del), # 文件上傳 url(r'^upload.html$', UploadTest.upload), #Ajax練習 # 1、普通的form提交+jQuery封裝後的Ajax url(r'^ajax1.html$', AjaxTest.ajax1), url(r'^ajax11.html$', AjaxTest.ajax11), #2、原生態的Ajax url(r'^ajax2.html$', AjaxTest.ajax2), #3、僞Ajax(form+iframe) url(r'^ajax3.html$', AjaxTest.ajax3), # 文件上傳 url(r'^ajaxUpload$', AjaxTest.ajaxUpload), ]
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="/static/js/jquery-3.3.1.min.js"></script> </head> <body> {% csrf_token %} <form action="ajax1.html" method="post"> <input type="text" id="ajaxText" name="ajaxText" placeholder="請輸入測試數據" value="{{ qMethod }}"> <input type="submit" value="普通提交"> <br/> <input type="button" value="JQuery封裝ajaxGET提交" onclick="ajax1Get()"> <input type="button" value="JQuery封裝ajaxPOST提交" onclick="ajax1Post()"> <br/> <input type="button" value="原生的ajaxGET提交" onclick="nativeAjax1Get()"> <input type="button" value="原生的ajaxPOST提交" onclick="nativeAjax1Post()"> <br/> </form> <iframe id="iframe" name="ifra"></iframe> <form id="fm" action="/ajax3.html" method="POST" target="ifra"> <input type="text" id="aText" name="aText" placeholder="請輸入測試數據" value="{{ qMethod }}"> <input type="button" value="僞ajaxPOST提交" onclick="fakeAjax1Post()"> <br/> </form> <hr/> <iframe id="uploadFR" name="uploadFR" style="display: none"></iframe> <form id="uploadFM" name="uploadFM" method="post" action="ajaxUpload" enctype="multipart/form-data" target="uploadFR"> <input type="file" id="img" name="val"> <input type="button" value="經過ajax+formData上傳" onclick="upload1()"> <input type="button" value="經過原生xhr+formData上傳" onclick="upload2()"> <input type="button" value="僞ajax上傳" onclick="upload3()"> </form> <script> function ajax1Get() { {#jQuery封裝後的ajax-get#} var st = $("#ajaxText").val(); var soft = {'ajaxTest': st} $.ajax({ url: 'ajax11.html', type: 'GET', dataType: 'json', data: soft, success: function (arg) { alert(arg.data) } }) } function ajax1Post() { {#jQuery封裝後的ajax-post#} var st = $("#ajaxText").val(); $.ajax({ url: 'ajax11.html', type: 'POST', dataType: 'json', data: {"ajaxTest": st}, success: function (arg) { alert(arg.data) } }) } function nativeAjax1Get() { {#1:建立對象#} var xhr = new XMLHttpRequest() {#2:建立句柄對象#} xhr.onreadystatechange = function () { {#4LoadedHTTP 響應已經徹底接收。#} if (xhr.readyState == 4) { alert(xhr.responseText) } } {#3:設置請求方式,指定url路徑#} var st = $("#ajaxText").val(); xhr.open("GET", "ajax2.html?ajaxTest=" + st) {#4:發送#} xhr.send() } function nativeAjax1Post() { {#1:建立對象#} var xhr = new XMLHttpRequest() {#2:建立句柄對象#} xhr.onreadystatechange = function () { {#4LoadedHTTP 響應已經徹底接收。#} if (xhr.readyState == 4) { alert(xhr.responseText) } } {#3:設置請求方式,指定url路徑#} var st = $("#ajaxText").val(); xhr.open("POST", "ajax2.html") xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8'); {#4:發送#} xhr.send("ajaxTest=" + st) } function fakeAjax1Post() { document.getElementById("iframe").onload = reloadIframe; var form1 = document.getElementById('fm'); form1.submit(); } function reloadIframe() { var countent = this.contentWindow.document.body.innerHTML var obj = JSON.parse(countent) if (obj.status) { alert(obj.message) } } function upload1() { var dataForm = new FormData() dataForm.append("val", document.getElementById("img").files[0]) $.ajax({ url: "ajaxUpload", type: "POST", data: dataForm, success: function (arg) { alert("ajax上傳文件成功") }, processData: false, // tell jQuery not to process the data contentType: false // tell jQuery not to set contentType }) } function upload2() { var dataForm = new FormData() dataForm.append("val", document.getElementById("img").files[0]) var xhr = new XMLHttpRequest() xhr.onreadystatechange = function () { {#4LoadedHTTP 響應已經徹底接收。#} if (xhr.readyState == 4) { alert("原生ajax上傳文件成功") } } xhr.open("POST", "ajaxUpload") xhr.send(dataForm) } function upload3(){ document.getElementById("uploadFR").onload=reloadIframe var form1 = document.getElementById('uploadFM'); form1.submit(); } </script> </body> </html>
from django.shortcuts import HttpResponse,render import os,uuid import json def ajax1(request): if request.method=="GET": QMethod='普通的get請求' return render(request,"AjaxTest/ajax1.html",{"qMethod":QMethod}) else: QMethod = '普通的Post請求------'+request.POST.get("ajaxText") return render(request,"AjaxTest/ajax1.html",{"qMethod":QMethod}) def ajax11(request): if request.method=="GET": QMethod = 'Ajax的get請求------' + request.GET.get("ajaxTest") ret = {'status': True, 'data': QMethod, 'message': QMethod} return HttpResponse(json.dumps(ret)) else: QMethod = 'Ajax的Post請求------'+ request.POST.get("ajaxTest") ret = {'status': True, 'data': QMethod, 'message': QMethod} return HttpResponse(json.dumps(ret)) def ajax2(request): if request.method=="GET": QMethod="原生的Ajax的get請求-----"+request.GET.get("ajaxTest") return HttpResponse(QMethod) else: QMethod = "原生的Ajax的post請求-----" + request.POST.get("ajaxTest") return HttpResponse(QMethod) def ajax3(request): if request.method == "GET": QMethod = '僞Ajax的get請求------' + request.GET.get("aText") ret = {'status': True, 'data': QMethod, 'message': QMethod} return render(request, "AjaxTest/ajax1.html", {"qMethod": QMethod}) else: QMethod = '僞Ajax的Post請求------'+request.POST.get("aText") ret = {'status': True, 'data': QMethod, 'message': QMethod} return HttpResponse(json.dumps(ret)) def ajaxUpload(request): # 經過uuid獲取到自動編號,防止重複 nid = str(uuid.uuid4()) # 經過request獲取上傳對象 obj=request.FILES.get("val") # 寫文件 file_path=os.path.join("static/files",nid+obj.name) f = open(file_path,'wb') for line in obj.chunks(): f.write(line) f.close() ret = {'status': True, 'data': None, 'message': None} ret["data"]=file_path #返回 return HttpResponse(json.dumps(ret))
附件上傳
from django.shortcuts import render, redirect, HttpResponse def upload(request): if request.method=="GET": return render(request, 'UploadTest/upload.html') else: user = request.POST.get("user") img=request.FILES.get('img') f=open(img.name,'wb') for line in img.chunks(): f.write(line) f.close() return render(request, 'UploadTest/upload.html')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="upload.html" method="post" enctype="multipart/form-data"> {% csrf_token %} <input type="text" name="user"/> <div style="position: relative"> <a>上傳</a> <input type="file" name="img" style="opacity: 0;position:absolute;top:0;left: 0;"/> </div> <input type="submit" value="提交"/> </form> </body> </html>
與 三種ajax請求類似,一樣存在三種附件上傳(代碼內容已包含在裏面)
Jsonp 示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="/static/js/jquery-3.3.1.min.js"></script> </head> <body> <input type="button" value="jsonp測試" onclick="submitJsonp()"/> <script> function submitJsonp() { $.ajax({ {#江西衛視的jsonp只能使用固定的callback函數list()#} {#url: "http://www.jxntv.cn/data/jmd-jxtv2.html",#} url: "https://sug.so.360.cn/suggest", type: 'GET', dataType: 'jsonp', jsonp: 'callback', jsonpCallback: 'func', }) } function func(arg) { alert("可自定義jsonpCallback的函數函數名稱") } </script> </body> </html>
from django.shortcuts import HttpResponse,render def jsonp(request): print(1111) return render(request, "JsonpTest/jsonp.html", {"qMethod": "123456"})