Django(四)
一、请求周期
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'})
<h1>{{ name }}</h1> -->
最终返回给用户的是<h1>v1</h1>
唯独不可以使用 redirect...
只能自己做跳转
location.reload() # 刷新
location.href = "某个地址" # 跳转
用户 <<<<< 本质上也是返回字符串
二、路由系统URL
a. /index/ -> 函数或类
b. /index/(\d+) -> 函数或类
c. /index/(?P<nid>\d+) -> 函数或类
d. /index/(?P<nid>\d+) name='root' -> 函数或类
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
@method_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
<!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> master.html
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> master.html
tpl1.html
{#被include继承#}
<div>
<input type="text" />
<input type="submit" value="提交" />
</div>
tag.html
如果传的格式是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. 装饰函数
@register.simple_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.
@register.filter
def func(a1,a2)
return "asdfasd"
e. settings中注册APP
f. 顶部 {% load xxoo %}
g. {{ 参数1|函数名:"参数二,参数三" }} {{ 参数1|函数名:数字 }}
缺点:
最多两个参数,不能加空格
优点:
能作为if条件
{% 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> simple_tag-filter
simple_tag-filter
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) xxoo任意函数
xxoo任意函数
五、数据库操作
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)#或者后台添加
封装:
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传递回服务器。比如:
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>
实际上这种技术可以简单的用对action应用URL重写来代替。
cookie 和session 的区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
Django(四)的更多相关文章
- Django(四):model
一.创建model django.db.models是django自带的创建数据库的ORM. 在models.py中以继承models.Model创建表后,需要在setttngs中确保添加了当前应用, ...
- Django 四——ModelForm用法
内容概要: 1.新增数据库表中数据 2.更新数据库表中数据 Django的ModelForm Django中内置了Form和Model两个类,有时候页面的表单form类与Model类是一一对应,因此分 ...
- django (四) model模型
models模型 1. models 定义属性 概述 django根据属性的类型确定以下信息 ·当前选择的数据库支持字段的类型 ·渲染管理表单时使用的默认html控件 ·在管理站点最低限度的验证 dj ...
- Django 中 a href标签 使用方法 跳转页面(Django四)
上次我已经用Django启动了一个登录模板页面 具体过程见:Django启动我的第一个模板页面 但问题是我们只能通过监听的端口访问这一个页面,不能通过页面的一些连接跳转到其他页面如下,我们不能点击注册 ...
- Django搭建网站笔记
参考文档 https://www.cnblogs.com/yoyoketang/p/10195102.html https://www.cnblogs.com/yoyoketang/p/1022094 ...
- 二、Django快速安装
一.安装Python 作为一个Python Web框架,Django依赖Python.从Django适用于哪些版本的Python可以获取更多信息.较新版本的Python内置一个轻量级的数据库SQLit ...
- 【Django笔记一】windows系统下搭建Django项目
一.环境版本信息: 操作系统:windows10 Django版本:2.0.5 Python版本:3.6.4 二.创建虚拟环境: 1.为什么要创建虚拟环境: 我们要开发一个新的项目,需要一套独立的Py ...
- 【Mac系统 + Python + Django】之搭建第一个【Django Demo(一)】
我编写的此系列学习资料是通过虫师的python接口自动化出的书学习而来的,在此说明一下,想学习更多的自动化的同学可以找虫师的博客园,非广告,因为我python+selenium自动化也是跟虫师学的,学 ...
- centos6.5安装pip方法
pip类似RedHat里面的yum,安装Python包非常方便.本节详细介绍pip的安装.以及使用方法. 一.pip下载安装 1.1 pip下载 wget "https://pypi.pyt ...
- 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...
随机推荐
- Offline.js - 自动判断网络连接状态并提醒用户
http://www.cnblogs.com/lhb25/p/offline-js-alert-users-when-no-internet-connectivity.html 使用 jslint/j ...
- HDU 1166 敌兵布阵(分块)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- PHP 实现“贴吧神兽”验证码
最早看到 “贴吧神兽” 验证码是在百度贴吧,吧主防止挖坟贴,放出了究极神兽验证码 例如: 地址:http://tieba.baidu.com/p/3320323440 可以用 PHP + JavaSc ...
- visual studio2015从git上clone(克隆)项目
本文介绍Visual Studio2015从git上clone项目代码的步骤. 1.打开VS2015,进到起始页,打开"团队资源管理器",如下图: 2.点击"克隆&quo ...
- MQTT——服务器搭建(一)
MQTT介绍 MQTT,是IBM推出的一种针对移动终端设备的基于TCP/IP的发布/预订协议,可以连接大量的远程传感器和控制设备: 轻量级的消息订阅和发布(publish/subscribe)协议 建 ...
- new一張form時用using{}的好處。
以下代碼,用Using可避免一些問題,例如handel10000.如果PaymentForm裏面用dialogresult=''而不是close或X,(close或X會即時dispose回收,但dia ...
- PHP获取某个表与其他表的关联关系算法
如图 电影movie有多个附表,如果通过movie表来找出多个与之关联的表. 本算法规则: 外键写法必须是X_id; A与B 1对多关系,中间表表名必须是A_B,且A_B,必须包含A_id,B_id外 ...
- iOS,应用崩溃日志分析
参考资料:http://www.cocoachina.com/industry/20130725/6677.html 1.获得崩溃日志 2.崩溃日志实例 3.符号化崩溃日志 4.低内存闪退 获得崩溃日 ...
- lua UT测试工具
luaunit Luaunit is a unit-testing framework for Lua, in the spirit of many others unit-testing frame ...
- JS限制input输入的为数字并且有小数的时候最多保留两位小数
JS限制input用户输入的为数字并且有小数的时候最多保留两位小数,代码如下: html部分: <input type="number" onkeypress="r ...