Django视图层之请求对象、响应对象、CBV、文件上传、pycharm自动提示、前后端交互编码及模板语法变量、句点符的使用

1、视图层之请求对象

def index(request):
    '''
    request: django封装的对象,它的类是WSGIRequest,它里面包含了所有http请求的东西
    '''
    print(request)
    print(type(request))
    # from django.core.handlers.wsgi import WSGIRequest
    
    # 请求方式
    print(request.method)
    print(request.GET)
    print(request.POST)

    # 自定制请求头
    # 上传文件使用的编码方式是form-data,默认编码方式urlencoded
    print(request.is_ajax())  # 是不是ajax请求
    print(request.path)       # 请求路径
    print(request.get_full_path())  # 请求全路径,带数据

    # print(request.body)      # 请求体,二进制,如果传文件,这个报错
    '''
    使用form表单,默认情况下数据被转成name=allen&password=123放到请求体中
    request.POST其实是从body中取出bytes格式的,转成了字典
    requet.GET其实是把路径中?后面的部分拆出来,转成了字典
    '''
    print(request.encoding)  # 客户端向服务端传递时,使用的编码方法

    print(request.META)      # 是字典,包含了一堆东西,请求用户的ip地址,请求头中数据,用户自定制请求头的数据
    '''
    把请求头的key值部分统一加HTTP_  并且全部转成大写
    '''
    print(request.META['REMOTE_ADDR'])  # 客户端的ip地址
    print(request.FILES)  # 客户端上传的文件

	# cookie、session相关
    print(request.COOKIES) # 空字典
    print(request.session) # session对象
    print(request.user)    # 匿名用户
    return HttpResponse('ok')

2、视图层之响应对象

# 重点: JsonResponse的使用(看源码)
def index(request):
    # 三剑客
    return HttpResponse('ok')
    return render(request,'index.html',context={'name':'allen','age':18})
    return redirect('/home')  # 重定向自己的地址,重定向第三方地址,经常跟反向解析一起使用

    # 向客户端返回json格式数据
    import json
    res=json.dumps({'name':'allen','age':18,'gender':'男'},ensure_ascii=False)
    return HttpResponse(res)
    # django内置提供的JsonResponse
    # 本质还是HttpResponse

    # ensure_ascii
    return JsonResponse({'name':'allen','age':18,'gender':'男'},json_dumps_params={'ensure_ascii':False})
    # safe,转换除字典以外的格式,需要safe=False
    return JsonResponse([11,12,13,'allen',[1,2,3],{'name':'allen','age':19}],safe=False)

3、cbv初步认识

# CBV基于类的视图(Class base view)和FBV基于函数的视图(Function base view)
# 之前使用的全是FBV,写的是视图函数

# 写视图类(还是写在views.py中)
# 第一步,写一个类,继承View
from django.views import View

class IndexView(View):
    def get(self, request):  # 当url匹配成功,get请求,会执行它
        return HttpResponse('ok')

    def post(self,request):  # 当url匹配成功,post请求,会执行它
        return HttpResponse('post')
    
# 第二步,配置路由
path('index/', views.IndexView.as_view()),

# 说明: 前期,全是FBV,后期,drf全是CBV

4、cbv本质(源码分析)

# 突破口在urls.py
url(r'^login/',views.MyLogin.as_view())
# url(r'^login/',views.view)  FBV一模一样
# CBV与FBV在路由匹配上本质是一样的 都是路由 对应 函数内存地址
"""
函数名/方法名 加括号执行优先级最高

as_view(): 是被@classmethod修饰的类方法
        
@classonlymethod
def as_view(cls, **initkwargs):
    pass
"""

@classonlymethod
def as_view(cls, **initkwargs):
    """
    cls就是我们自己写的类   MyCBV
    Main entry point for a request-response process.
    """
    def view(request, *args, **kwargs):
        self = cls(**initkwargs)  # cls是我们自己写的类
        # self = MyLogin(**initkwargs)  产生一个我们自己写的类的对象
        return self.dispatch(request, *args, **kwargs)
        """
        	在看python源码的时候 一定要时刻提醒自己面向对象属性方法查找顺序
            先从对象自己找
            再去产生对象的类里面找
            之后再去父类找
            ...
        总结: 看源码只要看到了self点一个东西 一定要知道当前这个self到底是谁
        """
    return view
  
