7

Django视图层/FBV与CBV/jsonResponse对象/form表单上传文件/request对象获取文件 - Py...

 1 year ago
source link: https://www.cnblogs.com/moongodnnn/p/16980680.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

每创建一个虚拟环境类似于重新下载了一个纯净的python解释器

但虚拟环境不要创建太多,会占用电脑硬盘空间

python
项目1需要使用:django1.11 								 python38
项目2需要使用:django2.22 pymysql requests			      python38
项目3需要使用:django3.22 request_html flask urllib3		 python38

实际开发项目中我们只会给项目配备所需的环境,不需要的一概不配!!!

虚拟环境:能够针对相同版本的解释器创建多个分身 每个分身可以有自己独立的环境


在CMD终端创建虚拟环境:  python -m venv pyvenv38

视图层views

HttpResponse

用来处理请求的视图函数都必须返回HttpResponse对象

返回字符串类型

render

返回html页面 还可以给页面传值

redirect

jsonResponse对象

前后端数据交互需要用到json格式

python
def ab_json(request):
  user_dict = {'username':'月神','age':18}
  json_str = json.dumps(user_dict,ensure_ascii=False)
  return HttpResponse(json_str)


from django.http import JsonResponse
   return JsonResponse(user_dict)

使用jsonresponse方法可以直接发送数据,但是遇到文字会乱码

如何解决乱码
   return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':false})

直接在json_dumps_params这个方法里面传入 'ensure_ascii':false 就可以了



如何传送列表

l1 = [11,22,33,44]

return JsonResponse(l1,safe=False)

其实通过看源码和报错都可以推导出来这些问题

form如何上传文件/request对象获取文件

form表单上传文件

python
<form action='' method='post' enctype ='multipart/form-data'>
首先必须是post请求 然后设置enctype ='multipart/form-data'属性


< input type='file' name='file'>
前端获取文件,




后端获取文件

file_obj = request.FILES.get('file)
可以获得前端发来的文件对象
                      
如何存储文件
with open(file_obj.name,'wb') as f:
   for line in file_obj:
       f.write(line)
 
这样就保存好了前端发来的文件

request对象方法

python
request.method 
获取请求方式
request.POST
获取post请求提交的普通键值对数据 不包括文件
request.GET
获取get请求
request.FILES
获取文件

request.path
获取用户访问的路由

request.path_info

request.get_full_path()
获取用户访问的路由及问号后面携带的参数

FBV与CBV

FBV:基于函数的视图;

CBV:基于类的视图;

python
使用函数实现功能

def index(request):
  return render(request,'login.html')

  
使用面向对象思想通过类实现功能  
from django.views import View
#需要导入django.views import View模块
class Mylogin(View):
  def get(self,request):
    return render(request,'login.html')
  def post(self,request): 
    return render(request,'login.html')
  
  
  使用CBV路由匹配时
  urlpatterns = [
    path('login/', views.Mylogin.as_view()),
]
  #访问路由 直接访问这个类 然后执行类里面的方法

'''
FBV和CBV各有千秋

CBV特点能够直接根据请求方式不同匹配到对应的方法执行

CBV源码解析

python
from django.views import View

class MyLogin(View):
  def get(self,request):
    return render(request,'login.html')
  
  def post(self,request):
    return render(request,'login.html')
  
使用 CBV 时,需要 通过 视图类. as_view() 才能进行路由匹配,那么直接观察这个as_view()的源码

   urlpatterns = [
    path('login/', views.Mylogin.as_view()),
]    # as_view() 是一个绑定给 类的方法
     # 由于加了()相当于立即执行了类里面的这个函数方法。      
 
    @classonlymethod
    def as_view(cls,**initkwargs):
      def view():
        return view
观察返回值能够发现,返回的是内部的一个view函数
      
通过这里得出结论path('login/', views.Mylogin.as_view()),
相当于        path('login/', views.view), 
因为Mylogin.as_view()执行完返回值是view 

所以 CBV 路由匹配的本质,就是 FBV

接下来,我们分析一下,当路由匹配成功时,需要执行的这个view函数的源码

python
@classonlymethod
def as_view(cls, **initkwargs):
			... ... # 源码省略

    def view(request, *args, **kwargs):
        self = cls(**initkwargs)  ----->  '实例化生成一个对象'
        if hasattr(self, 'get') and not hasattr(self, 'head'): 
            self.head = self.get ----> '给生成的对象添加 head 属性'
        self.request = request  --> '给生成的对象添加 request 属性'
        self.args = args  ----> '给生成的对象添加 args 属性'
        self.kwargs = kwargs  ----> '给生成的对象添加 args 属性'
        return self.dispatch(request, *args, **kwargs) 
			... ... # 源码省略
    return view

最后结果就是 return self.dispatch(request, \*args, \**kwargs)

对象 和 产生对象的类中都没有 dispatch函数,所有需要到 父类view中去找

python
  http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
  
  def dispatch(self, request, *args, **kwargs):

        if request.method.lower() in self.http_method_names:
        # 判断当前请求的方法是否符合 8 个 默认的请求方法
            handler = getattr(self, request.method.lower(), 
            # getattr反射
            # sele是自己写的类产生的对象 查找get方法,自己写的对象没有 就找对象的父类 也就是我们自己写的类 然后有 get 执行我们类里面的get方法
            # handler = 等于我们自己写的get方法
                      
 self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)
            # 触发我们函数内部的get方法
      
 

我们就剖析出,我们的as_view()函数做了这么几件事:

封装了一个函数,作为对应路由的函数
封装的函数中,让我们的自定义类产生了一个对象,并让对象执行方法dispatch返回结果
dispatch辨认了请求方式,根据请求方式返回了某个类体函数的结果(HttpResponse对象)

__EOF__


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK