一、请求周期
url> 路由 > 函数或类 > 返回字符串或者模板语言?
1、Form 表单提交:
提交 -> url > 函数或类中的方法
- ....
HttpResponse('....')
render(request,'index.html')
redirect('/index/')
用户 < < 返回字符串
(当接收到 redirect 时) 自动发起另外一个请求
--> url .....
2、Ajax 提交:
$.ajax({
url: '/index/',
data: {'k': 'v', 'list': [1,2,3,4], 'k3': JSON.stringfy({'k1': 'v'}))},
data 的另一种获取数据的方式 $(form 对象).serilize()
如果多个值发到后台如上面的 list 是一个列表,需要加如下参数 traditional 才能发送到后台
type: 'POST',
dataType: 'JSON',
traditional: true,
success:function(d){
location.reload() # 刷新
location.href = "某个地址" # 跳转
}
})
提交 -> url -> 函数或类中的方法
用 HttpResponse 可以返回序列化的字典(可定制更高)
HttpResponse('{}')
使用 render 的返回本质也是字符串,只是返回的是模板渲染后,特殊的字符串
render(request,'index.html', {'name':'v1'})
只能自己做跳转
location.reload() # 刷新
location.href = "某个地址" # 跳转
用户 <<<<< 本质上也是返回字符串
二、路由系统 URL
a. /index/ -> 函数或类
b. /index/(\d+) -> 函数或类
c. /index/(?P
d. /index/(?P
reverse()
{% url'root'1%}
e. /crm/ include('app01.urls') -> 路由分发
f. 默认值
url(r'^index/', views.index, {'name':'root'}),
def index(request,name):
print(name)
return HttpResponse('OK')
g. 命名空间
/admin/ include('app01.urls',namespace='m1')
/crm/ include('app01.urls',namespace='m1')
app01.urls
/index/ name = 'n1'
reverser('m1:n1')
三、试图 views 的获取请求方式
def func(request):
request.POST
request.GET
request.FILES
request.getlist
request.method
request.path_info
return render,HttpResponse,redirect 等方式
- 请求的其他信息
from django.core.handlers.wsgi import WSGIRequest
request.environ# 封装了所有请求相关的信息,取得话,可以根据字典来取
request.environ['HTTP_USER_AGENT'] #根据某个 key,去获取请求相应的信息
装饰器
FBV:
def auth(func):
def inner(reqeust,*args,**kwargs):
v = reqeust.COOKIES.get('username111')
if not v:
return redirect('/login/')
return func(reqeust, *args,**kwargs)
return inner
CBV:
fom django import views
from django.utils.decorators import method_decorator
_decorator(auth,name='dispatch')
class Order(views.View):
# @method_decorator(auth)
# def dispatch(self, request, *args, **kwargs):
# return super(Order,self).dispatch(request, *args, **kwargs)
# @method_decorator(auth)
def get(self,reqeust):
v = reqeust.COOKIES.get('username111')
return render(reqeust,'index.html',{'current_user': v})
def post(self,reqeust):
v = reqeust.COOKIES.get('username111')
return render(reqeust,'index.html',{'current_user': v})
四、模板引擎(Templates)
render(request,'index.html',' ')#index.html 是模板路径
# for
# if
# 索引. keys values items all
- 母版...html
extends 继承的母版,子板只能继承一个母版
include
master.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- {# 对应tpl1.html的title#}
- <title>{% block title %}{% endblock %}</title>
- <link rel="stylesheet" href="/static/commons.CSS" />
- <style>
- .pg_header{
- height: 50px;
- background-color: aqua;
- color: rebeccapurple;
- }
- </style>
- {# 对应tpl1.html的css#}
- {% block css %}{% endblock %}
- </head>
- <body>
- <div class="pg_header">
- {# 对应tpl1.html的content#}
- {% block content %}{% endblock %}
- </div>
- <script src="/static/jquery.js"></script>
- {# 对应tpl1.html的js#}
- {% block js %}{% endblock %}
- </body>
- </html>
tpl1.html
- {#继承的母板是master.html#
- } { % extends'master.html' %
- } {#标题#
- } { % block title %
- }用户管理 { % endblock %
- } {#内容#
- } { % block content %
- } < div class = "pg_header" > 小男孩管理 < /div>
- <u1>
- {% for i in userlist %}
- <li>{{ i }}</li > { % endfor %
- } < /u1>
- {# 继承include,tag.html模板#}
- {% include 'tag.html' %}
- {% include 'tag.html' %}
- {% include 'tag.html' %}
- {% endblock %}
- {#css样式继承#}
- {% block css %}
- <style>
- body{
- background-color: darkred;
- }
- </style > { % endblock %
- } {#js继承#
- } { % block js %
- } { % endblock %
- }
tag.html
- {#被include继承#}
- <div>
- <input type="text" />
- <input type="submit" value="提交" />
- </div>
- 帮助方法
如果传的格式是 datetime 类型,可以转换成时间日期格式
{{item.event_start|date:"Y-m-d H:i:s"}}
截取后台传过来的字符串的前 30 个字符
{{bio|truncatewords:"30"}}
拿到第一个字符,转换为大写
{{my_list|first|upper}}
字符转换为小写
{{name|lower}}
- 自定义函数
自定义 simple_tag
a. 相应的 app 下创建 templatetags 目录
b. 在 templatetags 目录下,创建任意 py 文件(如 xxoo.py)
c. 创建 template 对象 register(这个对象名不能改,必须为 register)
d. 装饰函数
_tag
def func(a1,a2,a3....) #可以传参数 a1,a2,a3
return "asdfasd"
e. settings 中注册 APP
f. 顶部 {% load xxoo %}
g. {% 函数名 arg1 arg2 %}
缺点:
不能作为 if 条件
优点:
参数任意
自定义 filter
a. app 下创建 templatetags 目录
b. 任意 xxoo.py 文件
c. 创建 template 对象 register
d.
def func(a1,a2)
return "asdfasd"
e. settings 中注册 APP
f. 顶部 {% load xxoo %}
g. {{参数 1 | 函数名:" 参数二,参数三 "}} {{参数 1 | 函数名: 数字}}
缺点:
最多两个参数,不能加空格
优点:
能作为 if 条件
simple_tag-filter
- {% load xxoo %}
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <div>
- {{ name }}
- </div>
- <div>
- {{ name | lower }}
- </div>
- <div>
- {# register.simpletag装饰器#}
- {% func1 2 5 7 %}
- </div>
- <div>
- {# register.filter装饰器#}
- {{ 'xiaozemaliya'|func2:28 }}
- </div>
- </body>
- </html>
xxoo 任意函数
- from django import template
- from django.utils.safestring import mark_safe
- # 创建register(register名字不能改)对象,
- register = template.Library()
- # simple_tag装饰器
- @register.simple_tag
- def func1(a1,a2,a3):
- return a1 + a2
- # filter装饰器
- @register.filter
- def func2(a1,a2):
- print(a1,type(a2))
- return a1 + str(a2)
五、数据库操作
class User(models.Model):
username = models.CharField(max_length=32) #字符长度
email = models.EmailField()
有验证功能
Django Admin
无验证功能:
可以创建成功
User.objects.create(username='root',email='asdfasdfasdfasdf')
User.objects.filter(id=1).update(email='666')
#一对多
class UserType(models.Model):
name = models.CharField(max_length=32)
class User(models.Model):
username = models.CharField(max_length=32)
email = models.EmailField()
user_type = models.ForeignKey("UserType")
#获取对象列表,对象的获取跨表值用 "." 点
user_list = User.objects.all()
for obj user_list:
obj.username,obj.email,obj.user_type_id,obj.user_type.name,obj.user_type.id
#获取单个对象
user = User.objects.get(id=1)
user.
#跨表,字符串的获取跨表值,用 "__" 双下滑杠
user.objects.all().values("username","user_type__name",)
#多对多
class UserType(models.Model):
name = models.CharField(max_length=32)
class User(models.Model):
username = models.CharField(max_length=32)
email = models.EmailField()
user_type = models.ForeignKey("UserType")
#自动生成第三张表
m = models.ManyToMany('UserGroup')
class UserGroup(models.Model):
name = ....
#获取一个对象(user 表中 id=1 的对象)
obj = User.objects.get(id=1)
obj.m.add(2)
obj.m.add(2,3)
obj.m.add(*[1,2,3])# 注这里的列表前面加 *
obj.m.remove(...)
obj.m.clear()
obj.m.set([1,2,3,4,5])# 注这里的列表前面不加 *
# 多个组,UserGroup 对象
obj.m.all()# 获取的是 m(及 usergroup)中的多个对象
obj.m.filter(name='CTO')# 获取的是 name='CTO'的对象
六、分页
防止 XSS 攻击:
{{page_str|safe}}# 前端添加
mark_safe(page_str)# 或者后台添加
封装:
View Code
- from django.utils.safestring import mark_safe
- class Page:
- '''
- current_page当前页
- data_count总数据
- per_page_count每页显示数据个数
- pager_num每页显示页码数
- @property 装饰一个方法变成属性来调用
- '''
- def __init__(self,current_page,data_count,per_page_count=10,pager_num=7):
- self.current_page = current_page
- self.data_count = data_count
- self.per_page_count = per_page_count
- self.pager_num = pager_num
- #当前页显示的起始页
- @property
- def start(self):
- return (self.current_page-1) * self.per_page_count
- #当前页面显示的末页
- @property
- def end(self):
- return self.current_page * self.per_page_count
- #总页数
- @property
- def total_count(self):
- #divmod取商和余数v为商,y为余数
- v,y = divmod(self.data_count, self.per_page_count)
- #当余数不为0时,总页数加一
- if y:
- v += 1
- return v
- #base_url就是url路由
- def page_str(self, base_url):
- page_list = []
- #当总页数小于,每页显示的页数时
- if self.total_count < self.pager_num:
- start_index = 1
- end_index = self.total_count + 1
- #当总页数大于,每页显示的页数时
- else:
- if self.current_page <= (self.pager_num+1)/2:
- start_index = 1
- end_index = self.pager_num + 1
- else:
- start_index = self.current_page - (self.pager_num-1)/2
- end_index = self.current_page + (self.pager_num+1)/2
- if (self.current_page + (self.pager_num-1)/2) > self.total_count:
- end_index = self.total_count + 1
- start_index = self.total_count - self.pager_num + 1
- #上一页,如果当前页数为1时,点击上一页href="javascript:void(0);"代表不做任何操作
- if self.current_page == 1:
- prev = '<a class="page" href="javascript:void(0);">上一页</a>'
- else:
- prev = '<a class="page" href="%s?p=%s">上一页</a>' %(base_url,self.current_page-1,)
- page_list.append(prev)
- for i in range(int(start_index),int(end_index)):
- if i ==self.current_page:
- temp = '<a class="page active" href="%s?p=%s">%s</a>' %(base_url,i,i)
- else:
- temp = '<a class="page" href="%s?p=%s">%s</a>' %(base_url,i,i)
- page_list.append(temp)
- #下一页,如果下一页等于总页数时,点击下一页href="javascript:void(0);"代表不做任何操作
- if self.current_page == self.total_count:
- nex = '<a class="page" href="javascript:void(0);">下一页</a>'
- else:
- nex = '<a class="page" href="%s?p=%s">下一页</a>' %(base_url,self.current_page+1,)
- page_list.append(nex)
- #跳转 val是获取当前输入的页码值,然后location.href跳转到后面的base+val字符串拼接
- jump = """
- <input type='text' /><a onclick='jumpTo(this, "%s?p=");'>GO</a>
- <script>
- function jumpTo(ths,base){
- var val = ths.previousSibling.value;
- location.href = base + val;
- }
- </script>
- """ %(base_url,)
- page_list.append(jump)
- #以下加mark_safe,是为了确保后台定义字符串包含特殊的html字符,前端可以做解析
- page_str = mark_safe("".join(page_list))
- return page_str
七、cookie 和 session
二者的定义:
当你在浏览网站的时候,web 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择,都纪录下来。当下次你再光临同一个网站,WEB 服务器会先看看有没有它上次留下的 Cookie 资料,有的话,就会依据 Cookie 里的内容来判断使用者,送出特定的网页内容给你。 Cookie 的使用很普遍,许多有提供个人化服务的网站,都是利用 Cookie 来辨认使用者,以方便送出使用者量身定做的内容,像是 Web 接口的免费 email 网站,都要用到 Cookie。
具体来说 cookie 机制采用的是在客户端保持状态的方案,而 session 机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以 session 机制可能需要借助于 cookie 机制来达到保存标识的目的,但实际上它还有其他选择。
cookie 机制。正统的 cookie 分发是通过扩展 HTTP 协议来实现的,服务器通过在 HTTP 的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的 cookie。然而纯粹的客户端脚本如 JavaScript 或者 VBScript 也可以生成 cookie。而 cookie 的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的 cookie,如果某个 cookie 所声明的作用范围大于等于将要请求的资源所在的位置,则把该 cookie 附在请求资源的 HTTP 请求头上发送给服务器。
cookie 的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成 cookie 的作用范围。若不设置过期时间,则表示这个 cookie 的生命期为浏览器会话期间,关闭浏览器窗口,cookie 就消失。这种生命期为浏览器会话期的 cookie 被称为会话 cookie。会话 cookie 一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。若设置了过期时间,浏览器就会把 cookie 保存到硬盘上,关闭后再次打开浏览器,这些 cookie 仍然有效直到超过设定的过期时间。存储在硬盘上的 cookie 可以在不同的浏览器进程间共享,比如两个 IE 窗口。而对于保存在内存里的 cookie,不同的浏览器有不同的处理方式 session 机制。session 机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个 session 时,服务器首先检查这个客户端的请求里是否已包含了一个 session 标识(称为 session id),如果已包含则说明以前已经为此客户端创建过 session,服务器就按照 session id 把这个 session 检索出来使用(检索不到,会新建一个),如果客户端请求不包含 session id,则为此客户端创建一个 session 并且生成一个与此 session 相关联的 session id,session id 的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 session id 将被在本次响应中返回给客户端保存。保存这个 session id 的方式可以采用 cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。一般这个 cookie 的名字都是类似于 SEEESIONID。但 cookie 可以被人为的禁止,则必须有其他机制以便在 cookie 被禁止时仍然能够把 session id 传递回服务器。
经常被使用的一种技术叫做 URL 重写,就是把 session id 直接附加在 URL 路径的后面。还有一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把 session id 传递回服务器。比如:
实际上这种技术可以简单的用对 action 应用 URL 重写来代替。
cookie 和 session 的区别:
1、cookie 数据存放在客户的浏览器上,session 数据放在服务器上。
2、cookie 不是很安全,别人可以分析存放在本地的 COOKIE 并进行 COOKIE 欺骗
考虑到安全应当使用 session。
3、session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用 COOKIE。
4、单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie。
5、所以个人建议:
将登陆信息等重要信息存放为 SESSION
其他信息如果需要保留,可以放在 COOKIE 中
来源: