Django 框架 第三章FBV,CBV,模版层

时间:2019-09-19
本文章向大家介绍Django 框架 第三章FBV,CBV,模版层,主要包括Django 框架 第三章FBV,CBV,模版层使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1,

FBV与CBV

视图函数并不只是指函数 也可以是类

FBV(基于函数的视图) 面向函数式编程

CBV(基于类的视图)   面向对象式编程

"""get请求来就会走类里面get方法,post请求来就会走类里面post方法 为什么???"""
                    
                    urls.py中
                        url(r'^login/',views.MyLogin.as_view())
                    views.py中
                        from django.views import View


                        class MyLogin(View):
                            def get(self,request):
                                print("from MyLogin get方法")
                                return render(request,'login.html')
                            def post(self,request):
                                return HttpResponse("from MyLogin post方法")
                    

## 研究方向

                        1.从url入手
                        url(r'^login/',views.MyLogin.as_view())  由于函数名加括号执行优先级最高,所以这一句话一写完会立刻执行as_view()方法
                        
                        @classonlymethod
                        def as_view(cls, **initkwargs):  # cls就是我们自己的写的类 MyLogin
                            def view(request, *args, **kwargs):
                                self = cls(**initkwargs)  # 实例化产生MyLogin的对象  self = MyLogin(**ininkwargs)
                                if hasattr(self, 'get') and not hasattr(self, 'head'):
                                    self.head = self.get
                                self.request = request
                                self.args = args
                                self.kwargs = kwargs
                                # 上面的几句话都仅仅是在给对象新增属性
                                return self.dispatch(request, *args, **kwargs)  # dispatch返回什么 浏览器就会收到什么
                                # 对象在查找属性或者方法的时候 你一定要默念 先从对象自己这里找  然后从产生对象的类里面找  最后类的父类依次往后
                            return view
                        
                        通过源码发现url匹配关系可以变形成
                        url(r'^login/',views.view)  # FBV和CBV在路由匹配上是一致的 都是url后面跟函数的内存地址
                        2.当浏览器中输入login 会立刻触发view函数的运行
                                def dispatch(self, request, *args, **kwargs):
                                    # Try to dispatch to the right method; if a method doesn't exist,
                                    # defer to the error handler. Also defer to the error handler if the
                                    # request method isn't on the approved list.
                                    # 我们先以GET为例
                                    if request.method.lower() in self.http_method_names:  # 判断当前请求方法是否在默认的八个方法内
                                        # 反射获取我们自己写的类产生的对象的属性或者方法
                                        # 以GET为例  handler = getattr(self,'get','取不到报错的信息')
                                        # handler = get(request)
                                        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
                                    else:
                                        handler = self.http_method_not_allowed
                                    return handler(request, *args, **kwargs)  # 直接调用我们自己的写类里面的get方法
                            # 源码中先通过判断请求方式是否符合默认的八个请求方法 然后通过反射获取到自定义类中的对应的方法执行

##  

django settings源码

前提:

1.django除了暴露给用户一个settings.py配置文件之外  自己内部还有一个全局的配置文件

2.我们在使用配置文件的时候 可以直接直接导入暴露给用户的settings.py也可以使用django全局的配置文件 并且后者居多

from django.conf import settings

3.django的启动入口是manage.py 

