day65 2018-06-15
1. Django框架详细介绍
MVC框架和MTV框架(了解)
Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性。
Django框架的不同之处在于它拆分的三部分为:Model(模型)、Template(模板)和View(视图),也就是MTV框架
Django的MTV模式
Model(模型):负责业务对象与数据库的对象(ORM)
Template(模版):负责如何把页面展示给用户
View(视图):负责业务逻辑,并在适当的时候调用Model和Template
此外,Django还有一个urls分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
app
命令行创建
python manage.py startapp app01
下面围绕这几个点说
视图系统
1. 视图 views.py
1. FBV(function base view) 基于函数的视图
抛出一个问题:
函数的装饰器能不能直接用来装饰类中的方法
2. CBV(class base view) FBV(function base view)基于类
注意:
使用CBV时,urls.py中也做对应的修改:
# urls.py中
url(r'^add_class/$', views.AddClass.as_view()),
Request对象和Response对象
request对象
当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象。
Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。
请求相关的常用值
· path_info 返回用户访问url,不包括域名
· method 请求中使用的HTTP方法的字符串表示,全大写表示。
· GET 包含所有HTTP GET参数的类字典对象
· POST 包含所有HTTP POST参数的类字典对象
· body 请求体,byte类型 request.POST的数据就是从body里面提取到的
属性
所有的属性应该被认为是只读的,除非另有说明。
3. 上传文件的注意事项: 1. 如果有上传文件,views.py中应该从request.FILES中取上传的文件对象 2. 如果有上传文件,html文件中的form表单一定要加 enctype="multipart/form-data" 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 HttpResponse("上传OK")
注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用:
request.POST.getlist("hobby")
使用
传递字符串 from django.http import HttpResponse response = HttpResponse("Here's the text of the Web page.") response = HttpResponse("Text only, please.", content_type="text/plain") 设置或删除响应头信息 response = HttpResponse() response['Content-Type'] = 'text/html; charset=UTF-8' del response['Content-Type']
Response对象
与由Django自动创建的HttpRequest对象相比,HttpResponse对象是我们的职责范围了。我们写的每个视图都需要实例化,填充和返回一个HttpResponse。
HttpResponse类位于django.http模块中。
使用
传递字符串 from django.http import HttpResponse response = HttpResponse("Here's the text of the Web page.") response = HttpResponse("Text only, please.", content_type="text/plain") 设置或删除响应头信息 response = HttpResponse() response['Content-Type'] = 'text/html; charset=UTF-8' del response['Content-Type']
属性
HttpResponse.content:响应内容
HttpResponse.charset:响应内容的编码
HttpResponse.status_code:响应的状态码
4. JsonResponse
Django封装的一个专门用来返回JSON格式数据的方法()
from django.http import JsonResponse
JsonResponse(字典)(默认传字典)
JsonResponse(列表,safe=False)
默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。
response = JsonResponse([1, 2, 3], safe=False)
补充一个知识点
在python中
我们在开发中通常需要清除浏览器缓存
Django shortcut functions
render和redirect
Render :结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
render()
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。 参数: request:用于生成响应的请求对象。 template_name:要使用的模板的完整名称,可选的参数 context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。 content_type:生成的文档要使用的MIME类型。默认为 DEFAULT_CONTENT_TYPE 设置的值。默认为'text/html' status:响应的状态码。默认为200。 useing: 用于加载模板的模板引擎的名称。 一个简单的例子: from django.shortcuts import render def my_view(request): # 视图的代码写在这里 return render(request, 'myapp/index.html', {'foo': 'bar'}) 上面的代码等于: from django.http import HttpResponse from django.template import loader def my_view(request): # 视图代码写在这里 t = loader.get_template('myapp/index.html') c = {'foo': 'bar'} return HttpResponse(t.render(c, request))
redirect()
参数可以是:
· 一个模型:将调用模型的get_absolute_url() 函数
· 一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称
· 一个绝对的或相对的URL,将原封不动的作为重定向的位置。
默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向。
示例:
你可以用多种方式使用redirect() 函数。
传递一个具体的ORM对象(了解即可) 将调用具体ORM对象的get_absolute_url() 方法来获取重定向的URL: from django.shortcuts import redirect def my_view(request): ... object = MyModel.objects.get(...) return redirect(object) 传递一个视图的名称 def my_view(request): ... return redirect('some-view-name', foo='bar') 传递要重定向到的一个具体的网址 def my_view(request): ... return redirect('/some/url/') 当然也可以是一个完整的网址 def my_view(request): ... return redirect('http://example.com/') 默认情况下,redirect() 返回一个临时重定向。以上所有的形式都接收一个permanent 参数;如果设置为True,将返回一个永久的重定向: def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True) 扩展阅读: 临时重定向(响应状态码:302)和永久重定向(响应状态码:301)对普通用户来说是没什么区别的,它主要面向的是搜索引擎的机器人。 A页面临时重定向到B页面,那搜索引擎收录的就是A页面。 A页面永久重定向到B页面,那搜索引擎收录的就是B页面。
模板
2. 模板语言(重要)
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. == 判断
1. 模板语言变量相关
1. 字典的key对应的值
{{ dic.key}}
2. 列表按索引取值
{{ list.1 }}
3. 对象的属性和方法
{{ obj.name }}
{{ obj.dream }} --> 方法不要加括号
2. Filters (对变量做一些额外的操作)
1. 内置的filter
语法: {{ value|filter_name:参数 }}
default
{{ value|default: "nothing"}}
如果value值没传的话就显示nothing
length
{{ value|length }}
'|'左右没有空格没有空格没有空格
返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
filesizeformat
将值格式化为一个 “人类可读的” 文件尺寸(例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:
{{ value|filesizeformat }}
如果 value 是 123456789,输出将会是 117.7 MB。
slice
切片
{{value|slice:"2:-1"}}
date
格式化
{{ value|date:"Y-m-d H:i:s"}}
safe
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。
比如:
value = "<a href='#'>点我</a>"
{{ value|safe}}
2. 自定义的filter
1. 在app下面新建一个Python package,包名必须叫 templatetags
2. 在上面的包中新建一个python文件,里面定义函数,并且注册到django的模板语言
from django import template
# 生成一个用于注册自定义filter方法的实例
register = template.Library()
@register.filter(name="sb")
def add_sb(value):
return "{} sb".format(value)
3. 使用自定义的filter方法
{% load py文件名 %}
{{ value|sb }}
3. tags
for
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
for循环可用的一些参数:
Variable |
Description |
forloop.counter |
当前循环的索引值(从1开始) |
forloop.counter0 |
当前循环的索引值(从0开始) |
forloop.revcounter |
当前循环的倒序索引值(从1开始) |
forloop.revcounter0 |
当前循环的倒序索引值(从0开始) |
forloop.first |
当前循环是不是第一次循环(布尔值) |
forloop.last |
当前循环是不是最后一次循环(布尔值) |
forloop.parentloop |
本层循环的外层循环 |
for ... empty
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% empty %}
<li>空空如也</li>
{% endfor %}
</ul>
if,elif和else
{% if user_list %}
用户人数:{{
user_list|length }}
{% elif black_list %}
黑名单数:{{
black_list|length }}
{% else %}
没有用户
{% endif %}
当然也可以只有if和else
{% if user_list|length > 5 %}
七座豪华SUV
{% else %}
黄包车
{% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
with
定义一个中间变量
{% with total=business.employees.count %}
{{ total }} employee{{
total|pluralize }}
{% endwith %}
csrf_token
这个标签用于跨站请求伪造保护。
在页面的form表单里面写上{% csrf_token %}
注意事项
1. Django的模板语言不支持连续判断,即不支持以下写法:
{% if a > b > c %}
...
{% endif %}
2. Django的模板语言中属性的优先级大于方法
def xx(request):
d = {"a": 1, "b": 2, "c": 3, "items": "100"}
return render(request,
"xx.html", {"data": d})
如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中:
{{ data.items }}
默认会取d的items key的值。
4. 母版与继承
1. 定义母版 --> 其他很多页面会用到的共用部分 我们可以提取出来放在单独的一个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 %} {% endblock %} </head> <body> <h1>这是母板的标题</h1> {% block page-main %} {% endblock %} <h1>母板底部内容</h1> {% block page-js %} {% endblock %} </body> </html>
注意:我们通常会在母板中定义页面专用的CSS块和JS块,方便子页面替换。
2. 在母版中 通过定义不同的 block 等待子页面来替换对应的内容
3. 在子页面中 通过 {% extends 'base.html '%}来继承已经定义好的母版
4. 在子页面中通过 block 来实现自定义页面内容
通过在母板中使用{% block xxx %}来定义"块"。
5. 通常会在母版中定义 子页面专用的 page-css 和 page-js 两个块
一起定义这两个
5.组件
把功能相对独立的html代码 放在一个单独的文件中 作为组件 供其他页面使用
{% include 'nav.html' %}