【1023 | Day 51】Django进阶(render原理/json相关知识/form表单/FBV和CBV/settings源码分析...)

1. render原理

2.json相关知识

2.1 给前端返回json格式字符串

  • 为什么要给前端返回json格式字符串?
》》前后端分离
》》基于json格式传输数据
》》后端就专门写接口
》》前端调用接口
》》拿到json格式的字符串
》》然后前端利用序列化反序列化
》》转换成前端对应的数据类型
  • 前端如何序列化反序列化?

    #前端
    JSON.stringify >>> json.dumps
    JSON.parse >>> json.loads
    
    #后端
    json.dumps >>> JSON.stringify 
    json.loads >>> JSON.parse
    
    #js常用数据类型
    数值、字符、数组[]、自定义对象、undefined、null、布尔值 true/false(小写)、symbol
    

2.2 形似json

2.3 中文乱码

解决路径:

  • 方法一:

    • 加一个ensure_ascii

  • 方法二:

    • 给源码里的json_dumps_parms默认的空字典加一个键值对

2.4 json序列化时间类型

注意:default就是默认不支持datetime序列化

解决路径:json支持序列化时间类型

  • 方法一:
    • dumps里的cls默认只能做那张表的功能
    • 我们重新定义一个类
    • 重写default方法
    • 如果o不是json默认能够序列化的
    • 重写其他方法只需要将datetime改成你要的方法

2.5 JsonResponse

JsonResponse 默认只支持字典

注意:如果你想序列化其他类型(json能够支持的类型),只需要加一个safe=False。

3. form表单上传文件

问题:

  • CRSF错误 —— 关闭MIDDLEWARE的django.middleware.csrf.CsrfViewMiddleware
  • 只能拿到文件名

分析:

  • 这次文件名字拿不到了,因为针对文件数据不会放进request.POST里面
  • 而是放在request.FILES里面

解决路径:

  • 在form表单里加入enctype="multipar/form-data"

  • 插入<input type="file" name="myfile">

  • 获取文件对象

    注意:要区分POST/GET

  • 获取

  • 保存

注意!!!这里有两点需要注意!!!

第一,我不是楚雨荨!

第二,我不叫喂!

fine,开个玩笑,哈哈哈

  • 第一,提交方式必须是post,因为get能携带的参数很小。
  • 第二,form标签的enctype属性由默认的urlencoded变成formdata

敲黑板敲黑板!

4. FBV与CBV(即CBV源码分析)

4.1 FBV(Function Based View) 基于函数的视图

4.2 CBV(Class Based View) 基于类的视图

  • 之前urls一一对应views功能,现在怎么写类?

    • url(r'^login/', views.MyReg.as_view())
      

    • 通过分析as_view()的源码,发现类.方法相当于之前FBV的文件名.函数,相当于一个闭包函数

  • 为什么前端传来GET就会执行GET,传来POST就会执行POST?

    • CBV路由
    
        url(r'^reg/',views.MyReg.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
        
        # views.py 
        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方法")
    
    • 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)  # 在调用获取到的方法
    

5. django settings源码分析及实际应用

先思考我们之前的一个知识点:当我们输入login、register等,网站会自动帮我们添上/

我们为了解决这个问题,用到了settins.py里面的一个语法:APPEND_SLASH:False

当我们将这条语法换成小写的:append_slash:flash

!!!

问题来了

此时运行,该命令是失效的,所以系统依旧会自动帮我们加上斜杠。

现在就需要分析settings.py的源码了。

5.1 django的配置文件

  • 一个是暴露给用户可以自定义配置

  • 一个是默认的全局配置文件

    用户指定了就用用户的
    用户没有指定就用默认的

from django.conf import settings
settings = LazySettings()
class LazySettings(LazyObject):
        
        def _setup(self, name=None):
     
            # os.environ你可以把它看成是一个全局的大字典
            settings_module = os.environ.get(ENVIRONMENT_VARIABLE)  # 从大字典中取值
            
            # settings_module = 'day59.settings'
            self._wrapped = Settings(settings_module)  # Settings('day59.settings')
    
class Settings(object):
    def __init__(self, settings_module):  # settings_module = 'day59.settings'
        
        for setting in dir(global_settings):  # 循环获取global_settings文件中所有的名字
            
            if setting.isupper():  # 在判断名字是否是大写
                
                # 如果是大写 利用反射 获取到大写的名字所对应的值  不停地添加到对象中
                setattr(self, setting, getattr(global_settings, setting))
                
                # store the settings module in case someone later cares
                self.SETTINGS_MODULE = settings_module
                mod = importlib.import_module(self.SETTINGS_MODULE)  # 'day59.settings'
                
                # from day59 import settings
                # mod 指代的就是暴露给用户的配置文件模块名
           
                for setting in dir(mod):  # 循环获取暴露给用户配置文件中所有的名字
                    if setting.isupper():  # 判断是否是大写
                        setting_value = getattr(mod, setting)  # 如果是大写 获取大写的变量名所对应的值
                        setattr(self, setting, setting_value)  # 不停的给对象设置值

整理好博客,再温习一遍,洗洗睡吧!

posted @ 2019-10-23 17:58  fxyadela  阅读(272)  评论(0编辑  收藏  举报