Django学习之模板层

三板斧

render,HttpResponse,redirect
render返回一个HTML页面,并且还能够给该页面传数据
render内部原理:
from django.template import Template,Context
def index(request):
    temp = Template('<h1>{{ user }}</h1>')
    con = Context({"user":{"name":'jason',"password":'123'}})
    res = temp.render(con)
    print(res)
    return HttpResponse(res)


FBV和CBV

  视图函数并不仅仅只有函数,也有类

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

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

  

# 问题:基于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()  # 单例模式    
 

模板层

模板语法

  两大类:{{ }} 变量相关

      {% %} 逻辑相关

  为模板传值

过滤器:|  

<p>{{ xxx|safe }}</p>  {# 转义 #}
<p>{{ file_size|filesizeformat }}</p> { # 文件大小 #}
<p>{{ ctime|date:'Y-m-d' }}</p>{# 年月日 #}
<p>{{ ss|default:'' }} default必须要有两个参数</p>{#当|左边的变量为空就会返回|右边的值#}
<p>{{ l|length }}</p> {#返回长度#}
<p>{{ info|truncatewords:3 }}</p>{# 就是按空格截取  三个点不算#}
<p>{{ info|truncatechars:6 }}</p>{#按字符截取内容 三个点也算#}
<p>{{ n|add:100 }}</p>{#数字相加#}
<p>{{ s|add:'hahah 翻车啦' }}</p>{#字符串相加#}
<p>{{ l|slice:'0:3' }}</p>
<p>{{ l|slice:'0:5:2' }}</p>{#切片并且支持步长#}

  前后端取消转义

  前端:  |safa

  后端:  如果不转义传过去的就是字符串

from django.utils.safestring import mark_safe
zzz = mark_safe('<h1>111</h1>')
标签:{% %}(逻辑相关)

for循环


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

关于forloop


Django学习之模板层


if判断


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

with


定义一个中间变量,多用于给一个复杂的变量起别名。


注意等号左右不要加空格。


{% with business.employees.count as total %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}
 
                                {#{% for foo in l %}#}
                {#    <p>{{ forloop }}</p>#}
                {#{% endfor %}#}
                {##}
                {##}
                {#{% if '' %}#}
                {#<p>xxx条件为true</p>#}
                {#    {% else %}#}
                {#    <p>xxx条件为false</p>#}
                {#{% endif %}#}

                {##}
                {#{% for foo in l %}#}
                {#    {% 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判断            

Django学习之模板层

 

自定义标签 过滤器 inclusion_tag

自定义固定的三步走战略:
  1.必须在你的应用下新建一个名为templatetags文件夹
  2.在该文件夹内新建一个任意名称的py文件
  3.在该py文件中固定先写下面两句代码

from  django import template
                    
register = template.Library()
# 自定义过滤器
@register.filter(name='baby')
def index(a,b):

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
@register.inclusion_tag('bigplus.html')
def bigplus(n):
l = []
for i in range(n):
l.append('第%s项'%i)
return {'l':l}

 

模板的继承

  当多个页面整体的样式都大差不差的情况下 可以设置一个模板文件
  在该模板文件中 使用block块划分多个预期
  之后子版在使用模板的时候 可以通过block块的名字 来选定到底需要修改哪一部分区域

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


模板的继承与导入


 
#首先需要再被继承的模块中划分多个区域
{% block 给区域起的名字 %}

{% endblock %}

#通常情况下一个模板中应该至少有三块
{% block css %}
页面css代码块
{% endblock %}

{% block js %}
页面js代码块
{% endblock %}

{% block contet %}  #注意起的名字不加引号
    页面主题内容
{% endblock %}
 

子板继承模板


 
#先继承模板所有的内容
{% extends 'home.html' %}

#然后根据block块的名字修改指定区域的内容
{% block content %}
    <form action="">
    <p>username:<input type="text" class="form-control"></p>
    <p>password:<input type="text" class="form-control"></p>
    </form>
{% endblock %}
 

模板的导入:将一段html当做模块的方式导入另一个html展示


{%  include '想导入的html文件名' %}







单表查询必会13条


# < 1 > all(): 查询所有结果

    # < 2 > filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
    # < 3 > get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)
    # < 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
    # print(models.Book.objects.exclude(pk=1))  # 只要pk不是1的数据全部查询出来


    # < 5 > order_by(*field): 对查询结果排序('-id') / ('price')
    # print(models.Book.objects.order_by('price'))  # 默认是升序
    # print(models.Book.objects.order_by('-price'))  # 加负号就是降序


    # < 6 > reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向
    # print(models.Book.objects.order_by('price').reverse())

    # < 7 > count(): 返回数据库中匹配查询(QuerySet)
    # print(models.Book.objects.count())  # 对查询出来的结果进行一个计数


    # 的对象数量。
    # < 8 > first(): 返回第一条记录
    # print(models.Book.objects.filter(pk=1).first())
    # < 9 > last(): 返回最后一条记录
    # print(models.Book.objects.all())
    # print(models.Book.objects.all().last())

    # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False
    # print(models.Book.objects.filter(pk=1000))
    # print(models.Book.objects.filter(pk=1000).exists())


    # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
    # model的实例化对象,而是一个可迭代的字典序列
    # print(models.Book.objects.values('title','price'))  # 得到的结果是列表套字典



    # < 12 > values_list(*field): 它与values()
    # print(models.Book.objects.values_list('title','price'))  # 得到的结果是列表套元组


    # 非常相似,它返回的是一个元组序列,values返回的是一个字典序列
    # < 13 > distinct(): 从返回结果中剔除重复纪录
    """
    去重的前提是 一定要有完全重复的数据 才能去重
    """
    # print(models.Book.objects.filter(title='三国演义').distinct())
    # print(models.Book.objects.values('title','price','create_time').distinct())