form表单在传输编码格式有两种: 1.urlencoded,2 multipart/form-data
在不指定编码的情况下,默认使用urlencoded,他只能传输文本格式的信息,如果传文件的话只能传文件的名称过去。并不能传输文件内容过去,使用form表单同时提交文本和文件也是可以的,我们将编码格式转为 multipart/form-data
就可以实现同时传输文本,和文件
<form action="" method="post" enctype="multipart/form-data">
form表单和ajax支持的编码格式有两个是相同的,两者都支持urlencoded和form-data,在Ajax中还支持json编码格式:
Ajax传输数据:
Ajax发送json格式数据 $.ajax({ url:'', // 不写默认朝当前页面所在的url地址提交 type:'post', contentType:'application/json', data:JSON.stringify({'name':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}), success:function (data) { alert(data) } })
后台代码:
def index(request): bytes_str = request.body res = json.loads(bytes_str.decode('utf-8')) print(res) return render(request,'index.html')
ajax同时传输数据和文件:
$('#d1').click(function () { // 如果用ajax发送文件 需要使用内置对象FormData var formData = new FormData(); // 生成一个内置对象 // 内置对象formdata既可以传普通的键值对,也可以传文件 formData.append('name','jason'); // 普通键值对 formData.append('password','123'); // 传文件 var fileObj = $('#d2')[0].files[0]; // 先获取标签对象 转成原生js对象 通过内置的files方法拿到列表 然后去索引0拿到文件对象 formData.append('myfile',fileObj); $.ajax({ url:'', // 不写默认朝当前页面所在的url地址提交 type:'post', // 注意ajax在发送文件的时候 需要你手动指定两个特殊的参数 contentType:false, // 不要用任何编码 使用我formdata自带的编码即可 processData:false, // 浏览器不要处理我的数据 是什么就什么 data:formData, success:function (data) { alert(data) } }) })
后台代码:
def index(request): if request.method == 'POST': print(request.POST) print(request.FILES) file_obj = request.FILES.get('myfile') with open(file_obj.name,'wb') as f: for line in file_obj: f.write(line) return render(request,'index.html')
form组件
form组件主要是帮助我们完成三件事:1 校验前台数据 2 渲染前台页面给用户提供输入条件 3 将数据处理后的结果展示给用户看
用form组件写用户注册。
1 导入模块包
from django import forms
创建form组件模型表
class MyForm(forms.Form): name = forms.CharField(max_length=6,label='用户名', error_messages = {'max_length':'用户名最大6位','required':'用户名不能为空'}) password = forms.CharField(max_length=8,min_length=3,label='密码', error_messages={'max_length':'密码最大为8位',"min_length":'密码最少为3位','required':'密码不能为空'}) confirm_password = forms.CharField(max_length=8,min_length=3,label='再次确认密码', error_messages={'min_length':'密码最少3位','required': "密码不能为空"} ) def clean_name(self): name = self.cleaned_data.get('name') if 'sb' in name: self.add_error('name','用户名不能包含敏感词汇') return name def clean(self): password = self.cleaned_data.get('password') print(password) confirm_password = self.cleaned_data.get('confirm_password') print(confirm_password) if not password == confirm_password: self.add_error('confirm_password','两次密码不一致') return self.cleaned_data
其中两个函数方式用的钩子函数,可以在后台做前台用户输入信息的判断,数据校验对于前台来说,可以做也可以不做,后台是一定要做的,使用钩子函数可以实现这个需求。
注册函数,前台得到的数据我们可以直接使用request.post直接作为参数传进去,因为form组件模型表有一个特点,参数少传了不行,多的参数也不会进行校验:
def register(request): form_obj = MyForm() if request.method == 'POST': form_obj = MyForm(request.POST) if form_obj.is_valid(): print(form_obj.cleaned_data) return HttpResponse('注册成功') return render(request,'register.html',{"form_obj":form_obj})
前台页面渲染方式
方式1 缺点是封装的程度太高了,不方便以后扩展 :
{# {{ form_obj.as_p }}#} {# {{ form_obj.as_ul }}#}
方式2 优点是可扩展性高,但是书写起来太麻烦
<p> {{ form_obj.username.label }}{{ form_obj.username }} {# forms对象点字段名拿到的是对应的输入框 </p> <p> {{ form_obj.password.label }}{{ form_obj.password }} {# forms对象点字段名拿到的是对应的输入框 </p>
方式3 利用循环遍历通过对象点方法渲染前台页面,这种方法比较常用 :
{% for foo in form_obj %} <P> {{foo.label}}:{{foo}} <span>{{foo.errors.0}}</span> </P> {% endfor %}
当我们需要测试在本地测试时可以打开一个新的test.py文件,配置好文件后导入我们想要测试的模块即可。‘
django中测试脚本书写 import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day66.settings") import django django.setup() from app01 import models print(models.Userinfo.objects.all())
钩子函数可以分为两种局部钩子函数,全局钩子函数:
局部对应的某个字段,而全局钩子对应的是全局中的所有字段:
局部钩子:
def clean_name(self): name = self.cleaned_data.get('name') if 'sb' in name: self.add_error('name','用户名不能包含敏感词汇') return name
全局钩子函数:
def clean(self): password = self.cleaned_data.get('password') print(password) confirm_password = self.cleaned_data.get('confirm_password') print(confirm_password) if not password == confirm_password: self.add_error('confirm_password','两次密码不一致') return self.cleaned_data
在form组件中,我们可以通过一些方法,来查看用户输入的数据是否合法,哪些合法,哪些不合法以及报错原因:
3.查看数据是否完全合法 obj.is_valid() 4.查看所有校验通过的数据 obj.cleaned_data {'email': '123@qq.com'} 5.查看所有没有通过的数据 obj.errors """ { 'username': ['Ensure this value has at most 6 characters (it has 7).'], 'password': ['Ensure this value has at least 3 characters (it has 2).']} """