Django——视图2

一、视图

视图函数就是一个python函数 , 当django接收到浏览器发送的请求,视图函数就进行接收与响应,视图函数的第一个参数必须是HttpRequest实例(也就是HttpRequest的对象),视图函数必须返回一个HttpResponse对象或者子对象作为响应

def index(request):
    return HttpResponse('我是HttpResponse对象')

def get_html(request):
    return render(request , 'indext.html')

def coll(request):
    # 重定向中可以直接放入视图函数名 , 重定向就是直接到这个视图函数中进行响应
    # 返回的是HttpResponse的子类对象
    return redirect(index)

1、请求HttpRequest

django使用HttpRequest的对象处理HTTP请求。

当接收到客户端的请求时 , django先创建一个HttpRequest对象 , 这个对象里面封装了请求相关的数据。django进行url的匹配 , 调用对应的视图函数 , 将HttpRequest对象传递给视图函数作为第一个参数。

def str_request(request):
    # 获取请求方式
    # print(request.method)
    # 根据请求获取对应的数据
    # post 的数据是从表单中获取数据
    # request.POST.get()

    # 获取url中的数据
    # http://127.0.0.1:8000/app1/str/?num=24
    # http://127.0.0.1:8000/app1/str/?num=24&name=%27ac%27
    # get请求中有多个数据使用 & 进行连接
    num = request.GET.get('num')
    name = request.GET.get('name')
    print(num , name)

    # 获取url路径
    url_path = request.path
    # get_full_path 当url中带有参数 , 那么同时也会把对应的参数也获取到
    get_url_path = request.get_full_path()
    print(url_path)
    print(get_url_path)
    return HttpResponse('ok')

2、响应HttpResponse

返回响应错误

django可以返回HTTP状态码 和状态描述信息。正常情况下视图函数返回的是HttpResponse对象的状态码:200。表示服务器正确处理响应成功。

django也提供了多个HttpResponse子类的响应状态。

# 301 返回永久重定向
from django.http import HttpResponsePermanentRedirect
def text_301(request):
    return HttpResponsePermanentRedirect('/admin')

# 400 表示请求错误
from django.http import HttpResponseBadRequest
def text_400(request):
    return HttpResponseBadRequest('请求错误')

# 404 找不到请求的内容
from django.http import HttpResponseNotFound
def text_404(request):
    return HttpResponseNotFound('没有找到请求内容')

# 500 服务器问题
from django.http import HttpResponseServerError
def text_500(request):
    return HttpResponseServerError('服务器出现错误')

# 直接通过http的状态码进行响应
def text_status(request):
    return HttpResponse(status=404)

二、类视图

前面实现的视图都是基于函数来实现 , 实现是特定的业务逻辑,其扩展性不高。函数视图(FBV)

类视图,把视图函数的逻辑进行拆分成类中的多个函数。复用性高 ,扩展强.

在django中所有基于类的视图都要继承与django.views.View

from django.http import HttpResponse
from django.views import View

class MyView(View):
    def get(self , request):
        # 当http的请求方式是get请求的时候执行
        return HttpResponse
    def post(self , request):
        # 当http的请求方式是post请求的时候执行
        return HttpResponse

as_view源码

def as_view(cls, **initkwargs):
    """Main entry point for a request-response process."""
    def view(request, *args, **kwargs):
        # 实例化类对象
        self = cls(**initkwargs)
        self.setup(request, *args, **kwargs)
        # 反射:使用字符串的方式访问类中的属性或者方法
        # hasattr 判断 request 是HttpRequest的对象是否存在
        if not hasattr(self, 'request'):
            # raise 抛出异常
            raise AttributeError(
                "%s instance has no 'request' attribute. Did you override "
                "setup() and forget to call super()?" % cls.__name__
            )
            return self.dispatch(request, *args, **kwargs)
    return view

dispatch源码

def dispatch(self, request, *args, **kwargs):
    # request.method.lower() 将请求方式变成小写的
    # http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    # 判断当前请求是否在请求列表中
    if request.method.lower() in self.http_method_names:
        # 请求方式在请求方式列表中
        # 当请求方式对应的视图存在,则进行调用 , 不存返回405
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed
        # http_method_not_allowed 返回405状态码的对应响应信息
        # 405 表示禁止使用指定的请求方式
        # 1、定义了类视图 , 但类中没有定义对应请求方式的视图函数
        # 2、请求方式不存在
        return handler(request, *args, **kwargs)

三、文件上传

def getfile(request):
    if request.method == 'GET':
        return render(request , 'get_file.html')
    # 获取到file的对象
    file = request.FILES.get('file')
    # 获取到文件名
    name = file.name
    # 文件的保存路径
    file_dir = os.path.join(settings.BASE_DIR , 'templates' , name)
    # 读取浏览器上传的文件
    with open(file_dir , 'wb') as f:
        # 读取文件对象中的内容需要使用循环读取
        for data in file:
            f.write(data)
    return HttpResponse('ok')
    <form method="post" enctype="multipart/form-data" action="">
        {% csrf_token %}
        <!--enctype="multipart/form-data" 以二进制的方式读取数据
            application/x-www-form-urlencoded 以键值对的方式读取数据-->
        <p>姓名:<input type="text" name="user"></p><br>
        <p>密码:<input type="password" name="password"></p><br>
        <p>文件:<input type="file" name="file"></p><br>
        <input type="submit" value="提交">
    </form>