花了2个星期学习了一下Django的基本使用,感觉就是python真的很牛逼,第三方库真是太丰富了,人生苦短我用python,这句话我是切切实实体会到了。用Django框架写服务端的代码,不知道比.net的效率高出多少倍。之前写.net的时候,为了把数据库映射到业务层花大力气了,又是用EF实体模型,又是用T4模板,从模型层上开始一个接口一个接口的写到业务层。如今用Django,都是集成的,根本不用管这些,甚至连SQL都不须要会使用,开发速度不知提升多少倍。javascript
这个是个人Django笔记,我听的老男孩的课,好像是第四期的,16年末的那个版本,两个大王老师讲的仍是很好的。知道了基本使用,接下来就是找个开源项目练一练,练熟了再看看源码。css
ps. 这是听得现场笔记,想着本身忘记了回头看能想起来就行,因此写的比较零碎。能想到的适合场景就是恰好你也想听这个课就能够拿着参考。若是你是想系统的看Django的教程,建议去alex,武沛齐这些大神的博客看,他们写的是真棒。html
Http:无状态前端
请求协议的格式java
请求首行.python
Accept:告诉server我能接收的有哪些类型 q是权重的意思mysql
Accept-encoding:压缩格式,告诉服务器你回复的压缩格式jquery
Accept-Language:能接受的语言web
connection:keep-alive 服务器稍微等一下子(默认3000ms),这个也能够设置成当即断的模式面试
Host:我访问的域名,,主机地址
useragent:我这边的计算机信息啊,浏览器信息啊之类的信息,(发给服务器的)
url发送数据的格式:www.baidu.com?username=hhh&pwd=123 就是不安全 数据的数据通常在1k范围内
get没有请求体,post才有,由于get把数据放到后面去了
默认是get的请求方式 a标签和超连接也都是get请求
post请求
数据再也不地址栏中
数据大小没有上限
有请求体
若是存在中文,会使用URL编码
referer:你这个请求从哪里过来的
响应协议
这个就是server端告诉浏览器的一些事情
状态码
500 代码写错了
300 定向相关的内容
server:服务器版本信息
写一个最最简单的web框架
就是要求写一个server端,
wsgiref,python内部得服务器,作http解析的
注意那个return后面有个 b 由于要的是字节
environ:服务器打包好了放过来的第一个参数。是一个大的字典。
start_response:就是用来处理请求头的。
return 返回的就是浏览器真正要响应的响应体。
njix(音),真实生产中用这个服务器
根据路径来调换显示什么内容
这个fool是返回的 读取一个html的内容 注意要加列表的符号 否则会报splite的错误
经过字符串读的时候可能会有问题,这时候能够考虑先经过字节读出来,而后转成字符串。
Django 就是学这4部分的内容
控制器 --url的分发
model--
魔板渲染
view视图:一个url处理一个函数
MVC MTV
Quit the server with CTRL-BREAK.
model:操做数据库 ORM的方式
怎么经过python操做数据库
怎么把数据库的内容更加灵活的渲染到页面上
这两点是重点学的也是难点,另外两点很简单
经过命令行,建立一个diango项目
mysite2就是一个全局的,这个全局下面有不少的功能。
在这个项目里面 建一个子项目blog (就好似大的微信微信项目里有三个独立的小的功能(朋友圈、聊天..))
至关于把应用分层了,如今这边说blog博客的应用,那全部的这个功能都在这个里面了。
pycharm里面快速的新建一个Django项目
1.在urls里面 加一个路由 因为所在的文件夹不一样 因此须要导入地址
req服务器打包的信息对
return 必定是个httpresponse对象
运行Django的命令
Django的htm文件都往这个文件夹里面放 若是没有这个文件夹就本身建
render 函数的第一个必须传入 request(得对应起来就行) render的功能就是内部作了一个渲染,而后仍是返回httpresponse
他能自动找到的缘由是在setting里面作了路径的自动拼接,因此能找到
Django每次修改自动重启,不须要再关闭了重启
放jqueery在static文件夹里,可是为了让这个文件夹的路径让Django知道,因此须要到setting里进行配置。
起别名就是为了之后方便改动,无外乎就是这个缘由
起了别名就不要用真实的了,用了也没用,必须用别名
添加Jquerry的方法2 推荐使用
这个方式注意须要在开头加一个东西。。无论哪一种方式,解析完都是同样的。
要使用static
标签,首先须要{% load static %}
。
若是把static那个文件放在blog里,事实上大点的项目都是这么玩的。
就该这么一个 十分方便就是由于有虚拟路径和实际路径的帮忙
无命名分组
只有分组的才会有参数更他对应,不加括号的确定没有参数和他对应
有名分组
?P<>起有名分组 ==这个是老版本的了,注意DJ2.0以后就不是这么玩的了==
人家在前端起好什么名字,你这边就得叫什么名字
提交注册
首先经过url进入regist
而后写完后,点击提交,这个前端访问一个连接,这个连接仍是指向了regist
能够经过一个视图作两件事,只要他们的方式不一样就行
同源的概念
==这个reg对应上能够这么理解:在html里写的时候就是在找 这个表单的信息给服务器的哪一个函数去执行呢(这个函数确定往前就是对应的一个连接了),,而后后端path(URL)那边气的别名,就是指示那个去执行表单提交过来的信息的函数==
URL如今都在全局的一个项目里面了,若是项目多了就很差使了。没有一个很好的解耦。
但愿全局作一个分发,发到我的。
推荐使用render问题少。。了解下面那个方法,由于其余人用
把局部变量转换成键值对的locals,
request也是局部变量,因此也能够传过去,还能够用里面的属性
跳转函数:redirect
从一个视图里作完了须要去另外一个页面,就用这个
跳转和直接render的区别:
模板的组成:HRML代码+逻辑控制代码
逻辑控制代码的组成
pycharm里面搞到shell的方法
这个render到底隐藏了哪些?
日后面传不必定是字符串,列表啊 字典啊 类啊 均可以滴 万能句点符号
内置函数 处理字符串方便一些
计数器
各类计数器
遍历到某个元素若是是空的时候作出什么处理
Django第一次post是禁止的,除非带着身份验证的token数据。
这个流程就是用浏览器访问的时候会把这个秘钥发过来,,而后post提交的时候会带着秘钥一块儿去
这个整完了得重启一下,好像是路径不能自动的更新
这个传的变量的个数,就是一个,若是要多个,那就弄个列表
自定义标签的参数不限制,能够有多个
建一个新的Django
先搭出一个这样的框架
先写一个基础了html,里面分块,这个块就是能够修改的。
字版的第一句话就是集继承过来
include添加
多对多的关系用三张表
一对一,两张表怎么弄
其实数据库只是提供了一对多的关系,多对多的关系个一对一的关系都是从一对多的关系上改过来的。
ORM 对象关系映射表
经过python的类对数据路的表进行操做
makemigrations 和 migrate
D:\Python37\python37.exe manage.py makemigrations (这一步只是建立了一个脚本,并无和数据库打交道,在blog下的migration文件夹里建立的脚本)
D:\Python37\python37.exe manage.py migrate
默认是链接sqlite数据库,若是是要链接mysql数据库,须要在设置里作一些修改
改动一下表的字段
增
方式一:
方拾二:
改
法一 :这种方法是能够同时改多个的 。这种update的方法效率高,单对单,就改一个。
法二 :这种方法只能改一个 save效率低,由于没有改动的也会给更新一下
经过设置,打印出ORM执行时所使用的sql语句的日志
删除
双下划线的特殊功能,模糊查询
一个2.0版本的新要求,视频的版本没有这个
一对多的直接点出来确定是一个对象
涉及到外键的一些查询
方法一: 有点麻烦
方法二
publish找book表关联的内容
==这个后面接04 03是补充的,有些错乱==
publish加上引号就是按照映射关系去找,也就是加载完去找,因此能够publish这个类放在book这个类的哪里都行。可是若是publish不加上引号,那就是按照变量关系去找的了,那么publish这个类就得放在book这个类的上面。
上承接02,多表查询的任务(找符合外键条件的一个任务)
推荐自动带的那个方式 manytomany
多对多前提是有两张多对多的表
==上述第三个表(本身写的那个表)的方法不经常使用,这个多是一家之言,主要是以为麻烦==
聚合函数
分组
能够理解为:先分组,而后sum是对每一个组进行操做
生成器的做用就是:节省内存
数据量很少还反复要用的话,缓存就行。
若是数据量万级别以上,仍是建议用迭代器
Django牛逼的组件
url
views
models
templates
admin
在、
注册->建立超级用户->在页面里看
admin关于数据库的后台管理
如今想在原来的上面横着显示一堆字样 ,,须要先写已给类,,而后告诉admin
1.让框子变的可修改
2.listdisable里不能加多对多的关系
显示字段的时候换个别名
按照某个字段排序
cookie和session都有默认放在某个表里的,因此若是要用这个你就须要把这个表给初始化出来。(用migrate的那些指令)
若是只有一个cookie的话,全部信息都放在客户端,不安全,容易被窃取。
cookie就像是客户端的钱包
session就像是服务端的钱包
session在Django里会默认存到数据库里
若是排除安全和你不嫌弃来回传输慢的化,cookies也是能够本身完成这些功能的,事实上人们一开始也是这么作的,后来拿session来解决cookies遇到的问题的。 我把钥匙(cookies)给你你下次带着钥匙来,用户的哪些资料(session对应的东西)我都放在数据库里面。拿着钥匙打开了数据库的内容。
登陆的时候若是用户名和密码对应上了,那就把两个关键字(islogin和user)存到session里。每次登陆index页面的时候都去看一下session里(按照islogin键去找)的islogin是否是为true,若是是true就继续往下走,若是不是true那就返回登陆界面,让用户登陆。
def login(request): print("cookies",request.COOKIES) print("sessions",request.session) if request.method=="POST": name=request.POST.get("user") pwd=request.POST.get("pwd") print("name=======",name) print("pwd==========",pwd) if name=="yuan" and pwd=="123":#这边在假设若是登陆成功了 #若是登陆成功了,就给这两个保存起来 #session会自动把这个存到数据库里面。 request.session["is_login"]=True request.session["user"]=name return redirect("/index") return render(request,"login.html")#若是没有登陆成功,就是还返回其login的界面 def index(request): if request.session.get("is_login",None): name=request.session.get("user",None) print("!!!!!!!!!!!!!!!!!!!!!!!!!!!",name) return render(request,"index.html",{"name":name}) else: return redirect("/login")
生命周期指的是用户在浏览器上一点,在你的浏览器上都发生了什么。---
这个是简单的流程
找到类后,不会首先执行get或post方法,而是执行继承的view里的那个dispatch方法,dispatch方法帮助咱们反射找到要执行的get仍是post方法。
渲染完的页面返回的时候,也是先返回给dispatch而后再返回给用户。
完整的建一个Django文件
这边还得加一个token钥匙,否则post不过去
单表的CRUD
一对多的CRUD
filter和values的跨表都是经过双下划线来实现的
多对多
找学生属于哪一个校区,,跨多个表
反向查找默认是字段_set_这种形式,是能够改的。
这集没啥特别的重点,一个是一对多表的CRUD,还有一个就是模板语言里怎么将下拉列表的框框变成默认的,就是怎么checked。
若是定义了related_name,就经过related_name对它进行反向操做
总结一下
感受不到第三张表的存在,这就是manytomany的魅力。
多对多的反向必须加上relatedname,,不加就不能反向查了。
加了value就是数字了,就不能再点了
c
对static里面的内容分个类
http://fontawesome.dashgame.com/ 专业图标 注意下面的使用方法
经过写ID绑定触发的方式把按钮和模态关联起来。
选两个标签的时候注意这个写法啊,一个引号里面写逗号
无心中调试出的一个知识点
须要值得注意的是:可能会出现,刚开始加页面时给全部的控件都绑定了事件,而后再ajax添加新的表单行后忘记给行里面的控件添加新的事件(57-bug修复)
解决方法,用事件委托来解决,何时点击,何时绑定。
方式一:
方式1的缺点就是,和格子的对于关系太严格了。要是再增长一列就完犊子了。
方法二:
方法二的思想就是经过给每个td上增长一个属性,而后经过js对各个表格进行精准的操做。这样的好处就是即便外面的再增长或者删除或调换一列,这个js代码都不须要大换。
<div class="container"> <table class="table table-bordered table table-striped" id="tb"> <thead> <th>姓名</th> <th>性别</th> <th>年龄</th> <th>班级</th> <th>操做</th> </thead> <tbody id="tb"> {% for row in stu_list %} <tr nid="{{ row.id }}"> <td na="user">{{ row.username }}</td> <td na="gender">{{ row.gender }}</td> <td na="age">{{ row.age }}</td> <td na="cls_id" cid="{{ row.cs_id }}">{{ row.cs.title }}</td> <td> <a href="del_students.html?nid={{ row.id }}">删除</a> | <a class="edit-row">编辑</a> </td> </tr> {% endfor %} </tbody> </table> </div>
function bindEditStudent() { $("#tb").on("click",".edit-row",function () { {# 首先把那个增长的模态页面给打开 #} $("#editstudentmodal").modal("show"); {# 打开后就要在这个上面去显示选中的那一行的值 #} {# 取出那一行每一个小个子td里面的值 #} $(this).parent().prevAll().each(function () { {#对那一行里的每个元素进行轮询#} var v=$(this).text(); var n=$(this).attr("na"); console.log(v) if (n=="cls_id")#特殊的特殊处理吧,这个须要拿到的是对于班级的id。。 { //为了这个特殊处理,在html里给这个增长了cid属性 var cid=$(this).attr("cid");{#拿到了这个学生对应的班级的id#} $('#editmodel select[name="cls_id"]').val(cid); } else if(n=="gender"){ //性别也特殊,是单选按钮,经过 if (v==true){ $("#editmodel :radio[value='0']").prop("checked",true); }else { $("#editmodel :radio[value='1']").prop("checked",true); } }else { //n=age //v=12 $("#editmodel input[name='"+n+"']").val(v); } }) }); }
这张图的cid没有赋值,看下一张
增长,编辑的时候建议使用普通的刷新页面的方式,删除的时候建议使用ajax的方式
若是非要发字典,把字典用json变成字符串日后发
def index(request): userList=[] for i in range(1,1000): temp={"name":"root"+str(i),"age":i} userList.append(temp) current_Page=request.GET.get("p")#当前想要获取哪一页 paginator=Paginator(userList,10)#传入总共的个数,和一页显示多少个 try: posts=paginator.page(current_Page) except PageNotAnInteger: posts=paginator.page(1) except EmptyPage:#当向page()提供一个有效值,可是那个页面上没有任何对象时抛出 posts=paginator.page(paginator.num_pages) return render(request,"neizhifenye.html",{"posts":posts})
<head> <meta charset="UTF-8"> <title>Title</title> {#把后端传过来的列表循环的显示出来#} {% for item in posts.object_list %} <li>{{ item.name }}-{{ item.age }}</li> {% endfor %} {% if posts.has_previous %} <a href="neizhifenye?p={{ posts.previous_page_number }}">上一页</a> {% endif %} {% if posts.has_next %} <a href="neizhifenye?p={{ posts.next_page_number }}">下一页</a> {% endif %} </head>
对Django自带的分页功能进行扩展后,前端和后端部分关键代码
这个可使用include形式,就是在前端页面把页码选择的那一行数据放到一个include的文件夹里,须要用的时候调出来用。。这样增长前端代码的复用率。
{% for item in posts.object_list %} <li>{{ item.name }}-{{ item.age }}</li> {% endfor %} {% if posts.has_previous %} <a href="neizhifenye?p={{ posts.previous_page_number }}">上一页</a> {% endif %} {% for i in posts.paginator.paper_num_range %} //这边注意先.出paginator 再paper_num.. {% if i == posts.number %} {# 到了当前页的给大写一下 #} <a style="font-size: 30px;" href="neizhifenye?p={{ i }}">{{ i }}</a> {% else %} <a href="neizhifenye?p={{ i }}">{{ i }}</a> {% endif %} {% endfor %} {% if posts.has_next %} <a href="neizhifenye?p={{ posts.next_page_number }}">下一页</a> {% endif %}
#扩展内置分页的一些功能 class CustomPaginator(Paginator):#继承于原理的paginator类 def __init__(self,current_page,per_pager_num,*args,**kwargs): self.current_page=int(current_page)#当前页 self.per_pager_num=int(per_pager_num)#一页显示多少条 super(CustomPaginator,self).__init__(*args,**kwargs) def paper_num_range(self):#这个就是扩展的那个功能 #self.num_pages 总共的页数 这个参数是从父类那里继承过来的 #self.current_page 当前页(就是浏览器申请访问的那个页面) #self.per_paper_num 最多显示页码的数量 if self.num_pages<self.per_pager_num: #若是总共须要的页数还比下面显示出来的页数少 return range(1,self.num_pages+1) #那就把总共的页数都显示出来 #若是总共须要的页数特别多 part=int(self.per_pager_num/2) #拿到下面一共要显示多少栏的一半的值 #好比下面要显示11个 那就取通常5个 if self.current_page<=part: #若是当前要显示的页码 比通常要写 return range(1,self.per_pager_num+1) #这种状况就是 你如今要第2页,下面显示11个跳转页面的按钮 #那就应该显示1--11 if (self.current_page+part)>self.num_pages:#这种状况就是最后那几个 当前要的页面 已经很接近最后那几个了,这时候就显示倒数后面几个就行 return range(self.num_pages-self.per_pager_num+1,self.num_pages+1) #若是上面的if都没有能经过,那就是最最普通的通常状况了 return range(self.current_page-part,self.current_page+part+1) def index1(request): userList=[]#模拟要显示的东西 for i in range(1,1000): temp={"name":"root"+str(i),"age":i} userList.append(temp) cuurent_page=request.GET.get("p") paginator=CustomPaginator(cuurent_page,7,userList,10) try: posts=paginator.page(cuurent_page) except PageNotAnInteger: posts=paginator.page(1) #若是取到的不是整数,那就默认显示第一页 except EmptyPage:#若是是空页面 说明过界了 那就显示最后一页 posts=paginator.page(paginator.num_pages) return render(request,"neizhifenye.html",{"posts":posts})
这个里面的名字(user pwd)必须和前端提交过来的同样(也就是required.post)里面存储的同样才行。这样Django才会有办法自动识别去找了比较。
后端代码
from django.shortcuts import render ,redirect,HttpResponse from django import forms from django.forms import fields class F1Form(forms.Form): #对form表单里的数据类型进行限定 #注意这个名字不能瞎写,须要和前端传过来的那个同样 user=fields.CharField(max_length=18, min_length=3, required=True, error_messages={"required":"用户名不能为空", "max_length":"太长了", "min_length":"过短了", "invalid":"..",#全部的格式错误关键字都是invalid } ) pwd=fields.CharField(min_length=6,required=True) age=fields.IntegerField(required=True) email=fields.EmailField(required=True) def form(request): if request.method=="GET": obj=F1Form return render(request,"form.html",{"obj":obj})#这个地方传过去是由于能够利用这个本身生成# #HTML if request.method=="POST": obj=F1Form(request.POST)#这个地方特别注意是request.POST而不是request否则会报isvalid的错误 #是否所有验证成功 if obj.is_valid(): #print("验证成功",obj.cleaned_data) return redirect("http://www.baidu.com") else: print("验证失败",obj.errors) return render(request, "form.html", {"obj": obj})
前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form id="fm" action="formtest" method="post"> {#前端利用了传来的form对象自动生成HTML#} <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>e-mail{{ obj.email }}{{ obj.errors.email.0 }}</p> <input type="submit" value="提交"> </form> </body> </html>
参考博客: http://www.cnblogs.com/wupeiqi/articles/6144178.html Form 1. 验证 2. 生成HTML(保留上次输入内容) 3. 初始化默认是 Form重点: - 字段 用于保存正则表达式 ChoiceField ***** MultipleChoiceField CharField IntegerField DecimalField DateField DateTimeField EmailField GenericIPAddressField FileField RegexField - HTML插件 用于生成HTML标签 - 特殊的单选或多选时,数据源是否能实时更新?????***** from app01 import models class LoveForm(forms.Form): price = fields.IntegerField() user_id = fields.IntegerField( # widget=widgets.Select(choices=[(0,'alex'),(1,'刘皓宸'),(2,'杨建'),]) widget=widgets.Select() ) def __init__(self,*args,**kwargs): super(LoveForm,self).__init__(*args,**kwargs) self.fields['user_id'].widget.choices = models.UserInfo.objects.values_list('id','username') from django.forms.models import ModelChoiceField from django.forms.models import ModelChoiceField class LoveForm(forms.Form): price = fields.IntegerField() user_id2 = ModelChoiceField( queryset=models.UserInfo.objects.all(), to_field_name='id' ) 注意:依赖models中的str方法
cleand_data就是获取传过来的数据
更加简洁的方式往数据库里存储数据
get请求后在userform里面设置默认值,这样返回到页面渲染后,控件就是有默认值的了
经过用这个组件,能够定制更多的HTML标签
这个select就是多选的下拉框
两种设置控件默认值(也就是这个控件在页面上显示什么值)的方法
一种是建立form对象的时候传,这个时候能够初始化全部的控件值
一种是建立控件的时候传,这个时候只能初始化所在的这个控件的值
一句话生成全部控件的方法,不推荐这儿作,由于虽然方便,可是调整样式的时候就麻烦了。
form表单传输文件的时候须要加上这句话,否则文件传输不过来的
单选框和多选框给默认的初值
用的不算太多,不知道用在什么场合
这些本质就是帮咱们作了正则表达式的封装
每个field里面都封装了一个正则表达式 + 一个默认插件。。这个默认插件就是在_str里,_str就是调用的时候输出的那个文本。
额外插的一个知识点:后端往前端传输一个字符串,怎么就能让前端知道这个字符串的意思不是普通的字符串,而是表明的HTML标签呢。
复习:简单的扩展就是若是自带的正则表达式已经不能知足你的需求了,那么如何扩展或者是说本身定义正则表达式,有多是多个正则表达式来验证。
复杂的扩展就是对内容进行一些判断了,若是内容已经有了,那怎么弄。
1.简单扩展 利用Form组件自带的正则扩展: a. 方式一 from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.CharField( error_messages={'invalid': '...'}, validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')], ) b. 方式二 from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.RegexField(r'^[0-9]+$',error_messages={'invalid': '...'}) 2.基于源码流程 a. 单字段 from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class AjaxForm(forms.Form): username = fields.CharField() user_id = fields.IntegerField( widget=widgets.Select(choices=[(0,'alex'),(1,'刘皓宸'),(2,'杨建'),]) ) # 自定义方法 clean_字段名 # 必须返回值self.cleaned_data['username'] # 若是出错:raise ValidationError('用户名已存在') def clean_username(self): v = self.cleaned_data['username'] if models.UserInfo.objects.filter(username=v).count(): # 总体错了 # 本身详细错误信息 raise ValidationError('用户名已存在') return v def clean_user_id(self): return self.cleaned_data['user_id'] b. 总体错误验证 class AjaxForm(forms.Form): username = fields.CharField() user_id = fields.IntegerField( widget=widgets.Select(choices=[(0,'alex'),(1,'刘皓宸'),(2,'杨建'),]) ) # 自定义方法 clean_字段名 # 必须返回值self.cleaned_data['username'] # 若是出错:raise ValidationError('用户名已存在') def clean_username(self): v = self.cleaned_data['username'] if models.UserInfo.objects.filter(username=v).count(): # 总体错了 # 本身详细错误信息 raise ValidationError('用户名已存在') return v def clean_user_id(self): return self.cleaned_data['user_id'] def clean(self): value_dict = self.cleaned_data v1 = value_dict.get('username') v2 = value_dict.get('user_id') if v1 == 'root' and v2==1: raise ValidationError('总体错误信息') return self.cleaned_data PS: _post_clean
如何把一个表单序列化,而后用ajax的方式传输出去
是什么致使了这个不是python内部的数据类型却可以转换成json,是由于他继承于dic
规则:自定义方法clean_字段名,必须返回值self。cleaned_data[“username”],若是出错:raise validationerror(“用户名已经存在”)
这个本身写clean函数须要有返回值,由于源码里是拿到返回值从新赋值给data。。
本身的感受:这两步的意思就是先检查格式,再检查内容。检查格式的人家已经给写好了正则表达式,
检查内容内容的须要本身去写,本身去写的过程当中注意去知足别人的格式。
导入validation的命名空间
有时候进行验证须要用到不少的前面传过来的数据,这个时候放在单一的那个变量里显然显得十分的不合适,
这个时候就须要咱们在全部的单一的执行完了以后,再有一个能够执行全局的校验的函数。
把某种东西可以保存在文件里的过程,叫作序列化
这种[ob,obj...]的只能经过Django给的那种方式进行序列化
这个里面的data数据至关于被序列化了两次,那么前端也要解两次。 success回调的那个arg至关于已经帮忙解开一次了,里面只要再解开一次就行。
经过values获取的时候怎么转换成json的格式
总结来讲,返回的是对象的时候采用内置的序列化方法,而后前端也要反序列化两次
Django序列化 a.对象 ----用内部的 b.字典 c.元祖 序列化:在JavaScript里用的是:JSON.parse() ,JSON.stringfy() Django里 json.dumps()和json.load() 这种python内置的序列化只能处理python内置的数据类型。为了解决 这个问题,用Django给提供的序列化一下,而后再总体序列化一下。意思就是那个不是数据类型的地方序列化的2次,因此前端那边也反序列化2次。 Django: json.dumps() json.loads() 问题: serilize: model.TB.objects.all() json: list(model.TB.objects.values()) json: list(model.TB.objects.values_list())
内容回顾: 1.ajax参数 url: type: data: 1. value不能是字典 {k1:'v1',k2:[1,2,3,],k3: JSON.stringify({})} 2. $('').serilizer() dataType:"JSON",# text,html,xml 单词太长了 traditional: success:function(arg){ # arg=>obj }, error:function(){ } 2. 序列化 JavaScript: JSON.parse() JSON.stringify() Django: json.dumps() json.loads() 问题: serilize: model.TB.objects.all() json: list(model.TB.objects.values()) json: list(model.TB.objects.values_list()) 3. Form 做用:用于验证+(生成HTML+保存上次提交的数据) 使用: 1.建立类 2.建立字段() 3. 验证用户输入: obj = Form(request.POST,request.FILES) if obj.is_valid(): obj.cleaned_data else: obj.errors 4. clean_字段 5. clean() _post_clean() PS: __all__ 4. 分页组件 a. 内置 b. 扩展 c. 自定义 5. XSS攻击 跨站脚本攻击: 防止: - 其余人输入的内容 不用safe - 本身输入的内容 可用safe <script> for(var i=0;i<9999;i++){ alert(i) } </script> <script> 获取本地cookie,发送到另一个网站 </script> 今日内容: - 文件上传 - 普通上传 - 自定义页面上传按钮 - 基于Form作上传 - Ajax上传文件????? - Django Model操做补充 参考博客:http://www.cnblogs.com/wupeiqi/articles/6216618.html 1. 建立类 class UserInfo(model.Model): age = CharFiled(是否为空,类型,长度,列名,索引=True||||错误提示,自定义验证规则) .. .. ### 一对多 ### 一对一 - ### 多对多 - 第三张表:a.自动建立;b.手动建立; c. 手动+自动 ### 自关联:互粉 ### a. 索引 b. 一对多: on_delete c. 一对一和一对可能是什么关系? unique=true d. 多对多: - a.自动建立;b.手动建立; c. 手动+自动 - ### 自关联:互粉 ### PS:related_name 2. 操做类 obj = UserInfo.objects.all().all().all()
上传的图标的制做
三种索引
对admin进行一些操做
对外键删除的时候作一些设置 就是你删除关联的时候其余人会怎么反应
联合惟一,就是好比给一我的打标签 一种标签只能打一次对一我的
这样写就能够经过m对这个操做了。本身定义第三张表,m的add和set就不能用了,filter还能够用。
这样容易乱,不是很推荐
ps:推荐写relatedname
下面可能会出现跨表操做的时候就加上related,加一个或者加两个都是能够的。
using指定链接哪一个库
题1:代码在执行前做用域已经建立,执行的时候按照做用域去找值就对了
返回inner函数没有拿到外面来,不拿,人家在编译的过程当中做用域就已经生成了。result是代指inner函数,inner函数有本身的做用域
因此第一个题目的答案是456
第二题:
js里没有类,通常用函数来充当类,函数充当类的时候,通常默认把函数名的首字母大写。
这个建议去武沛齐的博客上看
这样发过去会有一个问题,Django的后台不知道这个究竟是get仍是post,没法解析出这个body里面的数据
因此就会发现post和get里面没有数据,可是body里面有数据。
基于ireame和form表单实现的伪造ajax
form提供数据 irame提供通道 把数据发过去
irame的兼容性是最好的
不用动态绑定会出现的一个问题就是,重上到下进行刷新的时候可能会出现上面的用到下面的函数,可是尚未刷新到下面的函数的状况。
在标签上绑定的时候那个this为window,动态绑定this不要传递,由于内部的那个就是当前标签
jsonp是一种方式,添加到scrapt块里,而后在再删除掉。从而实现跨域的请求。
jsonp是一个规则,远程传过来时函数包裹着数据
jsonp只能用get,即便你用post,内部也会用get