import os
            import sys

            if __name__ == "__main__":
                # django在启动的时候 就会往全局的大字典中设置一个键值对  值是暴露给用户的配置文件的路径字符串
                os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day54.settings")
            
            class Settings(object):
                def __init__(self, settings_module):  # settings_module = 'day54.settings'
                    # update this dict from global settings (but only for ALL_CAPS settings)
                    for setting in dir(global_settings):  # django全局配置文件
                        # dir获取django全局配置文件中所有的变量名
                        if setting.isupper():  # 判断文件中的变量名是否是大写 如果是大写才会执行/生效
                            setattr(self, setting, getattr(global_settings, setting))  # 给settings对象设置键值对
                            # 给settings对象设置键值对  settings[配置文件中大写的变量名] = 配置文件中大写的变量名所对应的值

                    # store the settings module in case someone later cares
                    self.SETTINGS_MODULE = settings_module  # 'day54.settings'

                    mod = importlib.import_module(self.SETTINGS_MODULE)  # mod = 模块settings(暴露给用户的配置文件)
                    for setting in dir(mod):  # for循环获取暴露给用户的配置文件中所有的变量名
                        if setting.isupper():  # 判断变量名是否是大写
                            setting_value = getattr(mod, setting)  # 获取大写的变量名所对应的值
                            setattr(self, setting, setting_value)  # 给settings对象设置键值对
                            """
                            d = {}
                            d['username'] = 'jason'
                            d['username'] = 'egon'
                            用户如果配置了就用用户的
                            用户如果没有配置就用系统默认的
                            其实本质就是利用字典的键存在就是替换的原理 实现了用户配置就用用户的用户没配置就用默认的
                            """
                
            class LazySettings(LazyObject):
                    def _setup(self, name=None):
                        # os.environ你可以把它看成是一个全局的大字典
                        settings_module = os.environ.get(ENVIRONMENT_VARIABLE)  # 从大字典中取值键为DJANGO_SETTINGS_MODULE所对应的值:day54.settings
                        # settings_module = 'day54.settings'
                        self._wrapped = Settings(settings_module)  # Settings('day54.settings')
                        
                
            settings = LazySettings()  # 单例模式    

Django模板系统

常用语法

只需要记两种特殊符号:

{{  }}和 {% %}

变量相关的用{{}},逻辑相关的用{%%}。

def template_test(request):
    l = [11, 22, 33]
    d = {"name": "alex"}

    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age

        def dream(self):
            return "{} is dream...".format(self.name)

    Alex = Person(name="Alex", age=34)
    Egon = Person(name="Egon", age=9000)
    Eva_J = Person(name="Eva_J", age=18)

    person_list = [Alex, Egon, Eva_J]
    return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})

模版中支持的写法

