首页 > 其他分享 >必备知识点 视图

必备知识点 视图

时间:2024-03-28 20:01:03浏览次数:22  
标签:知识点 return 必备 request 视图 method login self def

4.视图

1.视图参数

# urls.py
urlpatterns = [
    path('login/', account.login, name="login"),
    path('auth/', order.auth, name='auth'),
]
# views.py
from django.shortcuts import HttpResponse


def login(request):
    return HttpResponse("login")

Request 是什么?

requests是一个对象,存放了浏览器给咱们发过来的所有内容,所以含有:
- 请求相关所有的数据: 当前访问的url、请求方式、...
- django额外添加的数据

1.1 request 方法

1.1.1 request.path_info
  • 只能获取到路由地址,无法获取到参数
  • 它保留了URL路径中的任何编码、特殊字符或斜杠等信息。
http://localhost:8000/api/login/

def login(request):
    print(request.path_info) # /api/login/
    return HttpResponse("Hello, world. You're at the")
1.1.2 request.path
  • 只能获取到路由地址,无法获取到参数
  • 它包含在域名之后,在任何查询参数之前
http://localhost:8000/api/login/

def login(request):
    print(request.path) # /api/login/
    return HttpResponse("Hello, world. You're at the")
1.1.3 request.GET
  • 该属性包含了请求中通过GET方法发送的所有参数。
  • 这些参数通常会附加在URL之后,以问号分隔。
  • 您可以使用参数的名字作为键来访问单个参数,例如request.GET['page']也可以直接.get()获取
http://localhost:8000/api/login/?xxx=serein&age=999

def login(request):
    print(request.GET) # <QueryDict: {'xxx': ['serein'], 'age': ['999']}>
    print(request.GET.get('xxx')) # serein
    print(request.GET['age']) # 999
    return HttpResponse("Hello, world. You're at the")
1.1.4 request.POST
  • request.POST:该属性是一个类似字典的对象,包含了请求中通过POST方法发送的所有参数。
  • 这些参数通常是通过HTML表单发送的。
  • 您可以使用参数的名字作为键来访问单个参数,例如request.POST['username'],也可以直接.get()获取
1.1.5 request.method
  • 返回客户端用于发起请求的HTTP方法,比如'GET','POST'等
http://localhost:8000/api/login/?xxx=serein&age=999

def login(request):
    print(request.method) # GET
    return HttpResponse("Hello, world. You're at the")
1.1.6 request.body
  • 获取POST请求的请求体
  • 获取到的数据是原始格式,数据格式什么样根据content-type决定
def login(request):
    print(request.body) # GET
    return HttpResponse("Hello, world. You're at the")
# b'{"code":"083Sjmll2yla694F3bll2DguCM2SjmlG","unionId":"oP6QCsyT_9bk1dfSaVf0GEV5Y-yE"}'  b'v1=123&v2=456'


# 请求体+请求头       数据格式 b'v1=123&v2=456'  content-type格式:content-type:application/x-www-form-urlencoded
		# 可以这么取值
		print(request.POST)
    print(request.POST.get("v1"))
    print(request.POST.get("v2"))
1.1.7 request.FILES
  • request.FILES:该属性是一个类似字典的对象,包含了请求中通过文件上传组件发送的所有文件。
  • 当表单中包含文件上传字段时,通过request.FILES可以访问上传的文件。
  • 您可以使用文件的名字作为键来访问单个文件,例如request.FILES['file'],也可以.get()获取
  • content-type格式, multipart/form-data
file_obj = request.FILES.get("avatar")
        print(file_obj, type(file_obj))
        # 165917-16953731571c11.jpg <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>

        # 获取文件名
        file_name = file_obj.name
        print(file_name, type(file_name))
1.1.8 request.get_full_path()
  • 即能获取到路由地址又能获取到完整的路由地址后面的参数
  • request.get_full_path():该方法返回请求URL的完整路径,包括路径部分和任何查询参数。
  • 当您需要将完整URL作为字符串使用时,这个方法非常有用。
def login(request):
    print(request.get_full_path())  # 获取到GET请求的完整路由地址和参数
    # /app01/login/?username=111&password=111
    return render(request, "login.html")
1.1.9 request.header
  • 获取请求的请求头
1.1.10 request.COOKIES
  • 请求头有个特殊的cookie,
  • 可以直接request.COOKIES获取
1.1.11 request.resolver_match
  • 获取requests中其他值

2. 返回json数据

  • 服务端返回json数据
  • JsonResponse模块
  • from django.http import JsonResponse
# 第一种方式:json模块序列化
def index(request):
    data = {"username": "serein", 'password': '1234'}
    # 先用json序列化
    data = json.dumps(data)
    # 三板斧对象
    response = HttpResponse(data)
    return response

