zoukankan      html  css  js  c++  java
  • Django学习之路04

    视图层

    小白必会三板斧

    1. HttpResponse
    2. render
    3. redirect

    django视图函数必须要给返回一个HttpResponse对象(render和redirect内部返回的也是一个HttpResponse对象

    前后端分离

    在前后端分离的情况下,为了保证数据的交互,我们选择JSON格式来传输数据。

    前端一个人干(前端转成自定义对象)

    JSON.stringify() ——————> json.dumps()
    
    
    JSON.parse()  ———————> json.loads()

    后端另一个干(python后端用字典)
    只要涉及到数据交互,一般情况下都是用的json格式
    后端只负责产生接口,前端调用该接口能拿到一个大字典
    后端只需要写一个接口文档 里面描述字典的详细信息以及参数的传递

    JsonReponse

    from django.http import JsonResponse
    def index(request):
        data = {'name':'jason好帅哦 我好喜欢','password':123}
        l = [1,2,3,4,5,6,7,8]
           # res = json.dumps(data,ensure_ascii=False)
           # return HttpResponse(res)
           # return JsonResponse(data,json_dumps_params={'ensure_ascii':False})
               # ensure_ascii的作用是可以让中文不被转译成ascii码
            return JsonResponse(l,safe=False)  # 如果返回的不是字典 只需要修改safe参数为false即可

    关于上传文件

    form表单上传文件需要注意的事项
      1.enctype需要由默认的urlencoded变成formdata
      2.method需要由默认的get变成post
    (目前还需要考虑的是 提交post请求需要将配置文件中的csrf中间件注释)

    如果form表单上传文件 后端需要在request.FILES获取文件数据 而不再是POST里面

     

    request

    request.method  # 获得请求的类型
    
    request.GET  # 获得get请求的数据,一个大字典
    
    request.POST  # 获得post请求的数据,一个大字典
    
    request.FILES 
    # 一个类似于字典的对象,包含所有的上传文件信息。
    # FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。
    #注意,FILES 只有在请求的方法为POST 且提交的<form> 带enctype="multipart/form-data" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象。
    
    request.body  # 原生的二进制数据
    
    request.path   # 只回去url后缀 不获取?后面的参数
    
    request.get_full_path()   # 后缀和参数全部获取

    render的内部原理

    from django.template import Template,Context
    def index(request):
        temp = Template('<h1>{{ user }}</h1>')  #  先把所有的内容读成字符串
        con = Context({"user":{"name":'jason',"password":'123'}})  # 然后把字典中的数据传进去
        res = temp.render(con)
        print(res)
        return HttpResponse(res)
    #最后把数据再传给前端

    FBV与CBV

    视图函数并不一定都是函数,也可以是类

    FBV(基于函数的视图) 面向函数式编程

    CBV(基于类的视图)     面向对象式编程

    之前的学习中都用的是FBV,所以不再做叙述,下面重点说一下CBV

    CBV的写法

    #urls中
    urlpatterns = [
         url(r'^index/$', MyView.as_view()),
    ]
    
    
    #viws中
    from django.http import HttpResponse
    from django.views import View
       
    class MyView(View):
     
          def get(self,request):
            print("from MyLogin get方法")
            return render(request,'login.html')
        
    
          def post(self,request):
            return HttpResponse("from MyLogin post方法")

    内部原理研究

    #从url入手
    url(r'^login/',views.MyLogin.as_view())  #由于函数名加括号执行优先级最高,所以这一句话一写完会立刻执行as_view()方法
    
    #点进as_view()的源代码查看                        
    @classonlymethod
    def as_view(cls, **initkwargs):  # cls就是我们自己的写的类 MyLogin
        def view(request, *args, **kwargs):
              self = cls(**initkwargs)  # 实例化产生MyLogin的对象,self = MyLogin(**ininkwargs)           
              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)  # dispatch返回什么 浏览器就会收到什么
             # 对象在查找属性或者方法的时候 你一定要默念 先从对象自己这里找  然后从产生对象的类里面找  最后类的父类依次往后
        return view
    
    #通过源码发现url匹配关系可以变形成
    url(r'^login/',views.view)  # FBV和CBV在路由匹配上是一致的 都是url后面跟函数的内存地址
    
    #当浏览器中输入login 会立刻触发view函数的运行
    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        # 我们先以GET为例
        if request.method.lower() in self.http_method_names:  # 判断当前请求方法是否在默认的八个方法内
            # 反射获取我们自己写的类产生的对象的属性或者方法
            # 以GET为例  handler = getattr(self,'get','取不到报错的信息')
            # handler = get(request)
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)  # 直接调用我们自己的写类里面的get方法
    # 源码中先通过判断请求方式是否符合默认的八个请求方法 然后通过反射获取到自定义类中的对应的方法执行

    总结:as_view()相当于调用了view函数,调用view函数之后,先拿到一个你定义的类实例化出的对象,然后通过反射中的hasattr方法进行判断,并给对象新增属性,然后将对象给调用dispatch,然后再进行判断看看是不是在默认的八个方法中,没有就报错,如果有就再通过反射中的getattr来获得你自己写的方法,如果自己没有,也返回一个报错,最后return就直接调用我们自己写的方法。

    django settings源码浅探

    前提:
    1.django除了暴露给用户一个settings.py配置文件之外 自己内部还有一个全局的配置文件
    2.我们在使用配置文件的时候 可以直接直接导入暴露给用户的settings.py也可以使用django全局的配置文件 并且后者居多

    from django.conf import settings

    3.django的启动入口是manage.py

    import os
    import sys
    
    if __name__ == "__main__":
        # django在启动的时候 就会往全局的大字典中设置一个键值对  值是暴露给用户的配置文件的路径字符串
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day54.settings")
    
    class Settings(object):
        def __init__(self, settings_module):  # settings_module = 'day54.settings'
            # update this dict from global settings (but only for ALL_CAPS settings)
            for setting in dir(global_settings):  # django全局配置文件
                # dir获取django全局配置文件中所有的变量名
                if setting.isupper():  # 判断文件中的变量名是否是大写 如果是大写才会执行/生效
                    setattr(self, setting, getattr(global_settings, setting))  # 给settings对象设置键值对
                    # 给settings对象设置键值对  settings[配置文件中大写的变量名] = 配置文件中大写的变量名所对应的值
    
            # store the settings module in case someone later cares
            self.SETTINGS_MODULE = settings_module  # 'day54.settings'
    
            mod = importlib.import_module(self.SETTINGS_MODULE)  # mod = 模块settings(暴露给用户的配置文件)
            for setting in dir(mod):  # for循环获取暴露给用户的配置文件中所有的变量名
                if setting.isupper():  # 判断变量名是否是大写
                    setting_value = getattr(mod, setting)  # 获取大写的变量名所对应的值
                    setattr(self, setting, setting_value)  # 给settings对象设置键值对
                    """
                    d = {}
                    d['username'] = 'jason'
                    d['username'] = 'egon'
                    用户如果配置了就用用户的
                    用户如果没有配置就用系统默认的
                    其实本质就是利用字典的键存在就是替换的原理 实现了用户配置就用用户的用户没配置就用默认的
                    """
        
    class LazySettings(LazyObject):
            def _setup(self, name=None):
                # os.environ你可以把它看成是一个全局的大字典
                settings_module = os.environ.get(ENVIRONMENT_VARIABLE)  # 从大字典中取值键为DJANGO_SETTINGS_MODULE所对应的值:day54.settings
                # settings_module = 'day54.settings'
                self._wrapped = Settings(settings_module)  # Settings('day54.settings')
    settings = LazySettings()  # 单例模式
  • 相关阅读:
    CSS中float与A标签的疑问
    常用的Css命名方式
    div css 盒子模型
    HTML初级教程 表单form
    Redis学习记录(二)
    Redis学习记录(一)
    Java源码——HashMap的源码分析及原理学习记录
    java编程基础——从上往下打印二叉树
    java编程基础——栈压入和弹出序列
    java基础编程——获取栈中的最小元素
  • 原文地址:https://www.cnblogs.com/wangnanfei/p/11536004.html
Copyright © 2011-2022 走看看