• Django基础(二)-视图,template


    一、Django Views

    http请求中产生两个核心对象:

    • http请求:HttpRequest对象
    • http响应:HttpResponse对象

    所在位置:django.http,之前我们用到的参数request就是HttpRequest    检测方法:isinstance(request,HttpRequest)

    1.1、HttpRequest对象

    path:       #请求页面的全路径,不包括域名
    
    method:     #请求中使用的HTTP方法的字符串表示。全大写表示。例如
    
                       if  req.method=="GET":
    
                                 do_something()
    
                       elif req.method=="POST":
    
                                 do_something_else()
    
    GET:         #包含所有HTTP GET参数的类字典对象
    
    POST:       #包含所有HTTP POST参数的类字典对象.服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用if req.POST来判断是否使用了HTTP POST 方法;应该使用  if req.method=="POST"
    
    COOKIES:     #包含所有cookies的标准Python字典对象;keys和values都是字符串。
    
    FILES:      #包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中              name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:
    
                filename:      上传文件名,用字符串表示
                content_type:   上传文件的Content Type
                content:       上传文件的原始内容
    
    user:       #是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前
                 没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你
                 可以通过user的is_authenticated()方法来辨别用户是否登陆:
                 if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware
                 时该属性才可用
    
    session:    #唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。
    
    #方法
    get_full_path(),
    比如:http://127.0.0.1:8000/index33/?name=123 ,
    req.get_full_path()得到的结果就是/index33/?name=123
    req.path 得到的结果是/index33
    
    注意一个常用方法:request.POST.getlist('')

    1.2、 HttpResponse对象

    对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。HttpResponse类在django.http.HttpResponse

    在HttpResponse对象上扩展的常用方法:

    页面渲染:         render()(推荐)                 render_to_response(),
    页面跳转:         redirect("路径")
    locals():        #可以直接将函数中所有的变量传给模板
    

    render与redirect区别:

    #url.py
    path('login/',views.login),
    path('name_back/',views.name_back),
    
    #views.py
    def login(request):
        if request.method=="POST":
            if 1:
                return redirect("/name_back/")
                # name="AAA"
                # return render(request,"backend.html",locals())
        return render(request,"login.html",locals())
    
    def name_back(request):
        name="AAA"
        return render(request, "backend.html", locals())
    
    #login.html
    <form action="/login/" method="post">
        <p>姓名<input type="text" name="username"></p>
        <p>性别<input type="text" name="sex"></p>
        <p>邮箱<input type="text" name="email"></p>
        <p><input type="submit" value="submit"></p>
    </form>
    
    #backend.html
    <h1>用户{{ name }}你好</h1>
    
    ##总结render与redirect区别:
    #   1 if render的页面需要模板语言渲染,需要的将数据库的数据加载到html,那么所有的这一部分
    #     除了写在name_back的视图函数中,必须还要写在login中,代码重复,没有解耦.
    
    #   2 the most important: url没有跳转到/name_back/,而是还在/login/,所以当刷新后
    #     又得重新登录.

    二、Django Template

    2.1、模板的组成

    组成:HTML代码+逻辑控制代码

    2.2、变量

    使用双大括号来引用变量:

    语法格式:     {{var_name}}

    Template和Context对象:

    >>> python manange.py shell  (进入该django项目的环境)
    >>> from django.template import Context, Template
    >>> t = Template('My name is {{ name }}.')
    >>> c = Context({'name': 'Stephane'})
    >>> t.render(c)
    'My name is Stephane.'
    
    
    # 同一模板,多个上下文,一旦有了模板对象,你就可以通过它渲染多个context,无论何时我们都可以
    # 像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会
    # 更为高效:
    
    # Low
    for name in ('John', 'Julie', 'Pat'):
        t = Template('Hello, {{ name }}')
        print t.render(Context({'name': name}))
    
    # Good
    t = Template('Hello, {{ name }}')
    for name in ('John', 'Julie', 'Pat'):
        print t.render(Context({'name': name}))

    2.3、深度变量查找

    在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)

    # 首先,句点可用于访问列表索引,例如:
    >>> from django.template import Template, Context
    >>> t = Template('Item 2 is {{ items.2 }}.')
    >>> c = Context({'items': ['apples', 'bananas', 'carrots']})
    >>> t.render(c)
    'Item 2 is carrots.'
    
    #假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点:
    >>> from django.template import Template, Context
    >>> person = {'name': 'Sally', 'age': '43'}
    >>> t = Template('{{ person.name }} is {{ person.age }} years old.')
    >>> c = Context({'person': person})
    >>> t.render(c)
    'Sally is 43 years old.'
    
    #同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有
    #year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性:
    
    >>> from django.template import Template, Context
    >>> import datetime
    >>> d = datetime.date(1993, 5, 2)
    >>> d.year
    >>> d.month
    >>> d.day
    >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
    >>> c = Context({'date': d})
    >>> t.render(c)
    'The month is 5 and the year is 1993.'
    
    # 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适
    # 用于任意的对象。
    >>> from django.template import Template, Context
    >>> class Person(object):
    ...     def __init__(self, first_name, last_name):
    ...         self.first_name, self.last_name = first_name, last_name
    >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
    >>> c = Context({'person': Person('John', 'Smith')})
    >>> t.render(c)
    'Hello, John Smith.'
    
    # 点语法也可以用来引用对象的方法。 例如,每个 Python 字符串都有 upper() 和 isdigit()
    # 方法,你在模板中可以使用同样的句点语法来调用它们:
    >>> from django.template import Template, Context
    >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
    >>> t.render(Context({'var': 'hello'}))
    'hello -- HELLO -- False'
    >>> t.render(Context({'var': '123'}))
    '123 -- 123 -- True'

    2.4、过滤器(filter)的使用

    语法格式:      {{obj|filter:param}}

    add          #给变量加上相应的值
    addslashes   #给变量中的引号前加上斜线
    capfirst     #首字母大写
    cut          #从字符串中移除指定的字符
    date         #格式化日期字符串
    default      #如果值是False,就替换成设置的默认值,否则就是用本来的值
    default_if_none  #如果值是None,就替换成设置的默认值,否则就使用本来的值
    
    
    #实例:
    #value1="aBcDe"
    {{ value1|upper }}
    
    #value2=5
    {{ value2|add:3 }}
    
    #value3='he  llo wo r ld'
    {{ value3|cut:' ' }}
    
    #import datetime
    #value4=datetime.datetime.now()
    {{ value4|date:'Y-m-d' }}
    
    #value5=[]
    {{ value5|default:'空的' }}
    
    #value6='<a href="#">跳转</a>'
    
    {% autoescape off %}
      {{ value6 }}
    {% endautoescape %}
    
    {{ value6|safe }}
    
    {{ value6|striptags }}
    
    #value7='1234'
    {{ value7|filesizeformat }}
    {{ value7|first }}
    {{ value7|length }}
    {{ value7|slice:":-1" }}
    
    #value8='http://www.baidu.com/?a=1&b=3'
    {{ value8|urlencode }}
    

    2.5、标签tag使用

    使用大括号和百分比的组合来表示使用tag:{% tags %}

    2.5.1、{% if %} 的使用

    {% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的所有内容

    {% if num >= 100 %}
    
        {% if num > 200 %}
            <p>num大于200</p>
        {% else %}
            <p>num大于100小于200</p>
        {% endif %}
    
    {% elif num < 100 %}
        <p>num小于100</p>
    
    {% else %}
        <p>num等于100</p>
    
    {% endif %}
    
    
    {% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
    {% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:
    {% if obj1 and obj2 or obj3 %}

    2.5.2、{% for %}的使用

    {% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

    <ul>
    {% for obj in list %}
        <li>{{ obj.name }}</li>
    {% endfor %}
    </ul>
    
    
    #在标签里添加reversed来反序循环列表:
    
        {% for obj in list reversed %}
        ...
        {% endfor %}
    
    #{% for %}标签可以嵌套:
    
        {% for country in countries %}
            <h1>{{ country.name }}</h1>
            <ul>
             {% for city in country.city_list %}
                <li>{{ city }}</li>
             {% endfor %}
            </ul>
        {% endfor %}
    
    
    #系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量,
    #这个变量含有一些属性可以提供给你一些关于循环的信息
    
    1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:
    
        {% for item in todo_list %}
            <p>{{ forloop.counter }}: {{ item }}</p>
        {% endfor %}
    2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0
    3,forloop.revcounter
    4,forloop.revcounter0
    5,forloop.first当第一次循环时值为True,在特别情况下很有用:
    
        
        {% for object in objects %}   
             {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}   
             {{ object }}   
            </li>  
        {% endfor %}  
        
    # 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了
    # 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
    # Django会在for标签的块中覆盖你定义的forloop变量的值
    # 在其他非循环的地方,你的forloop变量仍然可用
    
    
    #{% empty %}
    
    {{li }}
          {%  for i in li %}
              <li>{{ forloop.counter0 }}----{{ i }}</li>
          {% empty %}
              <li>this is empty!</li>
          {% endfor %}
    
    #         [11, 22, 33, 44, 55]
    #            0----11
    #            1----22
    #            2----33
    #            3----44
    #            4----55

    2.5.3、{%csrf_token%}:csrf_token标签

    用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,不会生效。其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。

    image

    image

    2.5.4、{% url %}:  引用路由配置的地址

    <form action="{% url "bieming"%}" >
              <input type="text">
              <input type="submit"value="提交">
              {%csrf_token%}
    </form>

    2.5.5、{% with %}:用更简单的变量名替代复杂的变量名

    {% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}

    2.5.6、{% verbatim %}: 禁止render

    {% verbatim %}
             {{ hello }}
    {% endverbatim %}

    2.5.7、{% load %}: 加载标签库

    自定义filter和simple_tag

    1)在app中创建templatetags模块(必须的)

    2)创建任意 .py 文件,如:my_tags.py

    image

    from django import template
    from django.utils.safestring import mark_safe
    
    register = template.Library()   #register的名字是固定的,不可改变
    
    
    @register.filter
    def filter_multi(v1,v2):
        return  v1 * v2
    
    
    @register.simple_tag
    def simple_tag_multi(v1,v2):
        return  v1 * v2
    
    
    @register.simple_tag
    def my_input(id,arg):
        result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
        return mark_safe(result)

    3)在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

    4)使用simple_tag和filter(如何调用)

    #html文件
    {% load xxx %}   #首行导入
        
        
        
     # num=12
    {{ num|filter_multi:2 }} #24
    {{ num|filter_multi:"[22,333,4444]" }}
    #[22,333,444][22,333,444][22,333,444][22,333,444][22,333,444][22,333,444][22,333,444][22,333,444][22,333,444][22,333,444][22,333,444][22,333,444]
    
    {% simple_tag_multi 2 5 %}  #10,参数不限,但不能放在if for语句中
    {% simple_tag_multi num 5 %} #60

    5)注意查看在settings中的INSTALLED_APPS是否配置app,不然django无法找到自定义的simple_tag.

    6)注意:filter可以用在if等语句后,simple_tag不可以

    {% if num|filter_multi:30 > 100 %}
        {{ num|filter_multi:30 }}
    {% endif %}

    2.5.8、extend(继承)模板标签

    Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?

    模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。

    #----------------------------------------------base模板----------------------------------------------#
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="jquery-3.1.1.js"></script>
        <title>Title</title>
    
        {% block styles %}
    
        {% endblock %}
    
        <style>
            * {
                margin: 0;
                padding: 0
            }
            .nav{
                line-height: 40px;
                 100%;
                background-color: #2459a2;
                color: white;
                font-size: 20px;
                text-align: center;
            }
    
            .left{
                 20%;
                min-height: 600px;
                overflow: auto;
                background-color: lightgrey;
    
            }
    
            .manage{
                text-align: center;
                padding: 20px 0px;
                margin: 20px 0;
                font-size: 18px;
    
            }
    
            .left,.content{
                float: left;
            }
            .content{
    
                 70%;
                min-height: 600px;
    
            }
            a{
                text-decoration: none;
            }
            h1,h2{
                text-align: center;
            }
        </style>
    </head>
    <body>
    <div class="outer">
        <div class="nav">标题</div>
    
        <div class="left">
             <div class="student manage"><a href="/student/">学生管理</a></div>
             <div class="teacher manage"><a href="">老师管理</a></div>
             <div class="course manage"><a href="">课程管理</a></div>
             <div class="classes manage"><a href="">班里管理</a></div>
        </div>
        <div class="content">
    
            {% block  content%}
                 <h1>WELCOME TO LOGIN</h1>
            {% endblock %}
    
    
    
        </div>
    </div>
    
    
    </body>
    </html>
    
    #----------------------------------------------继承base模板----------------------------------------------#
    {% extends "base.html" %}
    {% load staticfiles %}
    
    
    
    {% block styles %}
        <style>
              h2{
                  color: red;
              }
        </style>
    
    {% endblock %}
    
    
    {% block content %}
         {{ block.super }}
         {% for student in student_list %}
               <h2>学生{{ student }}</h2>
         {% endfor %}
         {% include "test.html" %}
    {% endblock %}

    模板继承使用技巧:

    1)如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记

    2)一般来说,基础模板中的 {% block %} 标签越多越好

    3)不允许在同一个模板中定义多个同名的 {% block %}

    4)如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签

  • 相关阅读:
    redis requires Ruby version >= 2.2.2.
    redis-持久化、主从复制、集群
    lucene索引文件大小优化小结
    spring+websocket的整合实例--可使用
    使用nexus3.10搭建maven私有仓库
    oracle 查看所有表的数据量并排序
    Spring框架-经典的案例和demo,一些可以直接用于生产,使用atomikos来处理多数据源的一致性事务等
    ORACLE WITH AS 用法
    判断对象部分属性是否为空
    代码行数统计
  • 原文地址:https://www.cnblogs.com/hujinzhong/p/11577252.html
Copyright © 2020-2023  润新知