今日学习目标
- 学习Django框架(视图层)
文章目录
学习内容
- 虚拟环境
- django路由层版本区别
- 视图函数的返回值
- 接收文件数据
- FBV与CBV(基于函数的视图、基于类的视图)
- 模板语法传值
一、虚拟环境
不同的项目应该有各自独立的解释器环境,最大化节省资源,实际功能中针对不同项目只会安装该项目所用到的模块,用不到的一概不装。
诸多项目在你的机器上如何无障碍的打开并运行
- 方式1:把所有需要用到的模块全部下载下来 如果有相同模块不同版本每次都重新下载替换
- 方式2:提前准备好多个解释器环境 针对不同的项目切换即可
创建虚拟环境
相当于在下载一个全新的解释器
识别虚拟环境
文件目录中有一个venv文件夹
如何切换环境
选择不用的解释器即可 全文不要再次勾选new enviroment...
注意
每创建一个虚拟环境,就类似于重新下载了一个纯净的python解释器
虚拟环境不要创建太多个,会占用内存。
二、django路由层版本区别
django1.X和django2.X及以上
-
urls.py中1.x用的是url,而2.x用的是path
并且2.x中的path第一个不支持正则表达式,写什么就匹配什么
如果你觉得不好用,2.x里面还有re_path 这个re_path就是你1.x里面的urlfrom django.urls import path,re_path
-
path方法提供了转换器功能
path('index/<int:id>/', index)
匹配对应位置的数据并且自动转换类型
‘’‘有五种转换器可供选择’‘’
参考:https://blog.csdn.net/weixin_49111957/article/details/109754240
三、视图函数的返回值
当浏览器向服务器发起数据请求的时候,那么服务器用来响应的视图函数的返回值的种类有两种,分别是HTML响应(HttpResponse、render、redirect)和JsonResponse(前后端分离)
HTML响应
- (1)HttpResponse
不使用模板,直接HttpResponse()
例子:创建视图函数
def testResponse(request):
response = HttpResponse()
response.content ='英雄联盟'
response.status_code = 404
# 直接写出文本
response.write('亚索')
# 一次性读取剩余字节,冲刷缓存区
response.flush()
return response
结果
- (2)render
render方法的返回值类型也是一个HttpResponse
例子:对render进行剪切一下,方便查看类型
def testRender(request):
response = render(request,'testRender.html')
print(type(response))
return response
结果
- (3)Redirect
重定向
其是HttpResponse的子类,响应重定向:可以实现服务器内部跳转
def testRedirect(request):
# 重定向就是执行其他的视图函数
return HttpResponseRedirect('/res/index/')
结果
2.JsonResponse
django的视图函数,是不可以直接返回data的
JsonResponse 缺点:1.中文乱码 2.序列化
解决中文乱码方案:
def testJson(request):
data = {
'msg': 'ok',
'status': 200,
'name': '张三',
}
# 忽略编码
return JsonResponse(data=data,json_dumps_params={'ensure_ascii':False})
结果
解决序列化方案:
from django.http import JsonResponse
def index(request):
data = {'name':'jason好帅哦 我好喜欢','password':123}
l = [1,2,3,4,5,6,7,8]
# 后端朝前端返回json格式的字符串方式一
# res = json.dumps(data,ensure_ascii=False) # 把参数ensure_ascii=False就不会把中文转成json格式
# return HttpResponse(res)
# 方式二
# return JsonResponse(data,json_dumps_params={'ensure_ascii':False}) # 让参数json_dumps_params={'ensure_ascii':False}作用也是不把中文转成json格式
return JsonResponse(l,safe=False) # JsonResponse默认只支持序列化字典,如果你想序列化其他类型(json能够支持的类型),需要将safe参数由默认的True改为False。
补充:
JsonResponse这个类是HttpRespon的子类,它主要和父类的区别在于:
1.它的默认Content-Type 被设置为: application/json
2.第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data可以填入任何能被转换为JSON格式的对象,比如list, tuple, set。 默认的safe 参数是 True. 如果你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常。
四、接收文件数据
注意事项:
-
enctype属性需要由默认的urlencoded变成formdata
-
method属性需要由默认的get变成post
(目前还需要考虑的是 提交post请求需要将配置文件中的csrf中间件注释)
-
如果form表单上传文件 后端需要在request.FILES获取文件数据 而不再是POST里面
例子:
urls.py
from django.conf.urls import url
from django.contrib import admin
from homework import views
urlpatterns = [
url(r'^file/$', views.file)
]
views.py
from django.shortcuts import render, HttpResponse, redirect, reverse
def file(request):
if request.method == 'POST':
print(request.FILES)
# 获取文件对象
file_obj = request.FILES.get('myfile')
print(file_obj.name)
with open(file_obj.name, 'wb') as f:
# for line in file_obj: # file_obj可以直接看成文件句柄f
# f.write(line)
# 也可以用下面一种方法
for chunk in file_obj.chunks():
f.write(chunk)
return render(request, 'file.html')
在templates目录下新建file.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="myfile">
<input type="submit" value="提交">
</form>
</body>
</html>
request其他方法
这个下边的方法是获取请求时候的一些入参
def detail(request):
# print(request.GET) #获取url里边传递的参数 ?id=1
# print(request.POST) #获取body里边的key values
# print(request.method)#获取请求方式
# # print(request.META)#获取header
# print(request.path_info)#获取当前路径 /api/user/login
# print(request.headers)#获取header
# print(request.content_type)#请求过来的数据类型是啥样的
# print(request.FILES)#如果有文件
# print(request.COOKIES)#获取cookie
print(request.body)#是json的用它
return HttpResponse('ok')
五、FBV与CBV(基于函数的视图、基于类的视图)
-
FBV(Function Based View):基于函数的视图
-
CBV(Class Based View):基于类的视图
CBV和FBV在路由匹配上,规则都是一样的,都是路由后面跟的函数的内存地址
在类中写了两个方法 一个叫get一个叫post
CBV:基于类的视图
from django import views
class MyLoginView(views.View):
def get(self, request):
return HttpResponse("from CBV get view")
def post(self, request):
return HttpResponse("from CBV post view")
结果总结:
- 如果请求方式是GET 则会自动执行类里面的get方法
- 如果请求方式是POST 则会自动执行类里面的post方法
为什么前端get请求来就会触发get方法
post请求来就会触发post方法 如何实现的???
这就讲一下CBV源码的实现思路
1、CBV路由层
url(r'^reg/',views.MyReg.as_view()) # 在这必须调用自己写的MyReg类中的as_view方法
# as_view的源码
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs) # cls就是我们自己的写的MyReg类
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)
# 对象在查找属性或方法的时候 顺序是什么? 先从自己找 再从产生对象的类中找 再去类的父类中找...
"""也就意味着你在看源码的时候 你一定要牢记上面的话"""
return view
2、视图层views.py中写上继承view的类
from django.views import View
class MyReg(View):
def get(self,request):
return render(request,'reg.html')
def post(self,request):
return HttpResponse("我是MyReg类中post方法")
3、在前端发送请求的时候就会进到CBV源码的dispatch方法判断请求方式在不在默认的八个请求方式中。
"""CBV源码最精髓的部分"""
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names: # 判断当前请求方式在不在默认的八个请求方式中
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
# handler = getattr(自己写的类产生的对象,'小写的请求方法(get\post)','获取不到对应的方法就报错')
# handler就是我们自己定义的跟请求方法相对应的方法的函数内存地址
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 再调用获取到的方法
六、模板语法传值
补充:
django提供的模板语法只有两个符号
{{}}:主要用于变量相关操作(引用)
{%%}:主要用于逻辑相关操作(循环、判断)
-
传值的两种方式
传值方式1:指名道姓的传 适用于数据量较少的情况 节省资源return render(request, 'ab_temp.html', {'name':name})
传值方式2:打包传值 适用于数据量较多的情况(偷懒) 浪费资源
'''locals() 将当前名称空间中所有的名字全部传递给html页面''' return render(request, 'ab_temp.html', locals())
-
传值的范围
- 基本数据类型都可以
- 函数名
模板语法会自动加括号执行并将函数的返回值展示到页面上
不支持传参(模板语法会自动忽略有参函数) - 文件名
直接显示文件IO对象 - 类名
自动加括号实例化成对象 - 对象名
直接显示对象的地址 并且具备调用属性和方法的能力
注意:
django模板语法针对容器类型的取值 只有一种方式>>>:句点符
既可以点key也可以点索引 django内部自动识别
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--调用字符串对象的upper方法,注意不要加括号-->
<p>{{ msg.upper }}</p>
<!--取字典中k1对应的值-->
<p>{{ dic.k1 }}</p>
<!--取对象的name属性-->
<p>{{ obj.name }}</p>
<!--取列表的第2个元素,然后变成大写-->
<p>{{ li.1.upper }}</p>
<!--取列表的第3个元素,并取该元素的age属性-->
<p>{{ li.2.age }}</p>
</body>
</html>