{# 取l中的第一个参数 #}
{{ l.0 }}
{# 取字典中key的值 #}
{{ d.name }}
{# 取对象的name属性 #}
{{ person_list.0.name }}
{# .操作只能调用不带参数的方法 #}
{{ person_list.0.dream }}

过滤器:  |

                    l |length

                        add

                        default

                        filesizeformat

                        truncatechars

                        truncatewords

前后端取消转义:

前端:

|safe

后端:

from django.utils.safestring import mark_safe

zzz = mark_safe('<h1>费电话费给你发</h1>')

|safe

|filesizeformat

    |date               

    slice 支持切片,可加步长

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
{#<p>{{ n }}</p>#}
{#<p>{{ f }}</p>#}
{#<p>{{ s }}</p>#}
{#<p>{{ l }}</p>#}
{#<p>{{ d }}</p>#}
{#<p>{{ t }}</p>#}
{#<p>{{ se }}</p>#}
{#<p>传函数名,会自动加括号调用该函数,前端展示的是函数调用之后的返回值:{{ index }}#}
{#    注意:如果函数需要参数的话  那么不好意思 模板语法不支持#}
{#</p>#}
{#<p>{{ obj }}</p>#}
{#<p>{{ obj.get_self }}</p>#}
{#<p>{{ obj.get_cls }}</p>#}
{#<p>{{ obj.get_static }}</p>#}
{#<p>总结:django的模板语法 不支持给函数传参!!!</p>#}

<br>
{#<h1>模板语法之标签:内部原理(会将|前面的当做第一个参数传入标签中)</h1>#}
{#<p>{{ l|length }}</p>#}
{#<p>{{ n|length }}</p>#}
{#<p>{{ ss|default:'当|左边的变量为空就会返回|右边的值' }}  default跟你后端get方法很想</p>#}
{#<p>{{ ss|default:'' }} default必须要有两个参数</p>#}
{#<p>{{ file_size|filesizeformat }}</p>#}
{#<p>{{ info|truncatewords:3 }} 就是按空格截取  三个点不算</p>#}
{#<p>{{ info1|truncatewords:3 }}</p>#}
{##}
{#<p>{{ info|truncatechars:6 }}按字符截取内容 三个点也算</p>#}
{##}
{#<p>{{ xxx|safe }}</p>#}
{#<p>{{ yyy|safe }}</p>#}
{#<p>{{ zzz }}</p>#}
{##}
{##}
{#<p>{{ ctime }}</p>#}
{#<p>{{ ctime|date:'Y-m-d' }} 只需要掌握年月日就可以了</p>#}
{##}
{##}
{#<p>{{ n|add:100 }}</p>#}
{#<p>{{ s|add:'hahah 翻车啦' }}</p>#}



<p>{{ l|slice:'0:3' }}</p>
<p>{{ l|slice:'0:5:2' }}</p>

<br>
<h1>模板语法之标签(逻辑相关)</h1>
{#{% for foo in l %}#}
{#    <p>{{ forloop }}</p>#}
{#{% endfor %}#}
{##}
{##}
{#{% if '' %}#}
{#<p>xxx条件为true</p>#}
{#    {% else %}#}
{#    <p>xxx条件为false</p>#}
{#{% endif %}#}

{##}
{#{% for foo in '' %}#}
{#    {% if forloop.first %}#}
{#        <p>这是我的第一次</p>#}
{#        {% elif forloop.last %}#}
{#        <p>这是最后一次了啊</p>#}
{#        {% else %}#}
{#        <p>来啊来啊!!!</p>#}
{#    {% endif %}#}
{#    {% empty %}#}
{#    <p>当for循环的对象为空的时候 会走empty</p>#}
{#{% endfor %}#}

{##}
{#<p>#}
{#    django模板语法在取值的时候 统一使用句点符(大白话就是 点号   .)#}
{#    {% with l.6.3.name as ttt %}  可以给一个比较复杂的取值操作取一个别名 之后在with语句中 就可以使用该别名#}
{#        {{ ttt }}#}
{#        {{ l.6.3.name }}#}
{#    {% endwith %}#}
{#</p>#}


{#{% for foo in d.keys %}#}
{#    <p>{{ foo }}</p>#}
{#{% endfor %}#}
{#{% for foo in d.values %}#}
{#    <p>{{ foo }}</p>#}
{#{% endfor %}#}
{#{% for foo in d.items %}#}
{#    <p>{{ foo }}</p>#}
{#{% endfor %}#}

{#<h1>自定义过滤器的使用#}
{#自定义过滤器 只能由两个形参#}
{#    但是你可以在给第二个参数传值的时候 传一个字符串#}
{##}
{#    只要思想不滑坡#}
{#    方法总比困难多#}
{#    {{ 123|baby:'1|2|3|4|5|6'}}#}
{#</h1>#}
{#{% load mytag %}#}
{#{{ 123|baby:1}}#}


{#<h1>自定义标签#}
{#支持传多个参数  参数与参数之间 空格隔开即可#}
{#</h1>#}
{##}
{#{% load mytag %}#}
{#{% jason 1 2 3 year=2 %}#}


<h1>自定义inclusion_tag
当你的页面上有一部分html代码需要经常被各个地方使用  并且需要传参才能渲染出来
    那么你可以把该html代码部分制作成一个inclusion_tag
    任何页面都能使用






</h1>
{% load mytag %}
{% bigplus 5 %}

<br>
{% bigplus 10 %}





















</body>
</html>

## 标签的使用

                    {#{% for foo in l %}#}
                    {#    <p>{{ forloop }}</p>#}
                    {#{% endfor %}#}
                    {##}
                    {##}
                    {#{% if '' %}#}
                    {#<p>xxx条件为true</p>#}
                    {#    {% else %}#}
                    {#    <p>xxx条件为false</p>#}
                    {#{% endif %}#}

                    {##}
                    {#{% for foo in '' %}#}
                    {#    {% if forloop.first %}#}
                    {#        <p>这是我的第一次</p>#}
                    {#        {% elif forloop.last %}#}
                    {#        <p>这是最后一次了啊</p>#}
                    {#        {% else %}#}
                    {#        <p>来啊来啊!!!</p>#}
                    {#    {% endif %}#}
                    {#    {% empty %}#}
                    {#    <p>当for循环的对象为空的时候 会走empty</p>#}
                    {#{% endfor %}#}

                    {##}
                    {#<p>#}
                    {#    django模板语法在取值的时候 统一使用句点符(大白话就是 点号   .)#}
                    {#    {% with l.6.3.name as ttt %}  可以给一个比较复杂的取值操作取一个别名 之后在with语句中 就可以使用该别名#}
                    {#        {{ ttt }}#}
                    {#        {{ l.6.3.name }}#}
                    {#    {% endwith %}#}
                    {#</p>#}


                    {% for foo in d.keys %}
                        <p>{{ foo }}</p>
                    {% endfor %}
                    {% for foo in d.values %}
                        <p>{{ foo }}</p>
                    {% endfor %}
                    {% for foo in d.items %}
                        <p>{{ foo }}</p>
                    {% endfor %}
            
                for循环里面的forloop对象
                if判断

### 

自定义标签 过滤器 inclusion_tag

自定义固定的三步走战略:

1.必须在你的应用下新建一个名为templatetags文件夹

2.在该文件夹内新建一个任意名称的py文件

3.在该py文件中固定先写下面两句代码

                        from  django import template
                        
                        register = template.Library()
            
            
            
            
                    from django import template


                    register = template.Library()
                    # 自定义过滤器 只能有2个形参数
                    @register.filter(name='baby')
                    def index(a,b):
                        # 该过滤器只做一个加法运算  是|add建议版本
                        """
                        |length
                        |add
                        |default
                        |filesizeformat
                        |truncatewords
                        |truncatechars
                        |safe
                        |slice

                        :param a:
                        :param b:
                        :return:
                        """
                        print('下午刚起床 一脸懵逼')
                        return a + b

 

## 

# 自定义标签

# 支持传多个值
                    @register.simple_tag(name='jason')
                    def xxx(a,b,c,year):
                        return '%s?%s|%s{%s'%(a,b,c,year)

                    
                    
                    # 自定义inclusion_tag
                    """
                    接收用户传入的参数  然后作用于一个html页面
                    在该页面上渲染数据 之后将渲染好的页面
                    放到用户调用inclusion_tag的地方
                    """
                    
                    
                    # 自定义inclusion_tag
                    @register.inclusion_tag('bigplus.html')
                    def bigplus(n):
                        l = []
                        for i in range(n):
                            l.append('第%s项'%i)
                        return {'l':l}

自定义filter

自定义过滤器只是带有一个或两个参数的Python函数:

  • 变量(输入)的值 - -不一定是一个字符串
  • 参数的值 - 这可以有一个默认值,或完全省略

例如,在过滤器{{var | foo:'bar'}}中,过滤器foo将传递变量var和参数“bar”

1,自定义filter代码文件摆放位置:

app01/
    __init__.py
    models.py
    templatetags/  # 在app01下面新建一个package package
        __init__.py
        app01_filters.py  # 建一个存放自定义filter的文件
    views.py

# 编写自定义filter

from django import template
register = template.Library()


@register.filter(name="cut")
def cut(value, arg):
    return value.replace(arg, "")


@register.filter(name="addSB")
def add_sb(value):
    return "{} SB".format(value)

使用自定义filter

{# 先导入我们自定义filter那个文件 #}
{% load app01_filters %}

{# 使用我们自定义的filter #}
{{ somevariable|cut:"0" }}
{{ d.name|addSB }}

Tags

for循环

普通for循环

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% endfor %}
</ul>

for循环可用的一些参数:

 

for ... empty

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% empty %}
    <li>空空如也</li>
{% endfor %}
</ul>

if判断

if,elif和else

 
{% if user_list %}
  用户人数:{{ user_list|length }}
{% elif black_list %}
  黑名单数:{{ black_list|length }}
{% else %}
  没有用户
{% endif %}

模板的继承

当多个页面整体的样式都大差不差的情况下 可以设置一个模板文件

在该模板文件中 使用block块划分多个预期

之后子版在使用模板的时候 可以通过block块的名字 来选定到底需要修改哪一部分区域

模板一般情况下 应该至少有三个可以被修改的区域

{% block css %}

子页面自己的css代码

{% endblock %}

{% block content %}

子页面自己的html代码

{% endblock %}

{% block js %}

子页面自己的js代码

{% endblock %}

# 模板的继承  使用方式

  

 {% extends 'home.html' %}

 

    {% block css %}

     <style>

      h1 {

       color: red;

      }

     </style>

    {% endblock %}

 

 

 

    {% block content %}

    <h1>登陆页面</h1>

     <form action="">

      <p>username:<input type="text" class="form-control"></p>

      <p>password:<input type="text" class="form-control"></p>

      <input type="submit" class="btn btn-danger">

     </form>

    {% endblock %}

 

 

    {% block js %}

 

    {% endblock %}

 

 

    # 一般情况下 模板上的block越多 页面的可扩展性就越强

 

 

 

   模板的导入

    {% include 'beautiful.html' %}

 

 

原文地址:https://www.cnblogs.com/chendaodeng/p/11552680.html