zoukankan      html  css  js  c++  java
  • Django

    视图层之视图函数(views)

    一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应。响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . . 是任何东西都可以。无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你的Python目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,约定是将视图放置在项目或应用程序目录中的名为views.py的文件中。

    视图函数:
        一定包含两个对象:
            requset---->用户请求相关的所有信息(对象)
            Httpresponse---->响应字符串

    一个简单的视图

    下面是一个返回当前日期和时间作为HTML文档的视图:

    from django.http import HttpResponse
    import datetime
    
    def current_datetime(request):
        now = datetime.datetime.now()
        html = "<html><body>It is now %s.</body></html>" % now
        return HttpResponse(html)

    让我们逐行阅读上面的代码:

    • 首先,我们从 django.http模块导入了HttpResponse类,以及Python的datetime库。

    • 接着,我们定义了current_datetime函数。它就是视图函数。每个视图函数都使用HttpRequest对象作为第一个参数,并且通常称之为request

      注意,视图函数的名称并不重要;不需要用一个统一的命名方式来命名,以便让Django识别它。我们将其命名为current_datetime,是因为这个名称能够精确地反映出它的功能。

    • 这个视图会返回一个HttpResponse对象,其中包含生成的响应。每个视图函数都负责返回一个HttpResponse对象。

    视图函数,围绕着两个对象进行:HttpResponse和HttpRequest

    1.HttpRequest

      request---->请求信息

    属性:

    request.path       # 获取访问文件路径
    
    request.method属性   #获取请求中使用的HTTP方式(POST/GET)

    request.body      #含所有请求体信息 是bytes类型
    request.GET       #GET请求的数据(类字典对象) 请求头中的url中?后面拿值
    request.POST     # POST请求的数据(类字典对象) 请求体里拿值

    request.COOKIES     #包含所有cookies的标准Python字典对象;keys和values都是字符串。

    request.FILES      包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中
                     name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:
    
                     filename:      上传文件名,用字符串表示
                     content_type:   上传文件的Content Type
                     content:       上传文件的原始内容
    
    
    request.user:       是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前
                     没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你
                     可以通过user的is_authenticated()方法来辨别用户是否登陆:
                     if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware
                     时该属性才可用
    
    request.session      唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用

    request.GET.get('name')    拿到GET请求里name的值

    如果某个键对应有多个值,则不能直接用get取值,需要用getlist,如:

    request.POST.getlist("hobby")


    请求url:http://127.0.0.1:8000/index.html/23?a=1

    request.path : 请求路径      
           request.path结果为:/index.html/23

    request.get_full_path()
           request.get_full_path()结果为:/index.html/23?a=1
    
    

    方法:

    1
    get_full_path()

    注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用:

    1
    request.POST.getlist("hobby")

     

    2.HttpResponse

      HttpResponse---->相应字符串

      对于HttpRequest请求对象来说,是由django自动创建的,但是,HttpResponse响应对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse响应对象。HttpResponse类在django.http.HttpResponse。

    在HttpResponse对象上扩展的常用方法

     1.render 函数

      将指定页面渲染后返回给浏览器

    render(request, template_name[, context])

    结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。

    参数:
         request: 用于生成响应的请求对象。
    
         template_name:要使用的模板的完整名称,可选的参数
    
         context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
    
         content_type:生成的文档要使用的MIME类型。默认为DEFAULT_CONTENT_TYPE 设置的值。
    
         status:响应的状态码。默认为200。
    from django.shortcuts import render
    
    def test(request):
        return render(request,'index.html')   #向用户显示一个html页面

    下面为render官方源码,可以看出render最后也是返回了一个HttpResponse给webserver

    def render(request, template_name, context=None, content_type=None, status=None, using=None):
        """
        Returns a HttpResponse whose content is filled with the result of calling
        django.template.loader.render_to_string() with the passed arguments.
        """
        content = loader.render_to_string(template_name, context, request, using=using)
        return HttpResponse(content, content_type, status)

    细说render:

      render方法主要是将从服务器提取的数据,填充到模板中,然后将渲染后的html静态文件返回给浏览器。这里一定要注意:render渲染的是模板,下面我们看看什么叫作模板:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Title</title>
        <style>
            li,ul,ol{  list-style: none;  }
            a{ text-decoration: none; }
        </style>
    </head>
    <body>
    <ul>
        {% for book in list %}
            <li><a href="{{book.id}}">{{ book.btitle }}</a></li>
        {% endfor %}
    </ul>
    </body>
    </html>

    上面{%%}之间包括的就是我们要从数据库取出的数据,进行填充。对于这样一个没有填充数据的html文件,浏览器是不能进行渲染的,所以,对于上述{%%}之间的内容先要被render进行渲染之后,才能发送给浏览器。

      下面举个例子:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Title</title>
        <style>
            li,ul,ol{  list-style: none;  }
            a{ text-decoration: none; }
        </style>
    </head>
    <body>
    <ul>
        {% for book in list %}
            <li><a href="{{book.id}}">{{ book.btitle }}</a></li>
        {% endfor %}
    
    </ul>
    </body>
    </html>
    show.html
    def show(request, id):  
        book = BookInfo.objects.get(pk=id)   #从数据库中取出对应id的数据
        herolist = book.heroinfo_set.all()  
        context = {'list': herolist}       # 将数据保存在list
        return render(request, 'booktest/show.html', context) #通过render进行模板渲染

     2.redirect 函数

    参数可以是:

    • 一个模型:将调用模型的get_absolute_url() 函数
    • 一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称
    • 一个绝对的或相对的URL,将原封不动的作为重定向的位置。

    默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向。

    示例:

    你可以用多种方式使用redirect() 函数。

    传递一个对象

    将调用get_absolute_url() 方法来获取重定向的URL:

    1
    2
    3
    4
    5
    6
    from django.shortcuts import redirect
     
    def my_view(request):
        ...
        object = MyModel.objects.get(...)
        return redirect(object)

    传递一个视图的名称

    可以带有位置参数和关键字参数;将使用reverse() 方法反向解析URL: 

    1
    2
    3
    def my_view(request):
        ...
        return redirect('some-view-name', foo='bar')

    传递要重定向的一个硬编码的URL

    1
    2
    3
    def my_view(request):
        ...
        return redirect('/some/url/')

    也可以是一个完整的URL:

    1
    2
    3
    def my_view(request):
        ...
        return redirect('http://example.com/')

    默认情况下,redirect() 返回一个临时重定向。以上所有的形式都接收一个permanent 参数;如果设置为True,将返回一个永久的重定向:

    1
    2
    3
    4
    def my_view(request):
        ...
        object = MyModel.objects.get(...)
        return redirect(object, permanent=True)  

    跳转(重定向)应用

    -----------------------------------url.py
    
     url(r"login",   views.login),
     url(r"yuan_back",   views.yuan_back),
    
    -----------------------------------views.py
    def login(req):
        if req.method=="POST":
            if 1:
                # return redirect("/yuan_back/")
                name="yuanhao"
    
                return render(req,"my backend.html",locals())
    
        return render(req,"login.html",locals())
    
    
    def yuan_back(req):
    
        name="苑昊"
    
        return render(req,"my backend.html",locals())
    
    -----------------------------------login.html
    
    <form action="/login/" method="post">
        <p>姓名<input type="text" name="username"></p>
        <p>性别<input type="text" name="sex"></p>
        <p>邮箱<input type="text" name="email"></p>
        <p><input type="submit" value="submit"></p>
    </form>
    -----------------------------------my backend.html
    <h1>用户{{ name }}你好</h1>
    View Code

    下面我们来看一个现象:

    --------------------urls.py------------------------------
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/', views.login),
        url(r'^index/', views.index,),
        # url(r'^register/', views.register,name='reg'),
    
    ]
    
    ------------------view.py-------------------------------
    def login(request):
        if request.method=='POST':
            username=request.POST.get('user')
            password=request.POST.get('pwd')
            if username=='yuan' and password=='123':
                # return render(request,'index.html')
                return redirect('/index/')
            else:
                return render(request,'login.html',{'info':'账号或密码错误'})
        else:
            return render(request,'login.html')
    
    
    def index(request):
            name='yuan'
            return render(request,'index.html',{'a':name})
    
    ---------------login.html--------------------------------
    <h1>登陆界面</h1>
    <form action="/login/" method="post">
        <p>姓名 <input type="text" name="user"></p>
        <p>密码 <input type="password" name="pwd"></p>
        <p><input type="submit"></p>
        <p>{{ info }}</p>
    </form>
    
    
    ---------------login.html--------------------------------
    <h1>个人主页</h1>
    <h2>hello,{{ a}}</h2>
    代码

    首先,启动服务器后,我们进入login页面

    正确输入姓名,密码后,此时执行redirect函数,结果如下

    现在我们将redirect换成render,再重新走一遍看看,在login页面,正确输入姓名,密码后,结果如下:

    细心的人会发现,用render函数执行后的,地址栏的地址没有变化,还是login,且页面上的{{a}}此时也没有被渲染,所以hello,后面没有内容显示!

    对比render与redirect:

    原因是
            render: 只是返回页面内容,但是未发送第二次请求
            redirect:发送了第二次请求,url更新

    总结两者区别:    

         第一,render返回一个登陆成功后的页面,刷新该页面将回复到跳转前页面。而redirect则不会

           第二,如果页面需要模板语言渲染,需要的将数据库的数据加载到html,那么render方法则不会显示这一部分,render返回一个登陆成功页面,不会经过url路由分发系统,也就是说,不会执行跳转后url的视图函数。这样,返回的页面渲染不成功;而redirect是跳转到指定页面,当登陆成功后,会在url路由系统进行匹配,如果有存在的映射函数,就会执行对应的映射函数。

  • 相关阅读:
    分页得到查询总数的方法 mysql
    input[type="file"] change事件第二次不触发
    小程序post请求,后台接收不到数据的解决方法
    Docker安装Kibana
    Docker安装ElasticSearch
    Docker安装Redis
    Docker安装Tomcat
    Docker安装 Nginx
    mysql服务设置远程连接 解决1251 client does not support ..问题
    Docker 安装MySQL容器
  • 原文地址:https://www.cnblogs.com/huchong/p/7718393.html
Copyright © 2011-2022 走看看