# 第二种办法
from django.http import JsonResponse
def index(request):
        data = {"username": "serein", 'password': '1234'}
    response = JsonResponse(data)
    return response

3. FBV和CBV

3.1 FBV和CBV

  • funtion 函数和路由之间的映射关系
  • class 类和路由之间的映射关系

3.2 CBV格式

  • 视图层
# views.py
from django.shortcuts import render, HttpResponse
# 导入view
from django.views import View

# 重写类,继承view
class LoginView(View):
  	# get请求
    def get(self, request):
        pass
        return HttpResponse("111")
		# post请求
    def post(self, request):
        return HttpResponse("111")
  • 路由层
from django.urls import path
from apps.api.views import LoginView

urlpatterns = [
    path('login/', LoginView.as_view())

3.3 CBV源码剖析

class View:
	# http_method_names : 存放了我们常用的请求方式
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
	
    # 绑定给类的函数,绑定方法
    @classonlymethod
    def as_view(cls, **initkwargs):
        # **initkwargs : 可变长关键字参数
        for key in initkwargs:
            # print(f"key :>>>> {key}") # key :>>>> pattern_name
            # 可变长关键字参数中的每一个键值对
            # 我们自己写视图类中没有定义过 http_method_names ,只能从父类 View 里面找
            if key in cls.http_method_names:
                # 
                raise TypeError(
                    'The method name %s is not accepted as a keyword argument '
                    'to %s().' % (key, cls.__name__)
                )
            # hasattr : 获取到当前对象中的属性
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))
		
        # 上面都没有报错,走到了 view 函数里面
        def view(request, *args, **kwargs):
            # 获取到当前类的对象 这个 cls ---> Register
            self = cls(**initkwargs)
            # 获取到了一个 当前的get方法
            self.setup(request, *args, **kwargs)
            # 必须接受一个位置参数叫request
            if not hasattr(self, 'request'):
                raise AttributeError(
                    "%s instance has no 'request' attribute. Did you override "
                    "setup() and forget to call super()?" % cls.__name__
                )
            # 触发了 dispatch 方法 ---> 获取到了get函数的返回值 
            # render
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view

    def setup(self, request, *args, **kwargs):
        # self : 当前Register实例化出来的对象
        # 有GET方法 并且 没有 head属性
        if hasattr(self, 'get') and not hasattr(self, 'head'):
            # self.head 变成了我自己写的 GET 方法
            self.head = self.get
        self.request = request
        self.args = args
        self.kwargs = kwargs
	
    # 走到了dispatch方法
    def dispatch(self, request, *args, **kwargs):
		# request.method.lower() :当前请求方法转全小写 
        if request.method.lower() in self.http_method_names:
            # 获取到了当前对象中的get方法的函数内存地址
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        # get方法的函数内存地址调用
        return handler(request, *args, **kwargs)

    def http_method_not_allowed(self, request, *args, **kwargs):
        logger.warning(
            'Method Not Allowed (%s): %s', request.method, request.path,
            extra={'status_code': 405, 'request': request}
        )
        return HttpResponseNotAllowed(self._allowed_methods())

    def options(self, request, *args, **kwargs):
        """Handle responding to requests for the OPTIONS HTTP verb."""
        response = HttpResponse()
        response.headers['Allow'] = ', '.join(self._allowed_methods())
        response.headers['Content-Length'] = '0'
        return response

    def _allowed_methods(self):
        return [m.upper() for m in self.http_method_names if hasattr(self, m)]
  • 当我们启动Django项目时
  • 会自动触发路由中的方法,调用 as_view 方法并自执行
  • 在执行后我们查看 as_view 方法的源码 发现
    • 在依次给我们的对象赋值后,最终返回了一个自执行的 dispatch 方法
  • 于是我们又去查看了 dispatch 方法
    • 在 dispatch 内部 ,先是将请求方式转换并进行校验
    • 然后开始校验需要调用的方法的调用位置,校验成功并拿到需要执行的方法执行
  • 在自己写的类中如果有相关的方法,会首先调用我们重写的类方法,并返回执行结果
    • 如果自己的类里面没有该方法 会去自己的父类中调用 父类的方法
      • 如果父类 以及 基类 都找不到则报错,抛出异常

3.3 给CBV和FBV加装饰器

3.3.1 给FBV加装饰器
  • 只需要将自己定义的装饰器放在指定的视图函数上面用语法糖
