Python攻城师的成长————Django框架(视图层)

今日学习目标

  • 学习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里面的url

    from 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. 传值的两种方式
    传值方式1:指名道姓的传 适用于数据量较少的情况 节省资源

    return render(request, 'ab_temp.html', {'name':name})
    

    传值方式2:打包传值 适用于数据量较多的情况(偷懒) 浪费资源

    '''locals() 将当前名称空间中所有的名字全部传递给html页面'''
    return render(request, 'ab_temp.html', locals())
    
  2. 传值的范围

    • 基本数据类型都可以
    • 函数名
      模板语法会自动加括号执行并将函数的返回值展示到页面上
      不支持传参(模板语法会自动忽略有参函数)
    • 文件名
      直接显示文件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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值