Django 0.5

1. MVC(model view controller)框架和MTV(model template view)框架: 耦合性低、重用性高、生命周期成本低

 

   Django的MTV模式

   Model(模型):负责业务对象与数据库的对象(ORM)

   Template(模版):负责如何把页面展示给用户

   View(视图):负责业务逻辑,并在适当的时候调用Model和Template

   此外,Django还有一个urls分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

2. Django视图系统views.py: 接收web请求request,并返回web响应responseHttpResponse,render,redirect等)

  http://www.cnblogs.com/liwenzhou/articles/8305104.html

 

   # 当浏览器向服务端请求一个页面时,Django创建一个HttpRequest对象(一般使用request参数承接这个对象),该对象包含关于请求的元数据。然后,Django加载相应的视图,将这个HttpRequest对象作为第一个参数传递给视图函数。每个视图负责返回一个HttpResponse对象。

    1. FBV(function base view) 基于函数的视图

 

       def add_class(request):

           if request.method == "POST":

               class_name = request.POST.get("class_name")

              models.Classes.objects.create(name=class_name)

               return redirect("/class_list/")

           return render(request, "add_class.html")

 

        #在urls中需如下调用

        url(r'^publisher_list/', views.add_class),    # FBV的注册方式

 

        抛出一个问题:函数的装饰器能不能直接用来装饰类中的方法

 

    2. CBV(class base view) 基于类的视图

 

       from django.views import View

       class AddClass(View):

           def get(self, request):

               return render(request, "add_class.html")

           def post(self, request):

               class_name = request.POST.get("class_name")

              models.Classes.objects.create(name=class_name)

               return redirect("/class_list/")

 

       #在urls中需如下调用

       url(r'^publisher_list/', views.AddClass.as_view()),  # CBV的注册方式

 

    # 具体用FBV还是CBV看需求。一般如果情况复杂,可考虑CBV,使结构更清晰

 

    3. request请求相关的常用值

       a. path_info        返回用户访问url(不包括域名)的路径,无参数

       b. get_full_path()  回用户访问url(不包括域名)的路径,和参数

       c. method           请求中使用的HTTP方法的字符串表示,全大写表示。

       d. GET              包含所有HTTP  GET参数的类字典对象

       e. POST             包含所有HTTP POST参数的类字典对象

       f. body             请求体中的数据,byte类型request.POST的数据就是从body里面提取到的;GET的为b'';POST的为b'name=****'

 

    #补充,如果一个项目有多个app。在urls.py导入时,可以给不同app中的views.py文件取别名,进而引用。

     from app02 import views as v2

 

    4. 上传文件的注意事项:

        1. 如果有上传文件,views.py中应该从request.FILES中取上传的文件对象。

           # request.POST取出的是字符串['hlw.png'],不是上传的文件对象。

        2. 如果有上传文件,html文件中的form表单一定要加enctype="multipart/form-data"

           # 若不加,取出的是一个空的类似字典的对象 ,不是上传的文件对象。

           换言之,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会包含数据。

        3. chunks()是django帮忙封装的优化方法,可以考虑使用。

 

        # views.py

        def upload(request):

            if request.method == "POST":

                file_obj = request.FILES.get("touxiang") # 拿到上传文件对象

                file_name = file_obj.name              # 拿到文件名

                with open(file_name, "wb") as f:          # 在本地新建一个同名文件

                    for line in file_obj.chunks():#从上传的文件对象中一点一点读取数据

                        f.write(line)                     # 写到新建的文件中

            return render(request, "upload_demo.html")

 

        # .html

        <form action="/upload/" method="post" enctype="multipart/form-data">

            <input type="text" name="username">

            <input type="file" name="touxiang">

            <input type="submit" value="提交">

        </form>

 

    5. JsonResponse对象

      Django封装的一个专门用来返回JSON格式数据的方法;是HttpResponse的子类

 

        import json

        HttpResponse(json.dumps(字典))  # HttpResponse()中只能传字符串

 

        from django.http import JsonResponse

        JsonResponse(字典)  # JsonResponse()默认只接收字典类型

        #以上两种方式,得到的结果相同

 

        JsonResponse(列表,safe=False)  # 默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。

 

    6. Django shortcut functions之render()

       #参数

       request: 用于生成响应的请求对象。

       template_name:要使用的模板的完整名称,可选的参数

       context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。

       content_type:生成的文档要使用的MIME类型。默认为DEFAULT_CONTENT_TYPE 设置的值。默认为'text/html'

       status:响应的状态码。默认为200。

       using: 用于加载模板的模板引擎的名称。  #django支持第三方模版方法,如果使用其他模板,可通过using设置

 

    7. Django shortcut functions之redirect()

       默认情况下,redirect()返回的是临时重定向。若设置permanent=True将返回永久重定向。

 

       临时重定向(响应状态码:302)和永久重定向(响应状态码:301)对普通用户来说是没什么区别的,它主要面向的是搜索引擎的机器人。

       A页面临时重定向到B页面,那搜索引擎收录的就是A页面。

       A页面永久重定向到B页面,那搜索引擎收录的就是B页面。

 

