django视图层进阶、模板层

django视图层进阶、模板层

视图层

三板斧:

HttpResponnse、redirect、render视图函数返回都是一个HttpResponse对象

jJasonResponse

可以试着阅读以下方法的源码(jsonresponse)

import json
json.dumps({'username':'你好啊'},ensure_ascii=False)  # 不会转码

from django.http import JsonResponse
user_dict = {'username':'你好啊'}
return JsonResponse(user_dict)

参数

1.json_dumps_params  字典
JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})

2.safe
该方法默认只用来序列化字典
l = [1,2,3,4]
JsonResponse(l,safe=False)

form表单上传文件

  1. 必须做的事

    method必须是post

    enctype必须是formdata

  2. 暂时需要做的事

    提交post请求需要将中间件里面的一个csrfmiddleware注释掉(权限认证)

后端获取用户上传的文件

file_obj = request.FILES.get('前端input框name属性值')
file_obj.name  # 文件名
for line in file_obj:
    print(line)

# django中推荐以下写法
for chunk in file_obj.chunks():
    print(chunk)

render简单实现原理

def ab_render(request):
    temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
    user_dict = Context({'user_dict':{'username':'jason','password':123}})
    res = temp.render(user_dict)
    return HttpResponse(res)

视图函数并不一定是函数,也可以是类

FBV:基于函数的视图

CBV:基于类的视图

CBV基本写法

from django.views import view

class MyLogin(view):
    def get(self,request):
        return render(request,'login.html')
    def post(self,request):
        return HttpResponse('我是类里面的post方法')
url(r'^login/',views.MyLogin.as_view())

朝login提交get请求会自动执行MyLogin里面的get方法
而提交post请求也会自动执行MyLogin里面的post方法
为什么MyLogin针对不同的请求方法能够自动执行对应的方法

CBV源码

url(r'^login/',views.MyLogin.as_view())

猜想
as_view要么是类里面定义的普通函数 @staticmethod
要么是类里面定义的绑定给类的方法 @classmethod
看源码发现是绑定给类的方法(看源码不需要每一句都看懂 只看自己能够看得懂)

模板层

{{}}	变量相关
{%%}	逻辑相关

模板语法传值

python基本数据类型全部支持传递给HTML文件

类:

  1. 函数和对象会自动加括号
  2. 模板语法不支持传参

对象:

后端给HTML文件传递数据的两种方式

  1. 指名道姓

    return render(request,'index.html',{'n':n,'f':f})
    
  2. locals() #会将当前名称空间所有的变量名全部传递给HTML页面

    return render(request,'index.html',locals())
    

html页面上,获取到后端传递过来的数据

{{ 变量名 }}

取值:

django模板语法取值,只有一种方式—句点符。

点索引、点键

<p>{{ l.2 }}</p>
<p>{{ d.username }}</p>
<p>{{ d.password }}</p>
<p>{{ d.hobby.1.username.1 }}</p>

过滤器

|length
|add
|default
|truncatechars
|truncatewords
|filesizeformat
|slice
|date
|safe

#验证之前先定义好|左边的变量
<p>过滤器  |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数</p>
1. <p>求数据长度:{{ s|length }}</p>
2. <p>加法运算:{{ n|add:10 }}{{ s|add:13132 }}{{ s|add:'DSB' }}</p>
3. <p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}{{ ff|default:'这个ff布尔值是Flase' }}</p>
4. <p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>
5. <p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}{{ sss|truncatewords:4 }}</p>
6. <p>文件大小:{{ file_size|filesizeformat }}</p>
7. <p>切片操作:{{ s|slice:'0:2' }}{{ s|slice:"0:8:2" }}</p>
8. <p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>
9. <p>转义:{{ res|safe }}{{ res1 }}、后端直接标识安全:{{ res2 }}</p>

前后端取消转义

前端:

|safe

后端:

取消转义模块,告诉前端界面字符串内的标签正常显示在页面上,否则就是一串普通字符。

from django.utils.safestring import mark_safe
mark_safe('<h1>安全滴</h1>')

总结:前端代码不一定非要在前端页面写,可以在后端写好后传递给前端页面使用,这样的话,你就可以利用到后端更加多的逻辑语法。

模板语法之标签(逻辑相关)

{% for foo in l %}  <!--l = [1,2,3,4,5,6]-->
		{% if forloop.first %}
			<p>这是我的第一次</p>
		{% elif forloop.last %}
			<p>这是最后一次了啊~</p>
		{% else %}
			<p>{{ foo }}</p>
		{% endif %}
		{% empty %}
        <p>for循环的对象内部没有值</p>
{% endfor %}

#first代表第一个,last代表最后一个执行结果为:
这是我的第一次
2
3
4
5
这是最后一次了啊~

自定义过滤器及标签 inclusion_tag

先完成一下前期准备工作

  1. 在应用名下新建一个名字必须叫templatetags文件夹

  2. 在该文件夹内新建一个任意名称的py文件(eg:mytag)

  3. 在该文件内,必须先写以下两句代码

    from django.template import Library
    
    register = Library()
    

自定义过滤器

@register.filter(name='my_sum')
def index(a,b):
    return a + b

<p>自定义过滤器的使用</p>
{% load mytag %}
<p>{{ 10|my_sum:90 }}</p>

<p>自定义的过滤器可以在逻辑语句中而自定义的标签不可以</p>
{% if 10|my_sum:100 %}
<p>条件成立</p>
{% endif %}

自定义标签

@register.simple_tag(name='my_baby')
def xxx(a,b,c,d):
    return '%s?%s?%s?%s'%(a,b,c,d)

<p>自定义标签的使用</p>
{% load mytag %}
<p>{% my_baby 1 2 3 'hello world' %}</p>

{% if my_baby 1 2 3 4 %}
<p>条件成立</p>
{% endif %}

自定义inclusion_tag

@register.inclusion_tag('demo.html',name='myin')
def index1(n):
    l = []
    for i in range(n):
        l.append(i)
        # 将列表传递给demo.html
        # return locals()
        return {'l':l}
    
<p>自定义inclusion_tag的使用</p>
{% load mytag %}
{% myin 5 %}

使用 总结 页面上使用他们 统一先导入

{% load mytag %}

模板的继承

某一个页面大部分区域是公用的,那这个页面就可以作为模板页面,当别人继承这个页面之后,如何修改对应的区域

先在模板页面上通过block实现划定区域

{% block content %}
模板页面内容
{% endblock %}

子页面中先导入整个模板

{% extends '模板页面.html'%}
修改特定的区域  通过实现划定好的区域名称
{% block content %}
子页面内容
{% endblock %}

通常情况下,模板页面应该起码有三块区域

{% block css %}
模板页面内容
{% endblock %}

{% block content %}
模板页面内容
{% endblock %}

{% block js %}
模板页面内容
{% endblock %}

模板的block块越多,可扩展性越高,还支持子页面调用父页面对应区域的内容,并且可以无限次调用。

{{ block.super }}

模板的导入

将HTML页面当作模块使用,哪里需要就导哪里,这个HTML页面通常都不是完整的,只是一个局部样式

{% include 'left.html' %}

基于django settings源码实现项目配置文件的,插拔设计

发布了100 篇原创文章 · 获赞 15 · 访问量 3262

猜你喜欢

转载自blog.csdn.net/lipenghandsome/article/details/103880695
今日推荐