django学习笔记(04)--视图层详解

1 视图层之请求对象

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

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

    # print(request.body)      # 请求体,二进制,如果传文件,这个报错
    '''
    使用form表单,默认情况下数据被转成name=lqz&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)  # 客户端上传的文件



    ########################3 暂时不用关注(后面会讲)
    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':'lqz','age':18})
    # return redirect('/home') # 重定向自己的地址,重定向第三方地址,经常跟反向解析一起使用

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

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

3 cbv和fbv

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

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

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

    def post(self,request):
        return HttpResponse('post')
    
## 第二步:配置路由
path('index/', views.Index.as_view()),


# 前期,全是FBV,后期,drf全是CBV




4 文件上传

## 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 postman软件

模拟发送http请求(控制请求路径,请求方式,请求头,请求体)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4SicV16H-1602233974759)(.\django-day63.assets\image-20201009115049146.png)]

7 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>

8 Pycharm的自动提示

from django.core.handlers.wsgi import WSGIRequest
# pycharm的自动提示
request=request  # type: WSGIRequest

作业

  1. 写一个项目,统计用户访问日志,记录用户的ip地址和访问时间,访问地址,存到mysql数据库

    views.py
    import datetime
    def home(request):
        user = request.user
        print(user)
        useraddr = request.path
        print(useraddr)
        ip = request.META['REMOTE_ADDR']
        print(useraddr)
        print(ip)
        da = datetime.datetime.now()
        models.Visit.objects.create(
            name=user,userip=ip,visittime=da,useraddr=useraddr)
        return render(request,'home.html')
    
    
    models.py
    class Visit(models.Model):
        name = models.CharField(max_length=32)
        userip = models.CharField(max_length=32)
        visittime = models.CharField(max_length=32)
        useraddr = models.CharField(max_length=32)
    
  2. 基于类的视图, 编写一个文件上传功能, 通过后缀限制, 只能上传图片

    html
    <form action="" method="post" enctype="multipart/form-data">
        <p><input type="text" name="user"></p>
        <p><input type="password" name="pwd"></p>
        <p><input type="file" name="myfile"></p>
        <p><input type="submit"></p>
    </form>
    
    
    # 只能上传 .jpg  .jpeg  .png  格式
    views.py
    def home(request):
        if request.POST:
            d = request.FILES.get("myfile")
            res = d.name
            jpg = res.endswith('.jpg')
            jpeg = res.endswith('.jpeg')
            png = res.endswith('.png')
            if jpg or jpeg or png:
                with open(d.name, 'wb') as f:
                    for i in d:
                        f.write(i)
                return HttpResponse("上传成功")
            else:
                return HttpResponse("格式错误")
        return render(request, 'home.html')
    
  3. 整理视图层对象, 相应对象, CBV, FBV 文件上传功能等

    index.html  前端页面
    <form action="/app01/home/" method="post" enctype="multipart/form-data">
        <p><input type="text" name="user"></p>
        <p><input type="password" name="pwd"></p>
        <p><input type="file" name="myfile" accept="image/*"></p>
        <p><input type="submit"></p>
    {#    #}
    </form>
    
    路由urls.py
    from app01 import views
    urlpatterns = [  路由匹配, 
        # path("home/",views.home),
        path('home/',views.Index.as_view()),
        path('index/',views.index)
    ]
    
    views.py视图
    
    class Index(View):  判断请求方式
        def get(self,request):
            return HttpResponse("GET")
        def post(self,request):
            return HttpResponse("POST")
    
        
    先返回一个页面, 发送post请求后向指定路由/home/再次发送请求分配, 接收后在Index类中判断
        是get请求或是post请求, 返回给页面, 这里涉及到CBV解码操作
    def index(request):
        return render(request,'home.html')
    
  4. (拓展) 研究CBV源码执行流程 , 写出执行过程

    源码剖析
    首先在视图函数中添加一个类
    class MyLogin(View):
        def get(self,request):
            return HttpResponse("get")
        def post(self,request):
            return HttpResponse("post")
    
    路由urls中添加
    path('login/',views.MyLogin.as_view()),
    相当于放了一个这样的路由
    path("login/",views.views)
    看到函数加括号, 首先想到的是调用之后的结果, 放到这里进as_view()内部, 
    
        @classonlymethod
        def as_view(cls, **initkwargs):
            类调用方法, 首先把调用类的本身传进来, MyLogin被传到  这里
            def view(request, *args, **kwargs):
                # self就是自己定义的类
                self = cls(**initkwargs)
        		# 将这个类返回, 并且携带dispatch方法, 加括号运行了这个函数, 到了吗看看
                return self.dispatch(request, *args, **kwargs)
    
        def setup(self, request, *args, **kwargs):
            # 实例对象
            self.request = request
            self.args = args
            self.kwargs = kwargs
    
        def dispatch(self, request, *args, **kwargs):
    		# 判断请求是否在允许范围, 8种请求方式, 如果请求不存在抛出异常
            if request.method.lower() in self.http_method_names:
                # 三个参数
                # 1. self: 本身中找到请求方式
                # 2. 新实例对象中找到请求方式
                # 3. 请求方式不存在抛出异常
                handler = getattr(self, request.method.lower(), 							self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            # 返回结果
            return handler(request, *args, **kwargs)
    
  5. (拓展) 研究django WSGIRequest类, 文件类, request.GET的类, 进一步理解对象属性方法

实例对象中找到请求方式
# 3. 请求方式不存在抛出异常
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
# 返回结果
return handler(request, *args, **kwargs)
```

  1. (拓展) 研究django WSGIRequest类, 文件类, request.GET的类, 进一步理解对象属性方法

你可能感兴趣的:(django)