def timer(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        print(f"总耗时 :>>>>> {time.time() - start_time} s ")
        return res

    return inner


@timer
def register(request):
    time.sleep(2)
    return HttpResponse("ok")
3.3.2 给CBV加装饰器
from django.utils.decorators import method_decorator


class Login(View):
    # 第一种方式
    # @timer
    # def get(self, request, *args, **kwargs):
    #     time.sleep(2)
    #     return HttpResponse("login")

    # 第二种方式 : 借助Django内置的公共函数 method_decorator
    # @method_decorator(timer)
    # def get(self, request, *args, **kwargs):
    #     time.sleep(2)
    #     return HttpResponse("login")

    # 第三种方式:重写 dispatch 方法做拦截
    def get(self, request, *args, **kwargs):
        time.sleep(2)
        return HttpResponse("login")

    def dispatch(self, request, *args, **kwargs):
        start_time = time.time()
        # 可以什么都不写
        # obj = super().dispatch(request, *args, **kwargs)
        # 可以放自己的类名和自己的对象 self
        obj = super(Login, self).dispatch(request, *args, **kwargs)
        print(f"总耗时 :>>>> {time.time() - start_time} s ")
        return obj

        # if request.method.lower() in self.http_method_names:
        #     handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        # else:
        #     handler = self.http_method_not_allowed
        # return handler(request, *args, **kwargs)

标签:知识点,return,必备,request,视图,method,login,self,def
From: https://www.cnblogs.com/Formerly/p/18102496

相关文章

  • 必备知识点 路由
    django必备知识点路由1.Django生命周期请求流程图浏览器>>发送请求(Http请求)>>web服务网关接口(django默认的wsgiref模块不能承受高并发,最大只有1000左右)>>中间件>>缓存数据库(返回给中间件已经缓存过的数据)>>urls.py(路由层)>>views.py(视图层)>>templates(......
  • 软考中级软件设计师【结构化开发】知识点+题目
      一、耦合   耦合是模块之间的相对独立性(相互连接的紧密程度)的度量。耦合取决于各个模块之间接口的复杂程度、调用模块的方式以及通过接口的信息类型等,有以下几个类型。   无直接耦合:指两个模块之间没有直接关系,它们分别属于不同模块的控制和调用,它们之间不......
  • MySQL学习必备SQL_DDL_DML_DQL
     MySQL创建数据库需要自行创建,数据库名称可以为【schoolDB】,字符集【utf8】,排序规则【utf8_general_ci】,1.学生表DDLCREATETABLE`student`( `id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'学号', `createDate`datetimeDEFAULTNULL, `userName`VARCHAR(......
  • MySQL学习必备查询语句like_between and_in
     MySQL创建数据库需要自行创建数据库名称可以为【schoolDB】,字符集【utf8】,排序规则【utf8_general_ci】,建表操作:CREATETABLE`student`( `id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'学号', `createDate`datetimeDEFAULTNULL, `userName`VARCHAR(20......
  • Go Template 常用疑难知识点
    前段时间,在项目开发中经常和go语言的HTMLLtemplate打交道,特意总结了几点我在使用中经常遇到不太明确的,比较纠结疑惑的知识点,巩固一下,也方便以后查找。​ 至于关于gotemplate的系统性的介绍说明,这是一篇我经常查看的文章,写的非常全面。1、作用域访问​ gotemplate中最常打交......
  • salesforce零基础学习(一百三十五)项目中的零碎知识点小总结(七)
    本篇参考:https://trailhead.salesforce.com/content/learn/modules/flow-implementation-2/debug-flows-as-another-userhttps://developer.salesforce.com/docs/platform/lwc/guide/create-components-dom-work.html?q=ref#refshttps://developer.salesforce.com/docs/platfo......
  • mysql 视图的创建
    概述MySQL视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。对其中所引用的基础表来说,MySQL视图的作用类似于筛选......
  • openGauss/MOGDB时间消耗相关视图
    openGauss/MOGDB时间消耗相关视图本文出处:https://www.modb.pro/db/388212数据库版本openGauss/MOGDB-2.1.1一、显示当前用户在各个节点上正在执行的作业的负载管理记录(单位:ms)包含:语句执行前的阻塞时间、语句执行的开始时间、语句已经执行的时间、语句执行预估总时间、语句......
  • 安卓开发列表视图的使用
    在Android开发中,列表视图可以通过使用ListView控件来实现。以下是使用ListView的一般步骤:1.在布局文件中添加ListView:打开布局文件,将ListView控件添加到合适的位置,并设置其属性,如布局参数和适配器。例如:<ListView  android:layout_width="match_parent" ......
  • 【知识点】接口和抽象类的区别
    相同点:都不能实例化都可以被实现或者继承继承或者实现的子类需要实现全部抽象方法,否则需要声明为抽象类不同点:不同点抽象类接口声明abstractinterface继承/实现extendsimplements构造器可以有构造器不能有构造器方法抽象方法和具体方法抽象方法......