Django(五)母版继承、Cookie、视图装饰器等
大纲
一、内容回顾
补充:默认值
补充:命名空间
二、模板语言
1、母版继承
2、include
3、自定义simple_tag
三、Cookie
Cookie 使用总结
四、视图
1、获取用户请求相关信息以及请求头
2、CBV和FBV用户认证装饰器
二、模板语言
1、母版继承
母板:{% block title %}{% endblock %} 子板:{% extends "base.html" %} # 指定继承母版文件 {% block title %}{% endblock %}
示例:
urls.py
url(r'^model/', views.model),
views.py
def model(request): user_list = [1, 2, 3, 43] return render(request, 'lgeng.html', {'u': user_list})
lgeng.html
{% extends 'master.html' %} {# 导入模板文件 #} {% block title %}用户管理{% endblock %} {# 标题 #} {% block center %} {# 内容 #} <h1>用户管理</h1> <ul> {% for i in u %} <li>{{ i }}</li> {% endfor %} </ul> {% endblock %} {% block css %} {# 自定义css #} <style> body{ background-color: white; } </style> {% endblock %} {% block js %} {# 自定义js #} <script></script> {% endblock %}
master.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> <link rel="stylesheet" href="/static/commons.css"> <style> .pg-header{ height: 48px; background-color: seashell; color: green; } </style> {% block css %}{% endblock %} {# 自定义css使用 #} </head> <body> <div class="pg-header">主机管理</div> {% block center %}{% endblock %} <script src="/static/jquery.js"></script> {% block js %}{% endblock %} {# 自定义js使用 #} </body> </html>
2、include
一个html只能继承一个母版,而对于一些小组件、经常使用的,可以通过导入实现。一个html中可以有多个include
lgeng.html 内增加
{% block center %} # 内容 <h1>用户管理</h1> {% for i in u %} {# 可以循环导入 #} {% include 'tag.html' %} {# include 导入 #} {% endfor %} {% endblock %}
tag.html
{{ u }} {# 导入文件中也可以使用模板语言 #} <form> <input type="text" /> <input type="submit" /> </form>
django 是把所有母版、include 合并成一个总的字符串后,在进行渲染。
3、自定义simple_tag
比如在模板语言里,传入值5,让返回25,或传入一个列表只显示前三个,等对值的二次处理。
在模板语言中,提供了部分内置功能。有些功能不够用时就需要自定义python函数实现。
- 内置功能 —> simple_tag
{{ time_obj|date:"Y-m-d H:i:s"}} # 对传入转为日期时间格式 {{ str_obj|truncatewords:"30" }} # 截取前三十个字符 {{ my_list|first|upper }} # 把第一个字符大写 {{ name|lower }} # 把传入值小写
- 自定义simple_tag
分两种方式,总结如下
# 两种方式相同配置 a. app下创建templatetags目录 (templatetags模块 --- python package ) b. 目录下任意xxoo.py文件,创建template对象 register from django import template register = template.Library() # 第一种方式:simple_tag c. 定义:装饰函数 @register.simple_tag def func(a1,a2,a3....) return "asdfasd" d. 配置:settings中注册APP e. 引用:哪里用哪里顶部 {% load xxoo %} f. 使用:{% 函数名 arg1 arg2 %} # 缺点: 不能作为if条件 # 优点: 参数任意 # 第二种方式:filter c.定义:装饰函数 @register.filter def func(a1,a2) return "asdfasd" d. 配置:settings中注册APP e. 引用:部 {% load xxoo %} # 引用母版extend时,load在extend下面。 f. 使用:{ 参数1|函数名:"参数二" }} # 传多个,把参数二自定义“a,b,c”多个,自己处理 # 缺点: 最多两个参数,不能加空格 # 优点: 能作为if条件
使用:
app01/templatetags/xxoo.py
from django import template register = template.Library() @register.simple_tag # 第一种方式 def houyafan(a1,a2): return a1 + a2 @register.filter # 第二种方式 def jingze(a1,a2): return a1 + a2
settings.py
INSTALLED_APPS = [ '……………………', 'app01', ]
templates/tpl4.html
{% load xxoo %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{% houyafan 2 7 %}</h1> <h1>{{ "maliya"|jingze:"Laoshi" }}</h1> </body> </html>
urls.py url(r'^tpl', views.tpl),
views.py
def tpl(request): return render(request,"tpl4.html")
三、Cookie
把浏览器的cookie禁用掉,所有涉及到登录的网站都不能登录使用了。
Cookie :客户端浏览器上的一个文件,类似于键值对字典存储。换浏览器就不行了。
基于这个功能可以实现用户的登录认证,但cookie不是专门用来做用户验证登录的,只不过是利用这个特性实现用户登录。
urls.py
url(r'^login/', views.login), url(r'^index/', views.index),
views.py
from django.shortcuts import render, HttpResponse,redirect user_info = { "lgeng00":{"pwd":"123456"}, "lgeng01":{"pwd":"123456"}, } def login(request): if request.method =="GET": return render(request,"login.html") if request.method == "POST": u = request.POST.get("username") p = request.POST.get("pwd") dic = user_info.get(u) if not dic: return render(request,"login.html") if dic['pwd'] == p: res = redirect('/index/') res.set_cookie("username111", u) ## 设置cookie return res else: return render(request,'login.html') def index(request): # 获取当前已登录的用户 v = request.COOKIES.get("username111") if not v: return redirect('/login/') return render(request,'index.html',{'current_user': v})
login.html
<body> <form action="/login/" method="POST"> <input type="text" name="username" placeholder="用户名" /> <input type="password" name="pwd" placeholder="密码" /> <input type="submit" /> </form> </body>
index.html
<body> <h1>欢迎登录:{{ current_user }}</h1> </body>
Cookie 使用总结
1、获取Cookie:
request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None) 参数: default: 默认值 salt: 加密盐 max_age: 后台控制过期时间
2、设置Cookie:
rep = HttpResponse(...) 或 rep = render(request, ...) rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密盐',...) 参数: key, 键 value='', 值 max_age=None, 超时时间 expires=None, 超时时间(IE requires expires, so set it if hasn't been already.) path='/', Cookie生效的路径,/ 表示根路径,特殊的 跟路径的cookie可以被网站的任何url的页面访问,如"/index",只能index下能访问 domain=None, Cookie生效的域名,在哪个子url下生效 secure=False, https传输(https时,设为ture) httponly=True 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖) def cookie(request): # 获取 Cookie # request.COOKIES # 客户端发来的所有Cookie # request.COOKIES['username111'] # 这个Cookie,就是字典 request.COOKIES.get('username111') # 设置 Cookie res = render(request,'index.html') res = redirect('/index/') res.set_cookie('key',"value") # 设置cookie,关闭浏览器失效 res.set_cookie('key',"value",max_age=10) # 设置cookie, N秒后失效 # expires:设置cookie, 截止时间后失效 import datetime current_date = datetime.datetime.utcnow() current_date = current_date + datetime.timedelta(seconds=5) res.set_cookie('key',"value",expires=current_date) # cookie 加密盐 obj = HttpResponse('s') obj.set_signed_cookie('username',"kangbazi",salt="asdfasdf") # 加密盐 request.get_signed_cookie('username',salt="asdfasdf") # 加密盐获取
四、视图
1、获取用户请求相关信息以及请求头
客户端发来的数据不只是get、post、文件等信息,还有基本的请求头,cookie、session等
想查看客户端发来的数据request提供了哪些方法?
-
先找到对象的类:
print(tyep(request))
-
导入类,查看类的内容
from django.core.handlers.wsgi import WSGIRequest
request.environ 封装了所有用户请求信息,原生数据
from django.core.handlers.wsgi import WSGIRequest for k,v in request.environ.items(): print(k,v) print(request.environ['HTTP_USER_AGENT']) # 客户端终端信息
2、CBV和FBV用户认证装饰器
urls.py
url(r'^login/', views.login), url(r'^index/', views.index), url(r'^order/', views.Order.as_view()),
views.py
###################### 装饰器函数 ########################### 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 ###################### FBV 认证装饰 ######################### @auth def index(reqeust): # 获取当前已经登录的用户 v = reqeust.COOKIES.get('username111') return render(reqeust,'index.html',{'current_user': v}) ###################### FBV 认证装饰 ######################### from django import views from django.utils.decorators import method_decorator # 需要导入模块 #****** 第三种:给类加、指定dispatch,同第二种,不需要多写个函数 ****** @method_decorator(auth,name='dispatch') class Order(views.View): # @method_decorator(auth) #===== 第二种:dispatch加,方法均有 ===== # 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}) # @method_decorator(auth) #--------- 第一种:每个函数都加 --------- def post(self,reqeust): v = reqeust.COOKIES.get('username111') return render(reqeust,'index.html',{'current_user': v})
一、之前内容回顾
1、请求周期 url> 路由 > 函数或类 > 返回字符串或者模板语言? Form表单提交: 提交 -> url > 函数或类中的方法 - .... HttpResponse('....') render(request,'index.html') redirect('/index/') 用户 <———— 返回字符串 (当接受到redirect时)自动发起另外一个请求 --> url ..... Ajax: $.ajax({ url: '/index/', data: {'k': 'v', 'list': [1,2,3,4], 'k3': JSON.stringfy({'k1': 'v'})}, // $(form对象).serilize()
//data:$('form').serilize() //-->:user=abc&pwd=aa&add=abc&email=aba&birth=aba&group_id=3 type: 'POST', dataType: 'JSON': traditional: true, # 使单值、列表等都可以发向后台 success:function(d){ location.reload() # 自己刷新 location.href = "某个地址" # 自己跳转 } }) 提交 -> url -> 函数或类中的方法 HttpResponse('{}') render(request, 'index.html', {'name': 'v1'}) <h1>{{ name }}</h1> --> <h1>v1</h1> redirect...Ajax里不可以 用户 <<<<< 字符串 2、路由系统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第三个参数作为默认参数传递到view函数里 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='m2')
app01.urls
app_name = 'app01' <-- 添加 app_name
urlpatterns=[ url(r'/index/', views.index, name = 'n1'),
url(r'/home/' , views.home, name = 'n2)'
]
reverser('m1:n1') --> /admin/index/
reverser('m1:n2') --> /admin/home/
reverser('m2:n1') --> /crm/index/
reverser('m2:n2') --> /crm/home/
3、获取请求 def func(request): request.POST request.GET request.FILES request.getlist request.method request.path_info return render,HttpResponse,redirect 4、模板 render(request, 'index.html') # for # if # 索引 用 . keys values items all (都不加括号) 5、数据库操作 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 = .... 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() obj.m.filter(name='CTO')
补充:默认值
看上面内容
补充:命名空间
a. project.urls.py
两个url同指向一个
from django.conf.urls import url,include urlpatterns = [ # namespace 命名空间 url(r'^a/', include('app01.urls', namespace='m1')), url(r'^b/', include('app01.urls', namespace='m2')), ]
b. app01.urls.py
from django.conf.urls import url from app01 import views app_name = 'app01' urlpatterns = [ url(r'^(?P<pk>\d+)/$', views.detail, name='detail') ]
c. app01.views.py
def detail(request): return HttpResponse('pk')
以上定义带命名空间的url之后,使用name反向生成URL(反解)的时候,应该如下:
v = reverse('m1:detail')
python代码里{% url 'm1:detail' %}
模板语言里
django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而使路由系统变得简洁。
转载请务必保留此出处:http://www.cnblogs.com/lgeng/articles/7365723.html
<!-- END -->
《版权说明》: 本文转自 -- http://blog.csdn.net/fgf00/article/details/54018066