Djanjo框架之视图层
视图层
django视图层,视图层就是django项目下的views.py 文件,它的内部是一系列函数或者类,用来专门处理客户端访问请求后处理请求并且返回相依哦那个的数据相当于一个中央情报系统
视图层,熟练的掌握两个对象即可:请求对象(request)和响应对象(HttpResponse)
Httpresponse
request属性
django将请求报文中的请求行,首部信息,内容主体封装成了Httpresponse类中的属性。除了特殊说明之外,其他均为只读的
1.HttpRequest.GET 一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。 2.HttpRequest.POST 一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。 POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中 没有任何的数据,QueryDict 对象依然会被创建。 因此,不应该使用 if request.POST 来检查使用的是否是POST 方法;应该使用 if request.method == "POST" 另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。 注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用: request.POST.getlist("hobby") 3.HttpRequest.body 一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用, 例如:二进制图片、XML,Json等。 但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。 4.HttpRequest.path 一个字符串,表示请求的路径组件(不含域名)。 例如:"/music/bands/the_beatles/" 5.HttpRequest.method 一个字符串,表示请求使用的HTTP 方法。必须使用大写。 例如:"GET"、"POST" 6.HttpRequest.encoding 一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。 这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。 接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。 如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。 7.HttpRequest.META 一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例: 取值: CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。 CONTENT_TYPE —— 请求的正文的MIME 类型。 HTTP_ACCEPT —— 响应可接收的Content-Type。 HTTP_ACCEPT_ENCODING —— 响应可接收的编码。 HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。 HTTP_HOST —— 客服端发送的HTTP Host 头部。 HTTP_REFERER —— Referring 页面。 HTTP_USER_AGENT —— 客户端的user-agent 字符串。 QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。 REMOTE_ADDR —— 客户端的IP 地址。 REMOTE_HOST —— 客户端的主机名。 REMOTE_USER —— 服务器认证后的用户。 REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。 SERVER_NAME —— 服务器的主机名。 SERVER_PORT —— 服务器的端口(是一个字符串)。 从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时, 都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_ 前缀。 所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。 8.HttpRequest.FILES 一个类似于字典的对象,包含所有的上传文件信息。 FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。 注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会 包含数据。否则,FILES 将为一个空的类似于字典的对象。 9.HttpRequest.COOKIES 一个标准的Python 字典,包含所有的cookie。键和值都为字符串。 10.HttpRequest.session 一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。 完整的细节参见会话的文档。 11.HttpRequest.user(用户认证组件下使用) 一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。 如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。 你可以通过 is_authenticated() 区分它们。 例如: if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users. user 只有当Django 启用 AuthenticationMiddleware 中间件时才可用。 ------------------------------------------------------------------------------------- 匿名用户 class models.AnonymousUser django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口, 但具有下面几个不同点: id 永远为None。 username 永远为空字符串。 get_username() 永远返回空字符串。 is_staff 和 is_superuser 永远为False。 is_active 永远为 False。 groups 和 user_permissions 永远为空。 is_anonymous() 返回True 而不是False。 is_authenticated() 返回False 而不是True。 set_password()、check_password()、save() 和delete() 引发 NotImplementedError。 New in Django 1.8: 新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。
request常用方法
1.HttpRequest.get_full_path() 返回 path,如果可以将加上查询字符串。 例如:"/music/bands/the_beatles/?print=true" 注意和path的区别:http://127.0.0.1:8001/order/?name=lqz&age=10 2.HttpRequest.is_ajax() 如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。 大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。 如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware,你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图 以让响应能够正确地缓存。
小白必会三板斧(HTTPRESPONSE)
- httpresponse(0
- 返回字符串类型的数据
HttpResponse()括号内直接跟一个具体的字符串作为响应体,比较直接很简单,所以这里主要介绍后面的两种形式
- render()
- 返回html页面,还可以使用模板语法
render(request,template_name[,context])结合一个给定的模板和一个给定的上下文字典,并且返回一个渲染后的httpresponse对象。
参数:
request: 用于响应请求对象。
template_name: 要使用模板的完整的名称,可选的参数
context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用他
rendeer方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。
- redirect()
- 传递要重定向的一个硬编码url
def my_view(request): return redirect('/some/url')
也可以是一个完整的url:
def my_view(request): .... return redirect('http://www.baidu.com/') 1、301和302的区别 301和302状态码都表示重定向,就是说浏览器再拿到服务器返回的这个状态码后会自动跳转到一个新的url地址,这个地址可以从响应的location首部中获取(用户看到的效果就是他输入的地址A瞬间编程了另外一个地址B)这是他们的共同点 2、不同点在于 301表示就地址的资源已经被永久的移除了(这个资源不可访问了),搜索引擎再抓取新的内容的同时也将旧的网址交换为重定向之后的网址; 302表示就地址资源还在(仍然可以访问)这个重定向只是临时地址从旧地址跳转到了新的地址搜索引擎会抓取新的内容而保存旧的内容。 3、重定向的原因 (1)网站调整(如该网页目录结构) (2)网页被移到一个新的地址 (3)网页扩展名改变(如应用需要把.php改成.html.shtml) 这种情况下,如果不做重定向,则用户收藏夹或者搜索引擎数据库中旧地址只能让访问到一个404 页面错误的信息,访问流量白白丧失,再者某些注册了多个域名的网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。
三板斧的本质
django视图函数必须要返回一个HttpResponse对象 正确
django视图函数必须有一个返回值,并且返回值的数据类型必须是Httpresponse对象
研究三者源码可以得出结论 #HttpResponse class HttpRespoonse(HTTPResponseBase): AN HTTP response class with a string as content #字符串作为内容的HTTP响应类 this content that can be read,appended to or replkaced #可以读取,添加或者替换内容 def __init__(self, content=b'', *args, **kwargs): super(HttpResponse, self).__init__(*args, **kwargs) # 内容是一个字节串。参见' content '属性方法 # Content is a bytestring. See the `content` property methods. self.content = content # render def render(request, template_name, context=None, content_type=None, status=None, using=None): """ Returns a HttpResponse whose content is filled with the result of calling django.template.loader.render_to_string() with the passed arguments. # 返回一个HttpResponse,它的内容中填充了调用的结果 # django.template.loader.render_to_string()和传递的参数 """ content = loader.render_to_string(template_name, context, request, using=using) return HttpResponse(content, content_type, status) # redirect内部是继承了HttpRespone类
jsonresponse
给前端返回json格式的字符串
方式一自己序列化
import json def func(request); d = {'user': 'jiaojiao 好美','password':123} res = json.dumps(d,ensure_ascii=False) return HttpResponse
方式二jsonresponse
from django.http import jsonresponse def func(request) d = {'user':'jiaojiao好美','password':123} return jsonresponse(d) 额外补充 json_dumps_params = {'ensure_ascii':False} safe=False #jsonresponse返回的也是httpresponse
上传文件
前端form表单上传文件注意的事项 1.method必须是post 2.enctype参数需要修改为multipart/form_data 后端暂时需要注意的是 1、配置文件中注释掉48行的内容中间件 2、通过request.FILes获取用户上传的post文件数据
def func3(request) if request.method == 'POST': print(request.POST) file_obj = request.FILES .get('myfile') print(file_obj.name) with open(r'%s'% file_obj.name,'wb')as f: for chunk in file_obj.chunks(): f.write(chunks) return render(request,'func3.html')
CBV与FBV路由匹配的本质
#urls.py urlpatterns = [ url(r'^func4',views.myview.as_view())#cbv写法 #等价 cbv路由匹配本质跟FBV一样 url(r'^fun4',views.view)
2、突破口
知识点:函数名/方法:加括号执行优先级最高
cbv写的是as_view(),加括号意味着再项目启动就会执行,那么我们大胆的猜测,要么是被@staicemthod修饰的静态方法,就是个普通函数没有形参,要么是被@classmehtod修饰的类的方法,类来调自动将类当作第一个参数传入
3. 研究一下源码
@classonlymethod # 类方法,就把它看成@classmethod def as_view(cls, **initkwargs): def view(request, *args, **kwargs): # view是as_view的闭包 self = cls(**initkwargs) # self = MyView()生成一个我们自己写的类的对象 """ 实例化出一个View类的对象,返回一个dispatch()函数,看着跟我们之前写的 视图函数几乎一毛一样,那么我们找一下函数的上级函数没有这个方法,最后在类 里发现了这个dispatch()函数 """ return self.dispatch(request, *args, **kwargs) return view # 返回一个函数的内存地址 def dispatch(self, request, *args, **kwargs): # 获取当前请求并判断是否属于正常的请求(8个) if request.method.lower() in self.http_method_names: # get请求 getattr(对象,'get') handler = 我们自己写的get方法 handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) # 执行我们写的get方法并返回该方法的返回值 # 结论:as_view()最终干的事情就是根据request请求方式来执行视图类的不同请求方法
总结:以后会经常需要看源码,但是在看Python源码的时候,一定要时刻提醒自己面向对象属性方法查找顺序,先从对象自己找,再去产生对象的类里面去找,之后再去父类找,看源码只要看到了self点一个东西,一定要问自己当前这个self到底是谁。

浙公网安备 33010602011771号