文章详情页 您现在的位置是:网站首页>文章详情
关于django后端渲染的笔记
Jeyrce.Lu 发表于:2019年4月16日 02:01 分类:【Python】 2894次阅读
为什么不在views中写html
太坑
views写html标签(业务和显示的耦合性太高)
显示提取到index.txt,业务中直接读取成字符串(.txt,不会联想)
将标签写到html,显示和业务分离成功,会联想
随着项目逐渐增大,html越来越多,那么html放在哪里?
django说templtes
提供一个便利?
def index_view(request): return render_me('templates/sencod.html') def render_me(path): with open(path, 'rb') as fr: content = fr.read() return HttpResponse(content)
能不能不写呢?可以
在settings中的TEMPLATES
'DIRS': [os.path.join(BASE_DIR, 'templates')]
获得settings中的DIRS
def index_view(request): return render_me('asdasd') def render_me(path): from settings import TEMPLATES import os dirs = TEMPLATES[0].get('DIRS') filepath='' for dir in dirs: if os.path.exists(os.path.join(dir,path)): filepath=os.path.join(dir,path) if not filepath: raise Exception('templte does not exist') with open(filepath, 'rb') as fr: content = fr.read() return HttpResponse(content)
django.shortcut render
render(request,'sencod.html')
Template
模板的渲染流程
def index_view(request): content = 'hello:{{name}}' # 模板字符串 from django.template import Template t = Template(content) # 创建模板 from django.template import Context c = Context({'name':'张三'}) # 准备数据 render_string = t.render(c) # 渲染 return HttpResponse(render_string)
将显示和业务分离
# 原来是Template类的实例支持模板标签 def index_view(request): with open('templates/sencod.html') as fr: content = fr.read() # content = '<font color="red">hello:{{name}}</font>' # 模板字符串 from django.template import Template t = Template(content) # 创建模板 from django.template import Context c = Context({'name':'张三'}) # 准备数据 render_string = t.render(c) # 渲染 return HttpResponse(render_string)
字典
def index_view(request): with open('templates/sencod.html') as fr: content = fr.read() # content = '<font color="red">hello:{{name}}</font>' # 模板字符串 # content = html # 模板字符串 from django.template import Template t = Template(content) # 创建模板 from django.template import Context c = Context({'users':users}) # 准备数据 render_string = t.render(c) # 渲染 return HttpResponse(render_string)
render的简化版的源代码
def render_me(path,data={}): from settings import TEMPLATES import os dirs = TEMPLATES[0].get('DIRS') filepath='' for dir in dirs: if os.path.exists(os.path.join(dir,path)): filepath=os.path.join(dir,path) if not filepath: raise Exception('templte does not exist') with open(filepath, 'rb') as fr: content = fr.read() #模板字符串 from django.template import Template t = Template(content) # 创建模板 from django.template import Context c = Context(data) # 准备数据 render_string = t.render(c) # 渲染 return HttpResponse(render_string)
模板渲染的步骤
获得原始字符串
创建模板
准备数据
渲染,获得渲染之后的字符串
返回HttpResponse对象
def index_view(request): raw_content = 'hello :{{name}}' #准备原始字符串 t = Template(raw_content) # 准备模板 c = Context({'name':'张三'}) # 准备数据 render_string = t.render(c) # 渲染,并获得渲染的字符串 return HttpResponse(render_string)
loader
t = loader.get_template('模板路径')
def index_view(request): t = loader.get_template('index.html') #<class 'django.template.backends.django.Template'> render_string = t.render({'name':'张三'}) return HttpResponse(render_string)
模板渲染的原理设计的对象
django.template Template
django.templte Context
django.shortcut loader
settings分析
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates',#渲染引擎 'DIRS': [os.path.join(BASE_DIR, 'templates')], # html模板存放的未知 'APP_DIRS': True, # 可以在模块下寻找模板 'OPTIONS': { 'context_processors': [ # 全局上下文 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
APP_DIRS:True(模板就可以直接写在模块中templates中),完全的模块化了。
APP_DIRS:False (寻找模板的时候就不会在模块下找了)
INSTALL_APPS作用
数据迁移的时候使用
寻找模块下的模板时候使用
DTL
django template lanague
如果一个变量找不到,DTL不会报错,而是显示空白
{{}}
变量 (任意的对象)
.作用
访问字典值
render(request,'post.html',{'user':{'name':'张三','age':10}}) # html 姓名:{{ user.name }},年龄:{{ user.age }}
访问对象属性
render(request,'post.html',{'today':datetime.datetime.today()}) # html {{ today.year }}-{{ today.month }}-{{ today.day }}
访问对象的方法(不能有参数)
render(request,'post.html',{'duanzi':'hello world'}) # html {{ duanzi.capitalize }}
访问列表(不能使负数索引)
render(request,'post.html',{'items':['asd','s']}) # html {{items.1}}
随便给模板传入一个对象 . 先按照字典查user['age'],在按照属性查user.age,再按照方法查user.age(),按照列表索引查user[age]
在django中访问不存在东西,是不会报错的,就是空白字符
{% %}
if
{% if items != None %} # 记得有空格 itmes不是空 {% endif %} {% if items %}items不是空{% else %}items是空{% endif %} {% if gender == '男' %}男生{% elif gender == '女' %}女生{% else %}未知{% endif %}
模板中写嵌套非常难阅读,业务应该放到业务层(views层)做判断,模板中做的是简单的显示,隐藏。
支持and or not
for 携带forloop
{% for user in users %} <tr> <td>{{ forloop.counter }}</td> <td>{{ user.name }}</td> <td>{{ user.age }}</td> </tr> {% endfor %} {% for user in users %} <tr style="color: {% if forloop.first %}red{% elif forloop.last %}cadetblue{% endif %}"> <td>{{ forloop.counter }}</td> <td>{{ user.name }}</td> <td>{{ user.age }}</td> </tr> {% endfor %}
forloop
counter,counter0,revcounter,last,first
对于列表 reversed
empty
{% for item in items reversed%} {{ item }}<br> {% empty %}当前没有数据 {% endfor %}
for不支持break,continue(所以复杂业务都在views中处理好)
多循环
{% for user in users %} {% for k,v in user.items %} {{ forloop.parentloop.counter }} --{{forloop.counter }}--{{ k }}--{{ v }}<br> {% endfor %} {% endfor %}
comment 注释{##}
{% comment %} {% for user in users %} {% for k,v in user.items %} {{ forloop.parentloop.counter }} --{{forloop.counter }}--{{ k }}--{{ v }}<br> {% endfor %} {% endfor %} {% endcomment %}
转义
所有的数据纯字符串,不进行解析
django将模板中的数据都进行了自动转义,防止 跨站脚本攻击(Cross Site Scripting,XSS)
关闭转义
{% autoescape off %} {{ user.name }} {% endautoescape %}
csrf_token(跨站请求伪造)其实起不了多大的防护作用。
csrftoken 在cookie中(唯一的表示浏览器),1年过期
csrfmiddlewaretoken(每请求一次,就变)
d={csrftoken:csrfmiddlewaretoken,csrftoken:csrfmiddlewaretoken} # 请求头自动携带cookie(csrftoken) # form表单提交csrfmiddlewaretoken d.get(csrftoken) == form表单提交csrfmiddlewaretoken # 原理 ,自己写一个csrf_token # {%csrf_token%} =====> <input type='hidden' name='csrfmiddlewaretoken' value='tqVHekuJNnlOwwSTAX8oIRepkxwQQNoPdmbOfWrPgs8GzjkLW6vHhMGOEa5OLVMg' /> d={csrftoken:'y7OyWpLPesgdcyjraSxiqdACSfu2xq8rJdixKZDVZWKm3B6XMUJt9YFbJGj2X3uf'} # cookie会在请求头自动携带y7OyWpLPesgdcyjraSxiqdACSfu2xq8rJdixKZDVZWKm3B6XMUJt9YFbJGj2X3uf d.get('EHRWgmZQl8wXNzd4N2035ndAFUz0qtnRhwUTMq0ygUkUrydHESWs6RPBH2mYH82m') # ==y7OyWpLPesgdcyjraSxiqdACSfu2xq8rJdixKZDVZWKm3B6XMUJt9YFbJGj2X3uf
django模板中不支持传参
过滤器来解决模板中不支持传参问题
过滤器在任何标签中都能使用
url逆向解析
reverse('order:myorder')
通过,模块的命名空间:函数名 (找到处理函数的真实地址)
函数中处理
get传递参数 ?参数
resetful传参数 捕获
url = reverse('order:myorder',args=(10,))+"?time=2017-11-11"
模板中
<a href="{%url 'order:myorder' 100 %}?time=20-10-10">我的订单</a>
模板继承
extends 继承html
include 将其他的html包含进来
block 挖坑,填坑
上下文
Context
RequestContext
有一些共同函数,需要一些共同的行为
#coding=utf-8 from django.http.response import HttpResponse def user_processor(request): # 函数 print request #User.objects.get(id = request.GET.get('uid')) return {'name':'张三'} # 字典 def index1_view(request): from django.template import Template,RequestContext t = Template('{{name}}:数据') render_string = t.render(RequestContext(request,dict_=None,processors=(user_processor,))) return HttpResponse(render_string) def index2_view(request): t = Template('{{name}}:数据') render_string = t.render(RequestContext(request, dict_=None,processors=(user_processor,))) return HttpResponse(render_string) def index3_view(request): from django.template import Template, RequestContext t = Template('{{name}}:数据') render_string = t.render(RequestContext(request, dict_=None,processors=(user_processor,))) return HttpResponse(render_string) def index4_view(request): return HttpResponse('index4') def index5_view(request): return HttpResponse('index5')
render(request,)
全局上下文(类似全局变量和局部变量)
# 配置在Templates中的context_processors def age_processor(request): return {'age':'asdasdadads'} TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'request.age_context_process.age_processor' ], }, },]
格式
def 函数名(request): #插叙数据库 return {'':''}
static标签
专门访问静态文件夹的东西
{%load staticfiles%}{%static 'a.jpg'%}
过滤器
last
first
length
length_is:2
truncatechars:30
safe 关闭转义
divisibleby:2
{% for c in content %} <li style="color: {% if forloop.counter|divisibleby:2 %}mediumvioletred{% else %}fuchsia{% endif %}">{{ c }}</li> {% endfor %}
自定义过滤器
mark_down
pip install markdown
创建过滤器的步骤
在模块中创建一个包,templatetags
在templatetags包中创建一个文件(随便起)
在这个创建的文件中写代码
from django.template import Library regitser = Library() @register.filter def md(value): # 默认传入的 import markdown return markdown.markdown(value)
{% load 创建的文件 %}
在template中就可以使用了
自定义截取
# {{content|s:'1,20'}} @register.filter def s(value,args): # '' start ,end = args.split(',') content = value.encode('utf-8').decode('utf-8') return content[int(start):int(end)]
自定义标签
@register.simple_tag() def u(value): return reverse(value)
版权声明 本文属于本站 原创作品,文章版权归本站及作者所有,请尊重作者的创作成果,转载、引用自觉附上本文永久地址: http://blog.lujianxin.com/x/art/1v4r1rrv1syt
下一篇:时光中,追逐与回首
猜你喜欢
文章评论区
作者名片
- 作者昵称:Jeyrce.Lu
- 原创文章:61篇
- 转载文章:3篇
- 加入本站:2046天
作者其他文章
站长推荐
友情链接
站点信息
- 运行天数:2047天
- 累计访问:164169人次
- 今日访问:0人次
- 原创文章:69篇
- 转载文章:4篇
- 微信公众号:第一时间获取更新信息