# 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方法
    """

总结:
1、请求来了,路由匹配成功执行 url(r’^login/’,views.MyLogin.as_view()),
执行views.MyLogin.as_view()()
2、本质是执行as_view()内部有个闭包函数view()
3、本质是view() —>调用dispatch()
4、dispatch内部,根据请求的方法(get,post ---->执行视图类中的def get def post

5、文件上传

<!-- html注意编码方式 -->
<form action="/index/" method="post" enctype="multipart/form-data">
    <p>用户名: <input type="text" name="name"></p>
    <p>密码: <input type="password" name="password"></p>
    <p>头像: <input type="file" name="myfile"></p>
    <p><input type="submit" value="提交"></p>
</form>
# views.py
def index(request):
    file=request.FILES.get('myfile')
    # 打开一个空文件,写入
    with open(file.name,'wb') as f:
        for line in file.chunks():
            f.write(line)
    return HttpResponse('文件上传成功')

6、form表单,提交地址

# action
# 1、不写,默认向当前地址发送请求
# 2、/index/,向当前域(http://127.0.0.1:8000/)的/index/发送请求
# 3、http://127.0.0.1:8000/index/,向该地址发送请求(可以向第三方服务发送请求)

# method
# 1 post: 发送post请求(默认编码情况下: 以key=value&key=value的形式拼到请求体中)
# 2 get: 发送get请求(以key=value&key=value的形式拼到路径中)

<form action="/index/" method="post">
    <p>用户名:<input type="text" name="name"></p>
    <p>密码:<input type="text" name="password"></p>
    <p><input type="submit" value="提交"></p>
</form>

7、Pycharm的自动提示

# 如果在写项目中,pycharm没有自动提示,需要自己指定使用类型
from django.core.handlers.wsgi import WSGIRequest
# pycharm的自动提示
request=request  # type: WSGIRequest

8、前后端交互编码方式

1、urlencoded---->传普通的数据,form表单默认就是这种---->request.POST
2、form-data----->传文件和数据                   ---->request.POST   request.FILES
3、json---------->传json格式数据                 ---->request.body中取出来自行处理

def index(request):
    # 接收urlencoded编码
    body体中: name=allen&age=18
    print(request.POST)

    # 接收form-data编码
    body体中: 分两部分,一部分是数据,一部分是文件
    数据部分: name=allen&age=18
    ---asdfasdfasdfgasgasgd---  # 中间的分隔符
    文件部分(二进制)
    
    # 数据部分
    print(request.POST)
    # 文件部分
    print(request.FILES)

    # 接收json格式
    body体中 
    {
    "name": "allen",
    "age": 18
	}
    # 这里没有
    print(request.POST)
    # 数据在这(自行处理)
    print(request.body)
    return HttpResponse('ok')

9、django模板使用的两种方式

# 方式一(直接使用render渲染)
return render(request,'time.html',context={'current_date':str(now),'title':'测试文件'})

# 方式二(页面静态化,提高网站并发量)
now=datetime.datetime.now()
from project import settings
import os
path=os.path.join(settings.BASE_DIR,'templates','time.html')
ss=open(path,'r',encoding='utf-8').read()
t=Template(ss)
c=Context({'current_date':str(now),'title':'测试文件'})
html=t.render(c)  # html是渲染后的字符串
return HttpResponse(html)

10、模板语法之变量

DTL:Django Template Language

10.1、views.py文件
模板中使用 {{python变量}}

def index(request):
    num = 10
    str = 'hello world'
    flag = False
    ll = [1, 2, 43]
    user_info = {'name': 'allen', 'age': 18}

    def test():
        print('我是test')
        return 'test'

    class Person():
        def __init__(self, name):
            self.name = name

        def print_name(self):
            return self.name
        def __str__(self):
            return self.name

    p = Person('allen')
	# 方式一: 在字典中一个一个传参数
    return render(request, 'index.html',{'num':num,'str':str,'flag':flag,'ll':ll,'user_info':user_info,'test':test,'p':p })
    
    # 方式二: locals() 把当前作用域下所有的变量,都传到context中
    return render(request, 'index.html',locals())
10.2、index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ss}}</title>
</head>
<body>

<h1>模板语法之变量</h1>

<p>数字: {{ num }}</p>
<p>字符串: {{ str }}</p>
<p>布尔: {{ flag }}</p>
<p>列表: {{ ll }}</p>
<p>字典: {{ user_info }}</p>
<p>函数: {{ test }}</p>
<p>对象: {{ p }}</p>
</body>
</html>

11、模板语法之深度查询句点符

11.1、views.py
def index(request):
    num = 10
    str = 'hello world'
    flag = False
    ll = [1, 2, 43, {'name': 'allen'}]
    user_info = {'name': 'allen', 'age': 18}

    def test():
        print('我是test')
        return 'test'

    class Person():
        def __init__(self, name):
            self.name = name

        def print_name(self):
            return self.name
            
        def __str__(self):
            return self.name
            
    p = Person('allen')
    
    link1 = '<a href="https://www.baidu.com">点我<a>'
    link2 = mark_safe(link1)

    input_1='<p>用户名:<input type="text" name="name"></p>'
    input_2=mark_safe(input_1)

    script_1='''
    <script>
    alert('你被攻击了')
    </script>
    '''
    script_2 =mark_safe(script_1)
    return render(request, 'index.html', locals())
11.2、index.html
<h2>模板语法之句点符的深度查询</h2>
<p>列表的第一个元素: {{ ll.1 }}</p>
<p>字典的name对应的值: {{ dic.name }}</p>
<p>列表的第三个元素的name对应的值: {{ ll.3.name }}</p>
<p>函数执行,直接写函数名即可: {{ test }}</p>
<p>函数如果有参数?不支持</p>
<p>对象调用方法: {{ p.print_name }}</p>
<p>对象调用属性: {{ p.name }}</p>
<hr>
<a href="https://www.baidu.com">点我</a>
<p>a标签的字符串: {{ link1 }}</p>
<p>a标签的字符串,显示成a标签: {{ link2 }}</p>

<p>用户名:<input type="text" name="name"></p>
<p>input标签:{{ input_1 }}</p>
<p>input标签,显示成标签:{{ input_2 }}</p>

<p>js原封不动显示:{{ script_1 }}</p>
{{ script_2 }}  <!--容易出现xss攻击-->

12、模板渲染成标签还是原封不动的字符串

# 容易造成xss攻击, django已经处理了xss攻击,直接处理成原封不动的字符串

from django.utils.safestring import mark_safe
link1 = '<a href="https://www.baidu.com">点我<a>'
link2 = mark_safe(link1)
{link1|safe}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值