111
Posted bigbox
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了111相关的知识,希望对你有一定的参考价值。
本周安排 bbs全部结束 今日内容 forms组件 cookie与session操作 每日内容 django中间件 csrf跨站请求伪造 auth认证模块 bbs表设计 周三四五 bbs业务实现 2020年目标 坚持做一年 今年目标确立 2019年 难 = 又 + 佳 上周内容回顾 多对多三种创建方式 1.纯自动 第三张不需要你自己创建 由orm自动创建 class Book(models): title = ... authors = models.ManyToManyField(to=‘Author‘) class Author(models): name = ... # 第三表扩展性较差 2.纯手动 class Book(models.Model): title = ... class Author(models.Model): name = ... class Book2Author(modes.Model): book = 一对多关系Book authors = 一对多关系Author # orm查询那一块 没有正反向的概念 3.半自动 class Book(models.Model): title = ... authors = models.ManyToManyField(to=‘Author‘,through=‘Book2Author‘,through_fields=(‘book‘,‘authors‘)) class Author(models.Model): name = ... # books = models.ManyToManyField(to=‘Book‘,through=‘Book2Author‘,through_fields=(‘authors‘,‘book‘)) class Book2Author(modes.Model): book = 一对多关系Book authors = 一对多关系Author # 不支持add、remove、set、clear # 完全靠业务逻辑来将表关系绑定起来 ajax 异步提交、局部刷新 eg:github的注册页面 基于jQuery封装之后的版本 ajax基本语法结构 $.ajax({ url:‘‘, # 控制的是数据的提交路径 type:‘get/post‘, # 控制的是数据的提交方式 data:{‘usernamae‘:‘jason‘}, # 提交的数据 success:function(data){ # 一旦异步提交有结果了 自动触发该函数的运行 形参data就是用来接收结果的 ... } }) 前后端传输数据编码格式 urlencoded 数据格式 username=jason&password=123 是form表单和ajax默认的编码格式 django后端针对符合该格式的数据都会自动解析并放到request.POST中 formdata 即可以发送文件也可以继续发送普通键值对 django后端会将该编码格式中符合username=jason&password=123格式数据 还是解析放到request.POST中 而针对文件数据则会解析放到request.FILES application/json 传输的数据与编码格式一定要保持一致 不要骗人家 ajax发送jason格式数据 1.修改contentType参数 urlencoded >>> application/json 2.数据要处理成json格式 JSON.stringify() django后端针对json格式的数据 并不会做任何的处理操作 数据就以二进制的形式存放在request.body中 需要你自己手动处理该数据 其实jason.loads可以直接反序列化符合json格式的二进制数据 解码 + 反序列化 ajax发送文件 1.利用内置对象FormData 2.需要额外修改两个参数的值 processData:false contentType:false 3.data只需要放FormData生成的对象即可 如何往FormData的对象中添加数据 formdata_obj = new FormData() # 普通键值 formdata_obj.append(‘username‘,‘jason‘) formdata_obj.append(‘password‘,‘123‘) # 文件 formdata_obj.append(‘myfile‘,$(‘input[type="file"]‘)[0].files[0]) django后端能够自动识别FormData对象 django后端会将该编码格式中符合username=jason&password=123格式数据 还是解析放到request.POST中 而针对文件数据则会解析放到request.FILES ajax结合sweetalert 自己练习 批量插入数据 bulk_create() # 效率极低的 for i in range(1000): models.User.objects.create(**kwargs) # 效率提升N多倍 b_list = [] for i in range(100000): b_list.append(modes.User(**kwargs)) models.User.objects.bulk_create(b_list) 自定义分页器 推导思路 1.利用queryset对象支持切片操作 2.一页展示多少条数据 一共需要多少页 起始位和终止位 当前页 per_page_num start_page end_page current_page # 上面四个参数的数学关系 3.前端页面做一个分页器的样式 然后点击即可查看对应页 4.到底需要渲染多少页 divmod 5.如何限制前端页面展示的页码数 奇数位 自定义分页器的使用方法 1.将封装好的分页器代码直接拷贝 2. # 1.生成一个分页器对象 page_obj = Pagenation(current_page=request.GET.get(‘page‘,1),all_count=queryset.count()) # 2.对真正的数据进行切片操作 queryset_data = queryset[page_obj.start:page_obj.end] # 3.将切片之后的数据传递到前端页面 return render(request,‘list.html‘,{"data":queryset_data}) 3.前端 将原本页面上的queryset全部替换成queryset_data {{ page_obj.page_html|safe }} forms组件 小需求 我们写一个注册页面 获取用户输入的用户名和密码 用户点击注册发送到后端做用户名密码的校验 用户名中不能包含金瓶 不符合社会主义核心价值观 密码不能为空 你个DSB,密码怎么能为空 1.手写获取用户输入的前端页面代码 渲染页面 2.后端获取用户数据并做合法性校验 校验数据 3.将校验之后的结果渲染到前端页面 展示信息 forms组件 1.渲染页面 2.校验数据 3.展示信息 你需要先写一个类 from django import forms class MyRegForm(forms.Form): # 用户名最少3位最多8位 username = forms.CharField(max_length=8,min_length=3) password = forms.CharField(max_length=8,min_length=3) # email字段必须填写符合邮箱格式的数据 email = forms.EmailField() 如何校验数据 # 1.传入待校验的数据 用自己写的类 传入字典格式的待校验的数据 form_obj = views.MyRegForm({‘username‘:‘jason‘,‘password‘:‘12‘,‘email‘:‘123456‘}) # 2.判断数据是否符合校验规则 form_obj.is_valid() # 该方法只有在所有的数据全部符合校验规则才会返回True False # 3.如何获取校验之后通过的数据 form_obj.cleaned_data {‘username‘: ‘jason‘} # 4.如何获取校验失败及失败的原因 form_obj.errors { ‘password‘: [‘Ensure this value has at least 3 characters (it has 2).‘], ‘email‘: [‘Enter a valid email address.‘] } Out[16]: {} # 5.注意 forms组件默认所有的字段都必须传值 也就意味着传少了是肯定不行的 而传多了则没有任何关系 只校验类里面写的字段 多传的直接忽略了 form_obj = views.MyRegForm({‘username‘: ‘jason‘, ‘password‘: ‘123456‘}) form_obj.is_valid() Out[12]: False form_obj.errors Out[18]: {‘email‘: [‘This field is required.‘]} form_obj = views.MyRegForm({‘username‘: ‘jason‘, ‘password‘: ‘123456‘, "email": ‘123@qq.com‘, "hobby": ‘hahahaha‘}) form_obj.is_valid() Out[14]: True form_obj.cleaned_data Out[15]: {‘username‘: ‘jason‘, ‘password‘: ‘123456‘, ‘email‘: ‘123@qq.com‘} form_obj.errors 如何渲染页面 你需要先写一个类 forms组件只帮你渲染获取用户输入(输入 选择 下拉 文件)的标签 不渲染按钮和form表单标签 渲染出来的每一个input提示信息都是类中字段首字母大写 <p>第一种渲染方式:多个p标签 本地测试方便 封装程度太高了 不便于扩展</p> {{ form_obj.as_p }} {{ form_obj.as_ul }} {{ form_obj.as_table }} <p>第二种渲染方式: 扩展性较高 书写较为繁琐</p> <label for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label> {{ form_obj.username }} {{ form_obj.password.label }}{{ form_obj.password }} {{ form_obj.email.label }}{{ form_obj.email }} <p>第三种渲染方式 推荐使用</p> {% for form in form_obj %} <p> {{ form.label }}{{ form }}</p> {% endfor %} 如何渲染错误信息 前端 <form action="" method="post" novalidate> {% for form in form_obj %} <p> {{ form.label }}{{ form }} <span>{{ form.errors.0 }}</span> # 这个是模板语法 索引不会出现超出报错 </p> {% endfor %} <input type="submit"> </form> 后端 def reg(request): # 1 先生成一个空的类对象 form_obj = MyRegForm() if request.method == ‘POST‘: # 3 获取用户数据并交给forms组件校验 request.POST form_obj = MyRegForm(request.POST) # 4 获取校验结果 if form_obj.is_valid(): return HttpResponse(‘数据没问题‘) else: # 5 获取校验失败的字段和提示信息 print(form_obj.errors) # 2 直接将该对象传给前端页面 return render(request,‘reg.html‘,locals()) 数据校验一个前后端都得有 但是前端的校验弱不禁风 可有可无 而后端的校验则必须非常全面 如何取消浏览器自动帮我们校验的功能 form表单取消前端浏览器自动校验功能 <form action="" method="post" novalidate> 常用参数 label input的提示信息 error_messages 自定义报错的提示信息 required 设置字段是否允许为空 initial 设置默认值 widget 控制type类型及属性 widget=forms.widgets.TextInput(attrs={‘class‘:‘form-control c1 c2‘}) widget=forms.widgets.PasswordInput(attrs={‘class‘:‘form-control‘}) 钩子函数 全局钩子(针对多个字段) 校验密码与确认面是否一致 局部钩子(针对单个字段) 校验用户名中不能包含666 # 全局钩子 def clean(self): # 校验密码和确认密码是否一致 password = self.cleaned_data.get(‘password‘) confirm_password = self.cleaned_data.get(‘confirm_password‘) if not password == confirm_password: # 展示提示信息 self.add_error(‘confirm_password‘,‘两次密码不一致‘) return self.cleaned_data # 局部钩子 def clean_username(self): username = self.cleaned_data.get(‘username‘) if ‘666‘ in username: self.add_error(‘username‘,‘光喊666是不行的‘) return username # 如果你想同时操作多个字段的数据你就用全局钩子 # 如果你想操作单个字段的数据 你就用局部钩子 forms补充知识点 正则校验 phone = forms.CharField( validators=[ RegexValidator(r‘^[0-9]+$‘, ‘请输入数字‘), RegexValidator(r‘^159[0-9]+$‘, ‘数字必须以159开头‘) ] ) 其他字段渲染 了解即可 做到用时去哪拷贝即可!!! django操作cookie与session cookie与session的作用 保存信息 当你第一次登陆成功之后 服务端给你返回了一个随机字符串 保存客户端浏览器上 之后再次朝服务端发请求 只需要携带该随机字符串 服务端就能够识别当前用户身份 超时时间的概念 cookie虽然是保存在客户端的浏览器上的 但是是服务端设置的 浏览器也是可以拒绝服务端对要求 不保存cookie cookie 保存在客户端浏览器上的键值对 return HttpResponse(‘...‘) return render(...) return redirect(...) # 变形 obj = HttpResponse(‘...‘) return obj obj1 = render(...) return obj1 obj2 = redirect(...) 设置cookie obj.set_cookie() 获取cookie request.COOKIES.get() 删除cookie obj.delete_cookie() print(‘request.path_info:‘,request.path_info) # 只拿路径部分 不拿参数 print(‘request.get_full_path():‘,request.get_full_path()) # 路径加参数 request.path_info: /home/ request.get_full_path(): /home/?username=jason&password=123 session 保存在服务端上的键值对 设置 request.session[‘key‘] = value """ 1.django内部会自动生成一个随机字符串 2.去django_session表中存储数据 键就是随机字符串 值是要保存的数据(中间件干的) 3.将生成好的随机字符串返回给客户端浏览器 浏览器保存键值对 sessionid 随机字符串 """ 获取 request.session.get(‘key‘) """ 1.django会自动取浏览器的cookie查找sessionid键值对 获取随机字符串 2.拿着该随机字符串取django_session表中比对数据 3.如果比对上了 就将随机字符串对应的数据获取出来并封装到request.session供用户调用 """ django中默认的session超时时间为14天 # 设置会话Session和Cookie的超时时间 request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。 # 删除当前会话的所有Session数据 request.session.delete() # 删除当前的会话数据并删除会话的Cookie。 推荐使用 request.session.flush() 这用于确保前面的会话数据不可以再次被用户的浏览器访问 例如,django.contrib.auth.logout() 函数中就会调用它。 session是保存在服务端 作业 利用session完成用户登录 基于session完成登录跳转 django_session表你还可以把它当成是一个临时的仓库
以上是关于111的主要内容,如果未能解决你的问题,请参考以下文章