学习内容总结
今日学习内容总结
虚拟环境
为什么使用本地虚拟环境
1. 在时间开发过程中,我们会给不同的项目配备不同的环境
2. 项目用到什么就装什么,用不到的一概不装
3. 不同的项目解释器环境都不一样
创建虚拟环境
1.打开pycharm项目,查看初始的 package : 打开Pycharm----->File----->settings----->Project:[项目名]----->Python Interpreter
2.进入 Project下 Project-Interpreter,点击show all或者添加新的虚拟环境。
下次创建新项目可以直接选择已经创建好的虚拟环境。
Django版本区别
路由层
1. django 1.x路由层使用url方法
2. django 2.x和3.x版本使用path方法
url方法与path方法的区别
url() 第一个参数支持正则
path()第一个参数是不支持正则的,可以使用 re_path替代url()
urlpatterns = [
# 用法完全一致
url(r'^app01/', include(('app01.urls','app01'))),
re_path(r'^app02/', include(('app02.urls','app02'))),
]
path方法提供了转换器功能,内部支持五种转换器:
1. str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
2. int,匹配正整数,包含0。
3. slug,匹配字母、数字以及横杠、下划线组成的字符串。
4. uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
5. path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
视图函数返回值
视图层是实现业务逻辑的关键层,视图函数必须要返回一个 HttpResponse 对象, 如果未返回, 会出现如下错误 :
提示你没有返回一个 HttpResponse 对象, 而是返回了一个 None
必须返回该对象的原因,我们 Ctrl + 鼠标点击分别查看三者的源码可得到解释:
# HttpResponse
# 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.
"""
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status) # 返回一个HttpResponse对象
# redirect
内部继承了 HttpResponse 类
JsonResponse 对象
Json格式的作用
1. JSON的全称是"JavaScript Object Notation", 意思是JavaScript对象表示法
2. 前后端的交互一般使用 JSON 实现数据的跨域传输
实现给前端返回 json 格式数据
1.直接自己序列化
import json
def test(resquest):
user_info = {"name":"shawn","age":23,"sex":"male","hobby":"吃饭"}
data = json.dumps(user_info,ensure_ascii=False)
return HttpResponse(data)
2.使用JsonResponse对象
from django.http import JsonResponse
def test2(request):
user_info = {"name":"shawn","age":23,"sex":"male","hobby":"吃饭"}
return JsonResponse(user_info)
JsonResponse 对象没有 ensure_ascii 参数是如何保证中文正常显示的,可以查看JsonResponse 源码
JsonResponse 返回的也是 HttpResponse 对象。并且封装了json模块,对json序列化的数据类型做了扩充。
from表单上传文件
注意事项
1. method 必须指定 post 提交
2. enctype 须修改为 multipart/form-data,默认是application/x-www-form-urlencoded。
3. 后端需要使用request.FILES获取
代码操作:
# html
<body>
<div class="container">
<div class="col-md-8 col-md-offset-2">
<form action="" method="post" enctype="multipart/form-data">
<input type="file" class="form-control" name="myfile">
<input type="submit" class="btn btn-warning btn-block" value="提交">
</form>
</div>
</div>
</body>
# views
def form_test(request):
if request.method == "POST":
# 从文件对象字典中获取名为"myfile"的文件对象
file_obj = request.FILES.get('myfile')
file_name = file_obj.name
# 保存方式一:
with open(f'./{file_name}',"wb")as f:
for line in file_obj:
f.write(line)
# 保存方式二:(官方推荐)
with open(f'./{file_name}',"wb")as f:
for line in file_obj.chunks():
f.write(line)
return render(request,'test.html')
# 打印个别结果看看
print(request.FILES)
'''
<MultiValueDict: {'myfile': [<InMemoryUploadedFile: README.md (application/octet-stream)>]}>
'''
print(file_obj,type(file_obj))
'''
README.md <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
'''
print(file_obj.name)
'''
README.md
'''
# 官方推荐写法 chunks() 的源码
def chunks(self, chunk_size=None):
self.file.seek(0)
yield self.read()
# 一个迭代器
request其他方法
1. request.method 获取大写的请求类型
2. request.POST 获取POST携带的数据
3. request.GET 获取url?后面的数据
4. request.FILES 获取文件
5. request.body 存放的是接收过来的最原始的二进制数据
request.POST、request.GET、request.FILES这些获取数据的方法其实都从body中获取数据并解析存放
6. request.path 获取路径
7. request.path_info 获取路径
8. request.get_full_path() 获取路径并且还可以获取到路径后面携带的参数
FBV与CBV
FBV : ( function-based-view ) 基于函数的视图
url(r'^index/',函数名)
我们之前在视图层写的都是基于函数的视图。
CBV : ( class-based-view ) 基于类的视图
# views.py 文件
from django.views import View
def test_func(request):
return render(request,'test.html')
class MyView(View):
def get(self,request):
return HttpResponse('触发了get方法:')
def post(self,request):
return HttpResponse('触发了post方法:')
# urls.py 文件
from django.urls import path,re_path,include
from app02 import views
urlpatterns = [
re_path(r'^test/',views.test_func),
re_path(r'^func',views.MyView.as_view())
]
# 模板文件 test.html
<div>
<form action="/func/" method="post" enctype="multipart/form-data">
<input type="file">
<input type="submit">
</form>
</div>
如果请求方式是GET,则会自动执行类里面的get方法。如果请求方式是POST,则会自动执行类里面的post方法。
CBV源码剖析
切入点
re_path(r'^func',views.MyView.as_view()) # as_view() 是什么东西
我们 Ctrl + 点击查看其源码
发现它是一个类方法, 查看其整体结构(只看框起来的即可, 其他的不用管), 该方法内部有一个 view 方法, 并且返回值是 view 的内存地址, 类似于闭包函数:
于是我们得到一个初步结果:
re_path(r'^func',views.MyView.as_view()) # 等同于下面
re_path(r'^func',views.view) # 看着是不是与普通的路由没有什么区别了 : 通过匹配触发视图函数的运行
那么 view 是一个什么样的函数呢? 现在突破口变成了 view 方法了。我们再看其源码(只看框起来的即可,其他的不用管) :
"self = cls(**initkwargs)"
# cls是什么? 记得上面的类方法吗? 类调用时传入类本身
# 我们是通过MyView来调用as_view的, 那么cls也就是MyView
# 类加括号实例化得到对象self, 这个self就是我们自己的类产生的对象 : self=MyView(**initkwargs),我们不用去管里面的参数
# 接下来看看view的返回值 : self.dispatch(request, *args, **kwargs)
# 也就是去MyView类实例出的对象里面去找dispatch方法并执行,很显然self对象中没有该方法,于是去类中去找,也没有
# 最后到父类View中去找,发现就在as_view类方法的下面找到了
我们在看它下面的逻辑代码:
逻辑很简单,使用了反射的知识点
# 先是拿到当前请求方式的大写字符转成小写, 然后判断在不在后面的 self.http_method_names 里面
# Ctrl+点击 看看这是个什么东西 :
'http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']'
# 发现是8种常用的请求方式列表, 接着返回dispatch源码查看,为了方便我们假设现在的是get请求方式
# 判断get请求在请求列表里面,于是执行紧跟其下的代码...我们先看看getattr()得到的是什么结果
# 判断我们的self是否有名叫get的属性或方法,如果有则返回该属性的值或方法的内存地址,否则返回 self.http_method_not_allowed, 这是个啥,我们 Ctrl+点击 也来看看:
模板语法传值
django提供的模板语法只有两个符号:
{{}}:主要用于变量相关操作(引用)
{%%}:主要用于逻辑相关操作(循环、判断)
传值的两种方式
传值方式1:名字传值,适用于数据量较少的情况,节省资源。
return render(request, 'ab_temp.html', {'name':name})
传值方式2:打包传值,适用于数据量较多的情况。
return render(request, 'ab_temp.html', locals())
# locals() 将当前名称空间中所有的名字全部传递给html页面
传值的范围
基本数据类型都可以。
函数名:会自动将函数名调用之后的返回值传值,但是不支持函数参数
文件名:直接显示文件IO对象
类名:自动加括号实例化对象
对象名:显示对象的地址,并具备调用属性和方法的能力
取值:.句点符,.key(django内部自动识别)