三、Django之视图层

Django之视图层

1、三板斧

"""
HttpResponse
	返回字符串类型
render
	返回html页面,并且在返回给浏览器之前还可以给html文件传值
redirect
	重定向
	
如果我们一个视图函数没有返回值的话,会直接报如下错误
The view app01.views.index didn't return an HttpResponse object. It returned None instead.
点击三板斧的源码,我们会发现最后都是HttpResponse对象,所以视图函数必须要返回HTTPResponse对象
"""

# render简单内部原理
from django.template import Template,Context
res = Template('<h1>{{ user }}</h1>')
con = Context({ 'user':{'username':'jason','password':123} })
ret = res.render(con)
return HttpResponse(ret)

2、JsonResponse对象

"""
json格式的数据可以跨语言交互,前端后端数据加护需要使用使用json作为过渡

前端序列化					后端序列化(python)
JSON.stringify()				json.dumps()
JSON.parse()					json.loads()
"""
  1. 原始方法实现数据序列化

    # 在视图函数中,我们要把一个字符串的数据转化成json数据,然后传递给前端
    import json
    from django.http import JsonResponse
    
    def ab_json(request):
        user_dict = {'username':'jason','password':123,'hobby':'read'}
        # json模块方式,ensure_ascii=False在dumps里默认是True,默认不显示中文字符
        json_str = json.dumps(user_dict,ensure_ascii=False)
        return HttpResponse(json_str) 
    
  2. 使用JsonResponse实现数据序列化

    import json
    from django.http import JsonResponse
    
    def ab_json(request):
        user_dict={'username':'jason','password':123,'hobby':'read'}
        return JsonResponse(user_dict,json_dumps_parse={'ensure_ascii':False}) # 读源码可以知道 本质上还是用json模块实现的,只是添加了一些其他的功能
    
  3. 注意:JsonResponse默认只能序列化字典,序列化其他需要加safe参数

    # 默认只能序列化字典,序列化其他需要加safe参数
    import json
    from django.http import JsonResponse
    
    def ab_json(request):
        l = [111,222,333,444,555]
        return JsonResponse(l,safe=False)
    

3、from表单上传文件及后端获取

  1. 注意:from表单上传文件类型的数据

    • method必须指定成post
    • enctype必须换成multipart/form-data
  2. 具体实现

    def ab_fire(request):
    	if request.method == 'POST':
            # print(request.POST) 只能获取普通的简单键值对 文件不行
            print(request.FIRE) # 获取列表嵌对象的文件数据对象
            # <MultiValueDict: {'file': [<InMemoryUploadedFile: u=1288812541,1979816195&fm=26&gp=0.jpg (image/jpeg)>]}>
            fire_obj = request.FIRE.get('fire') # 获取具体的文件对象
            with open(fire_obj.name,'wb') as f:
                for line in fire_obj.chunks():   # 官方推荐加上chunks方法 其他加不加都一样
                    f.write(line)
    	return render(request,'from.html')
    

4、FBV与CBV

  1. FBV(function base views)

    # 路由层
    	url(r'^login/',views.login)
    # 视图层
    	def login(request):
            user_id = request.GET.get('user_id')
          	user_obj = 	models.User.object.filter(id=user_id).first()
            if request.method == 'POST':
                user_name = request.POST.get('username')
                pass_word = request.POST.get('password')
                if user_obj:
                    if user_obj.password == pass_word:
                        return HttpResponse('登录成功')
                else:
                    return HttpResponse('登录失败')
    		return redirect('/register/')
    
  2. CBV(class base views)

    # 路由层
       	url(r'^login/',views.Login.as_view())
    # 视图层
    	from django.views import View
    	class Login(View):
        	def get(self,request):
            	return render(request,'form.html')
        	def post(self,request):
            	return HttpResponse('post方法')
    # CBV可以根据不同的请求直接匹配到不同的方法去执行
    

5、CBV源码

# 突破口在urls.py
url(r'^login/',views.MyLogin.as_view())

"""
函数名/方法名加括号执行优先级最高
猜测
	as_view()
		要么是被staticmethod修饰的静态方法
		要么是被classmethod修饰的类方法  ------ 正确
		
	@classonlymethod
	def as_view(cls,**initkwargs):
		pass
"""

# 具体源码解析

# 1.as_view里面的源码
@classonlymethod
def as_view(cls,**initkwargs):
	# cls就是我们自己写的类 MyLogin
    def view(request,*args,**kwargs):
        self = cls(**initkwargs) # cls就是我们自己写的类
        # self = MyLogin(**initkwargs) 产生一个我们自己写的类的对象
        return self.dispatch(request,*args,**kwargs)
   		"""
   		以后我们会经常需要看源码 但是在看python源码的时候 一定要时刻提醒自己面向对象属性方法查询顺序
   			先从对象自己这里找
   			再去产生对象的类里面找
   			之后再去父类里面找
   			...
   		总结:看源码只要看到了self点一个东西 一定要问你自己当前这个self到底是谁
   		"""
    view.view_class = cls
    view.view_initkwargs = initkwargs
    update_wrapper(view, cls, updated=())
    update_wrapper(view, cls.dispatch, assigned=())
	return view  
# 2.dspatch里的源码 CBV的精髓
def dispatch(self,request,*args,**kwargs):
    # 获取当前请求的小写格式,然后对比当前请求方式是否合法
    # get请求为例
    # post请求为例
    if request.method.lower() in self.http_method_names:
        handler = getattr(self,request.method.lower(),self.http_method_not__allowed)
        """
        反射:通过字符串来操作对象的属性或者类方法
        	handler = getattr(自己写的类产生的对象,'get',当前找不到get属性或者方法的时候就会使用第三个参数)
        	handler = 我们自己写的类里面的get方法
        """
    else:
        handler = self.http_method_not_allowed
    return handler(request,*args,**kwargs)
	"""自动调用get方法"""

posted @ 2021-01-26 15:32  今天捡到一百块钱  阅读(66)  评论(0编辑  收藏  举报