Django 规范化编程7

Django进阶

Task1 了解请求

相信学过计网的大家对请求,尤其是B/S的HTTP请求大家应该都了解的差不多了。这里抛开计网的知识不谈,我们来解析一下。

其实Django的请求,或者说Django的请求对象我们在之前已经接触过,在Views中我们的函数都会有一个参数:request: Django.http.HttpRequest。这个请求我们可以差分出以下的属性:

path : 完整的请求路径
method: 请求方法 GET POST PUT DELETE
headers:  accept:      接受的编码格式
		 cookies:     字典,包含所有的cookie参数
		              cookie中也包括session
		 meta:        客户端的元数据

我们来具体看一下请求对象,这样才能搞懂他的操作与原理的嘛

class HttpRequest:
    """A basic HTTP request."""

    # The encoding used in GET/POST dicts. None means use default setting.
    _encoding = None
    _upload_handlers = []

    def __init__(self):
        # WARNING: The `WSGIRequest` subclass doesn't call `super`.
        # Any variable assignment made here should also happen in
        # `WSGIRequest.__init__()`.
        # GET请求,POST请求结果是一个QueryDict对象
        self.GET = QueryDict(mutable=True)
        self.POST = QueryDict(mutable=True)
        # Cookies, Meta是字典
        self.COOKIES = {}
        self.META = {}
        self.FILES = MultiValueDict()
		
        # 请求路径是字符串
        self.path = ""
        self.path_info = ""
        self.method = None
        self.resolver_match = None
        self.content_type = None
        self.content_params = None

根据Django的封装,我们来具象化Django可以接受的参数

  • GET 查询参数
  • POST 表单参数, 包好post / put两个请求方法的参数
  • COOKIES 客户端当前domain的所有cookie信息
  • MTEA 客户端的源信息
    • REMOTE_ADDR
  • FILES 上传的表单参数中所有的文件对象
  • session 会话中存储的数据
  • path 请求路径
  • method 请求方法
  • content_type 数据类型, 如text/html;
  • content_params 编码类型, 如 charset = utf8
  • body 字节码数据,一般接受上传的json数据

关于request的常用API直接在pychram中翻一翻就行了

Tips: URL 与 URI https://www.cnblogs.com/xy586/p/13281562.html?ivk_sa=1024320u

URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。 Web上可用的每种资源如HTML文档、图像、视频片段、程序等都是一个来URI来定位的, URI说白了是给开发者用的,用于Rest规范

URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。URL说白了是给客户访问用的。

TIPS: 关于请求,对于一个URL进行一个参数的多次赋值,最后会返回最后赋值的那个值。eg. weibo 微博搜索 (weibo.com)会在跳转到第四页的结果而不是前面的2,3页

Task2 PUT请求初尝试

咱就是说,HTTP的form 表单时只能使用GET 和POST方法,是没有办法使用PUT 与DELETE方式传参的,就算强用了,也会发生下面这样的事故:

<form action="http://127.0.0.1:8000/son1/hello" method="puts">

在这里插入图片描述

方法直接就变成GET了,那肯定不行。上网查了下,没办法,最简单的方式就是ajax。 其实我就没学过前端的,不过玩渗透的嘛,总是会接触一点点,所以尝试手搓一个ajax

<script>
    function PUT_method() {
        data = {
            name: '爸爸,我是你儿子',
        };
        fetch('',{
        method:'PUT',
        headers:{
            'Content_Type':"application/x-www-form-urlencoded"
        },
        body: JSON.stringify(data)
        }).then(response => response.text()).then(html => {document.write(html)})

    }
</script>

在这里插入图片描述

就是咱能看出Ajax能实现PUT的传播数据的。或者我们想串表单数据的话将data值更换即可

<script>
    function PUT_method() {
        data = {
            name: document.forms[0].name.value
        };
        fetch('',{
        method:'PUT',
        headers:{
            'Content_Type':"application/x-www-form-urlencoded"
        },
        body: JSON.stringify(data)
        }).then(response => response.text()).then(html => {document.write(html)})

    }
</script>
Task3 META数据初识

我们刚刚说过meta是存储访问的源信息。meta字段(元数据)
META是wsgi的请求元数据,包括服务起的环境信息,客户端的请求信息等。这玩应竟然包含了机子的环境变量等等各种适合渗透的信息。。。所以说,这玩应绝对不要放在你的模板上,不然机子都给你日穿了。

# views.py
@csrf_exempt
def put_try(request: HttpRequest):
    print(request.META)
    return render(request, 'post_try.html', locals())

# part_of output 我截取了部分wsgi的内容
{'wsgi.multithread': True, 
'wsgi.multiprocess': False, 
'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>, 
'CSRF_COOKIE': 'sp838ShEhEcgi82TddA8Mk28PcC9rIvvJn8ALnxgsa77vsDaiZXJXpxnJId9rFRk'}

Task4 文件上传

首先我们要明确,GET和POST在传文件上面的区分。为社么我们要用POST传输文件呢:

  • 首先:Post传输数据时,不需要在URL中显示出来,而Get方法要在URL中显示。
  • 其次:Post传输的数据量大,可以达到2M,而Get方法由于受到URL长度限制,只能传递大约1024字节.
  • 再次:Post就是为了将数据传送到服务器段,Get就是为了从服务器段取得数据.而Get之所以也能传送数据,只是用来设计告诉服务器,你到底需要什么样的数据.Post的信息作为http请求的内容,而Get是在Http头部传输的

也就是说,GET真的只适合请求,求求不要用GET来进行文件传输了。好,接下来我们先把前端给冲了

#在form中一定要设置type为文件上传类型,不然收不到文件 
<form action="http://127.0.0.1:8000/upload" method="post", enctype=”multipart/form-data”>
    <p>这是一个文本框<input name = 'text',value="你好,天龙人",type="text"/></p>
    # 在HTML中上传文件使用的是input type = file标签即可
    <p>上传文件这里请<input name = 'file', type="file"/></p>
    <button type="submit", value="Submit">提交</button>
</form>

题外话,咱就是说套模板套久了自己写个form是真的太丑了看不下去 好的,我们来看后端。在request中,虽然文件使用POST上传的,但是文件并没有放在request.POST这个QuerySet()里面。他里面放的是文件名(真的是笑死我了)。我们想要调用文件的时候,需要用到request.FIFE这个东西。

m = request.POST.get('file',None)
print(type(m))
<class 'str'>

俗话说得好,遇到不懂的就看源码,我们直接找request.FILES对象嘛。你看我们上面的源码,然后能看到文件是一个MultiValueDict()对象。至于MulyivalueDict, 我们反倒定义,开头头一句就是个class继承dict。那差不多也和字典没啥区别了呀,下面已经可以不用看了。

# 看的出来,自己覆写的字典子类,那我们其实本质上还是自定义功能的字典嘛,就把它当字典用
class MultiValueDict(dict):
    def __init__(self, key_to_list_mapping=()):
        super().__init__(key_to_list_mapping)

我们接下来需要搞定文件的类型。

# views.py
def file_upload_deemo(request: HttpRequest):
    if request.method == "GET":
        return render(request, 'upload_deemo.html', locals())
    else:
        n = request.FILES.get('file', '123')
        print(type(n))
        return HttpResponse('Hello')
<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>

这个东西,看名字就知道,是一个存在内存里的文件。这个类叫InMemoryUploadedFile。 我们想验证文件类型的时候,使用MIME这个协议的接口进行验证(因为它文件转换使用的是MIME)

# 限制文件类型。这个type的字符串我们可以查MIME的type
if n.content_type.startswith('image/'):

存文件的时候我们最好分块存储。文件本身给我们这个借口了,不然大文件那就啥也干不了的卡死了,IO始终是计算机的瓶颈痛点。至此,我们就完成了简单的文件上传。

 # 用wb参数是因为他是2进制文件
    with open('路径' + n.name, 'wb') as writer:
      # 分段写入
      for chuck in n.chunks():
            writer.write(chuck)
            writer.flush()
      return HttpResponse('上传成功')
Task5 了解Response对象

响应对象是视图函数返回的对象,由我们自己创建。 我们在写views的时候返回的哪个东西就叫做response响应对象。比如说render, redirect等等返回值,常见的响应对象类 :

  • HttpResponse
  • HttpResponseRedirect
  • JsonResponse

响应对象可以包含的属性:

  • content: 响应的内容,或者说渲染后的模板
  • status: 响应的状态码,快去复习
  • content_type 响应的数据类型(http, img等等等等)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值