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

关于django后端渲染的笔记

图片丢失 jeeyshe 发表于:2019年4月16日 02:01 分类:【日常笔记 168次阅读

为什么不在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}})
    	姓名:{{ user.name }},年龄:{{ user.age }}
  • 访问对象属性

    render(request,'post.html',{'today':datetime.datetime.today()})
    	{{ today.year }}-{{ today.month }}-{{ today.day }}
  • 访问对象的方法(不能有参数)

    render(request,'post.html',{'duanzi':'hello world'})
    	
    	{{ duanzi.capitalize }}
  • 访问列表(不能使负数索引)

    render(request,'post.html',{'items':['asd','s']})
    
    	{{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_processorsdef 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)
  • 显示图片


版权声明 本文属于本站  原创作品,文章版权归本站及作者所有,请尊重作者的创作成果,转载、引用自觉附上本文永久地址: https://www.lujianxin.com/x/art/1v4r1rrv1syt

文章评论区

作者名片

图片丢失
  • 作者昵称:jeeyshe
  • 原创文章:13篇
  • 转载文章:3篇
  • 加入本站:91天

站点信息

  • 运行天数:92天
  • 累计访问:9760人次
  • 今日访问:25人次
  • 原创文章:16篇
  • 转载文章:4篇
  • 微信公众号:第一时间获取更新信息