3. 模板语言

   http://www.cnblogs.com/liwenzhou/p/7931828.html

 

    1. 目前已经学到的模板语言内容

       # 变量相关用{{ }},逻辑相关用{% %}

        1. {{变量}}

        2. {% 逻辑操作%}

            1. for循环

                {% for i in list %}

                    {{ i }}

                {% endfor %}

 

               forloop.counter

               forloop.counter0

                forloop.last

 

                {% empty %}

 

            2. if判断

                {% if 条件%}

                    条件成立要做的事儿

                {% else %}

                    条件不成立要做的事儿

                {% endif %}

 

            3. 逻辑判断

                1. in 判断

                2. == 判断

 

    2. 模板语言变量相关(点所有)

        1. 字典的key对应的值

            {{ dic.key}}

        2. 列表按索引取值

            {{ list.1 }}

        3. 对象的属性和方法

            {{ obj.name }}

            {{ obj.dream }}  --> 方法不要加括号,django自动帮助补全拼接

 

    3. Filters (对变量做一些额外的操作)

       {{ value|filter_name:参数}}  # '|'左右没有空格没有空格没有空格

 

        1. 内置的filter

           {{ value|default: "nothing"}}  # 如果value值没传的话就显示nothing

           {{ value|length }}  # 返回value的长度,如value=['a', 'b', 'c', 'd']的话,就显示4.

           {{ value|filesizeformat }}  # 如果value 是123456789,输出将会是117.7 MB。

           {{value|slice:"2:-1"}}

           {{ value|date:"Y-m-d H:i:s"}}

           {{ value|safe}}  # 告诉Django这段代码是安全的不必转义。

           # 为保证安全,Django的模板中会对HTML标签和JS等语法标签进行自动转义。若不希望转译,可设置safe

 

        2. 自定义的filter

            1. 在app下面新建一个Python package,包名必须叫templatetags

 

            2. 在上面的包中新建一个python文件(用于存放自定义filter的文件),里面定义函数,并且注册到django的模板语言

                from django import template

                # 生成一个用于注册自定义filter方法的实例

                register = template.Library()

 

                @register.filter(name="sb")

                def add_sb(value):

                    return "{} sb".format(value)

 

               @register.filter(name="add")

                def add(value, arg):

                    return "{} {}".format(value, arg)

 

            3. 使用自定义的filter方法  #在html中

                {% load py文件名%}

                {{ value|sb }}

                {{ name|add:"super dsb" }}

 

    4. truncatechars

       {{ value|truncatechars:9}}  # 显示6个原文字符+三个. ;如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

 

    5. Tags  #和Filters相比,Tags功能更丰富,支持逻辑等

 

        # for

        <ul>

        {% for user in user_list %}

            <li>{{ user.name }}</li>

        {% endfor %}

        </ul>

 

        forloop.counter    当前循环的索引值(从1开始)

        forloop.counter0  当前循环的索引值(从0开始)

        forloop.revcounter当前循环的倒序索引值(从1开始)

        forloop.revcounter0    当前循环的倒序索引值(从0开始)

        forloop.first   当前循环是不是第一次循环(布尔值)

        forloop.last    当前循环是不是最后一次循环(布尔值)

        forloop.parentloop      本层循环的外层循环

 

        {% empty %}

 

        # if,elif,else

        {% if user_list %}

          用户人数:{{ user_list|length }}

        {% elif black_list %}

          黑名单数:{{ black_list|length }}

        {% else %}

          没有用户

        {% endif %}

 

        if语句支持and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

 

        # with (定义一个中间变量;取别名)

        {% with total=business.employees.count %}

            {{ total }} employee{{ total|pluralize }}

        {% endwith %}

 

    6. 注意事项

       1. Django的模板语言不支持连续判断,即不支持以下写法:

          {% if a > b > c %}

            ...

          {% endif %}

 

          #python支持连续判断,但如果用Django模板,则不能使用连续判断

 

           若a=10, b=20, c=-5, 判断a>b>c的布尔值

           python: False; a>b and b>c -> False

           HTML: True; a>b ->False, False>-5 => 0>-5 -> True

       2. Django的模板语言中属性的优先级大于方法

          def xx(request):

              d = {"a": 1, "b": 2, "c": 3, "items": "100"}

              return render(request, "xx.html", {"data": d})

 

          {{ data.items }  # 默认会取d的items key的值。

 

    7. 母版与继承

        1. 定义母版   --> 其他很多页面会用到的共用部分 我们可以提取出来放在单独的一个html文件中

 

        2. 在母版中,通过定义不同的block 等待子页面来替换对应的内容

 

        3. 在子页面中,通过{% extends 'base.html '%}来继承已经定义好的母版

           # 继承语句要放在子模板的最上方

 

        4. 在子页面中通过block 来实现自定义页面内容         

           {% extends 'base.html '%}

           {% block page-main %}

              <p>世情薄</p>

              <p>人情恶</p>

              <p>雨送黄昏花易落</p>

            {% endblock %}

 

        5. 通常会在母版中定义 子页面专用的page-css 和page-js 两个块,方便子页面替换

 

        #base.html

        <!DOCTYPE html>

        <html lang="en">

        <head>

          <meta charset="UTF-8">

          <meta http-equiv="x-ua-compatible" content="IE=edge">

          <meta name="viewport" content="width=device-width, initial-scale=1">

         <title>Title</title>

 

          {% block page-css %}  # 某些子页面单独用的css可置于此

 

          {% endblock %}

 

        </head>

        <body>

 

        <h1>这是母板的标题</h1>

        {% block page-main %}

 

        {% endblock %}

        <h1>母板底部内容</h1>

 

        {% block page-js %}

 

        {% endblock %}

 

        </body>

        </html>

 

    8.组件

        把功能相对独立的html代码(导航条,页尾信息等)放在一个单独的文件中 作为组件 供其他页面使用

        {% include 'nav.html' %} # 放在body里

        # 以nav.html为例,只放<nav>...</nav>即可

 

    #补充

一般brower会自动帮忙加载缓存,但当开发时,不希望缓存干扰测试结果,可在检查页面做如下设置

posted @ 2018-06-19 20:46  yangli0504  阅读(132)  评论(0编辑  收藏  举报