文章详情页 您现在的位置是:网站首页>文章详情

关于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篇
  • 微信公众号:第一时间获取更新信息