Django(视图层、模板层)

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)

一、视图层

视图函数必须返回一个HttpResponse对象。

视图函数可以是一个函数,也可以是一个类

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针对不同的请求方法能够自动执行对应的方法?

可以查看as_view源码:

 

 

 

 

 

1.通过查看源码,我们得知 as_view是一个闭包类的绑定方法,返回一个view方法,调用views.MyLogin.as_view()方法等价于:views.view。再次去view源代码中去查看:

 

 

 2.view方法中,首先会产生一个我们自己写的类即MyLogin的对象self,然后给这个对象的名称空间中添加request、位置参数、关键字参数属性,返回一个dispatch方法(我们自己创建的对象和类中没有,会去父类View中查询)

3.去父类中的dispatch方法查看,会判断request中返回的请求方式是否在八个基本请求方式中,如果在,则通过反射获取该请求方式的在我们的类中的方法,最后返回该方法的调用

django settings源码

1.在from django.conf import global_settings, settings,去settings中查看

 

 

 2.再去LazySettings类中查看

 

 

 3.再去类中的Settings查看

 

 

 4.在Settings类中,我们可以发现里面有两个遍历的for循环,第一次是设置默认的全局的设置:global_settings,第二次是设置用户可以配置的设置:settings。用户配置了就用用户的,用户没有配就用默认的

 

 

 二、模板层

1.模板语法符号

{{}}      变量相关

{%%}  逻辑相关

2.模板传值

Python基本数据数据类型全部支持传递给html文件

注意:传递函数和对象时候,会自动加括号,也就是传递时候会直接调用

对象

  后端给html文件传递数据有两种方式:

  1.以一个字典方式,指名道姓传值

return render(request,'index.html',{'n':n,'f':f})

  2.locals():将当前名称空间中所有的变量名全部传递给html页面

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

取值:django模板语法取值只有一种操作方式:句点符"."

  .索引

  .键

<p>{{ l.2 }}</p>    # 索引
<p>{{ d.username }}</p>    # 键
<p>{{ d.hobby.1.username.1 }}</p>    # 索引和键混合

3.过滤器

  |左边的会当做过滤器的第一个参数,过滤器名右边的会当做过滤器的第二个参数

|length:求数据长度
|add:假发运算
|default:默认值(判断是否为空)
|truncatechars:截取字符
|truncatewords:截取单词
|filesizeformat:文件大小
|slice:切片操作
|date:日期格式化
|safe:转义

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

补充:前后端取消转义

  前端:|safe

  后端:from django.utils.safestring import mark_safe

     mark_safe('<h1>安全滴</h1>')

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

4.标签

{% 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 %}

5.自定义

过滤器、标签、inclusion_tag可以自定义

前期步骤:

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

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

  - 在该文件内 必须先写以下两句代码

from django.template import Library            
register = Library()

自定义示例:

# 自定义过滤器
@register.filter(name='my_sum')
def index(a,b):
    return a + b


# 自定义标签
@register.simple_tag(name='my_baby')
def xxx(a,b,c,d):
    return '%s?%s?%s?%s'%(a,b,c,d)


# 自定义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}
            

使用自定义时候,需要在html文件中导入mytag

{% load mytag %}

6.继承

某一个页面大部分区域都是公用的,那这个页面就可以作为模板页面

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

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

  - 子页面中先导入整个模板

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

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

css、js、content

模板的block块越多,可扩展性越高

子页面调用父页面对应区域的内容,并且可以无限次调用

{{ block.super }}

7.导入

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

语法:

{% include 'left.html' %}

 

 

补充:基于django settings源码实现项目配置文件的,插拔式设计示例:

文件目录:

-mysetting

  - conf

    - settings.py

  - lib

    - conf

      - __init__.py

      - global_settings.py

  start.py

import os
import sys


BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR)


if __name__ == '__main__':
    # 项目启动 就应该朝全局的大字典中设置键值对
    os.environ['xxx'] = 'conf.settings'
    from lib.conf import settings
    print(settings.NAME)
start.py
NAME = '我是暴露给用户的配置文件'
settings.py
NAME = '我是项目默认的配置文件'
global_settings.py
import importlib
import os
from lib.conf import global_settings


class Settings(object):
    def __init__(self):
        # 先循环遍历项目默认的全局配置文件
        for name in dir(global_settings):
            # 判断变量名是否是大写
            if name.isupper():
                # 键值对设置给对象
                k = name  # NAME
                v = getattr(global_settings,name)  # jason
                setattr(self,k,v)

        # 先获取暴露给用户的配置文件的字符串路径
        module_path = os.environ.get('xxx')  # conf.settings
        # 里面importlib模块 导入settings文件
        md = importlib.import_module(module_path)  # md = settings

        # 同上操作
        for name in dir(md):
            # 判断变量名是否是大写
            if name.isupper():
                # 键值对设置给对象
                k = name  # NAME
                v = getattr(md,name)  # jason
                setattr(self,k,v)





settings = Settings()
__init__.py
posted @ 2020-01-07 19:09  treeter  阅读(260)  评论(1编辑  收藏  举报