zoukankan      html  css  js  c++  java
  • django修身大法之吸星大法

    路由和视图

    Django中的视图主要用来接受Web请求,并做出响应。此响应可以是网页,重定向或404错误,ⅪML文档或图像等的HTML内容。在mνt模式中,视图负责从模型中获取数据,然后展示在模板中,是联系模型和模板的桥梁,是业务逻辑层。

    视图响应的过程:
    当用户从浏览器发起一次请求时,首先 django获取用户的请求,然后通过路由(urls)将请求分配到指定的是视图函数。视图函数负责进行相应的业务处理,处理完毕后把结果(可能是json、htm等)浏览器

    1.路由

    当用户在您的web应用程序上发出页面请求时,Django会获取url中请求路径(端口之后的部分),然后通过 urls.py文件查找与路径相匹配的视图,然后返回HTML响应或404未找到的错误(如果未找到)。在urls.py中,最重要的是“urlpatterns列表。这是您定义URL和视图之间映射的地方。映射是URL模式中的path对象,例如

    from django.conf.urls import patterns, include
    from app import views
    urlpatterns = [
         path('hello/', views.hello, name='hello'),
         path('blog/', include('blog.urls')),
    ]
    

    path对象有四个参数

    • 模式串:匹配用户请求路径的字符串(和fask一样)
    • 视图函数:匹配上用户指定请求路径后调用的是视图函数名
    • kwargs:可选参数,需要额外传递的参数,是一个字典
    • 名称(name):给路由命名,在代码中可以使用ηame进行反向解析(由name获取用户请求路劲)。

    另外,如果path中模式串如果不能满足你路由规则,还可以使用 re_path对象re_path对象中模式串是正则表达式,其他三个参数和path对象一致

    1.1 模式

    path中的模式串是一个普通字符串,用于匹配用户的请求路径。如果这种方式无法满足复杂路由请求的话,可以使用re_path完成路由映射,re_path中模式包含了个上尖括号(^和一个美元符号($)。这些都是正则符号,上尖括号表示从字符串开头匹配。美元符号表示匹配字符串的结尾,这两个符号和到一起就表示模式必须完全匹配路径,而不是包含一部分。比如对于模式:

    r'^hello/$' 如果不包含美元符,也就是r'^hello/' ,任何以/hello/的url都可以
    匹配,例如:/hello/world/、/hello/1/2/等,同样如果不以上尖括号开头,则任何
    以hello/做结尾的url都可以匹配。

    Django检查ur模式之前会移除模式前的/,所以ur模式前面的/可以不写,但如果在地址栏里请求的时候不带尾斜杠,则会引起重定向,重定向到带尾斜杠的地址,所以请求的时候要带尾斜杠

    模式匹配的时候要注意:

    • Django从上往下进行模式匹配,一旦匹配成功就不会往下继续匹配了
    • 一个视图函数可以有多个模式匹配
    • 模式前面不需要加/
    • 如果匹配不上,则会引起异常,Django会调用错误处理视图处理(关闭调试模式)

    1.2 URL配置

    在setting中指定根级url配置⽂件,对应的属性ROOT_URLCONF

    (1)urlpatterns:⼀个url实例的列表,全在根配置中搞定

    (2)导入其它ur配置:在应用中创建 urls.py文件编写匹配规则,在工程 urls.py中进行导入包含

    from django.urls import include
    urlpatterns = [ path('xxx/',include('App.urls')) ]
    

    Django的请求处理流程:

    • Django获取用户发出请求
    • Django在工程配置文件 settings.py中通过 ROOT URLCOF配置来确定根URLconf
    • Django在 URLcon仲中的所有URL模式中,查找第一个配的条目
    • 如果找到匹配,将调用相应的视图函数,并将 Httpreuest对象传入
    • 视图函数回一个 Httpresponse响应

    1.3 动态url

    前面写的url都是静态的,无法给视图函数传递数据,要想给视图函数传参数,url必须是动态,带有参数,但 Django主张漂亮简介的url,所以不会使用查询字符串
    (/hello?name=tom),而是采用通配符:

    path("hello/<name>/",views.hello)
    path("show/<name>/<int:age>",views.show)
    re_path(r'^hello/(w+)/$',views.hello) 
    #http://localhost:8000/hello/tom/
    

    在path中使用<参数名>表示所传参数,视图函数中的参数名必须和<>中参数名⼀
    致。参数可以是以下类型:

    • str:如果没有指定参数类型,默认是字符串类型。字符串参数可以匹配除/和
      空字符外的其他字符串
    • int:匹配0和正整数,视图函数的参数将得到⼀个整型值
    • slug:匹配由数字、字母、-和_组成的字符串参数
    • path:匹配任何非空字符串,包括/。

    在re_path中,()部分是正则的组, django在进⾏url匹配时,就会自动把匹配
    成功的内容,作为参数传递给视图函数。

    • 位置参数:url中的正则表达式组,和视图函数中的参数⼀⼀对应,函数中的参
      数名可以随意指定。
    #位置参数:hello/name/age
    re_path(r'^hello/(w+)/(d{1,2})/$',views.hello)
    #视图函数
    def hello(req,value1,value2): #参数名字随意,但从左往右和url中分组对应
     return HttpResponse("哈喽:" + value1 + " age= {}".format(value2))
    
    • 关键字参数:对正则表达式分组进行命名
    ?P<组名>
    url(r'^hello/(?P<name>w+)/(?P<age>d{1,2})/$',views.hello),
    
    #视图函数
    def hello(req,name,age): #参数名字必须是name和age,和url中命名⼀致,但顺序随意
     	return HttpResponse("哈喽:" + name + " age= {}".format(age))
    

    匹配/分组算法:

    • 在⼀个匹配模式中要么使用命名分组,要么使用无命名分组,不能同时使⽤
    • 请求的URL被看做是⼀个普通的Python 字符串, URLconf在其上查找并匹
      配。进行匹配时将不包括GET或POST请求方式的参数以及域名。换句话讲,
      对同⼀个URL的无论是POST请求、GET请求、或HEAD请求⽅法等等 —— 都
      将路由到相同的函数。
    • 每个捕获的参数都作为⼀个普通的Python 字符串传递给视图,无论正则表达
      式使用的是什么匹配方式。

    2.视图

    视图本质上是⼀个函数(类)。这个函数第⼀个参数的类型是HttpReuest;它
    回⼀个 HttpResponse
    实例。为了使⼀个Python的函数成为⼀个Django可识别的
    视图,它必须满足这两个条件。

    • 作用:接收并处理请求,调用模型和模板,响应请求(返回HttpResponse或
      其子类)
      • 响应模板
      • 重定向
      • 直接响应字符串
      • 响应错误模板
      • json数据

    2.1 HttpRequest

    HttpRequest是从web服务器传递过来的请求对象,经过Django框架封装产生的,
    封装了原始的Http请求

    • 服务器接收到http请求后,django框架会自动根据服务器传递的环境变量创建
      HttpRequest对象
    • 视图的第⼀个参数必须是HttpRequest类型的对象
    • 在django.http模块中定义了HttpRequest对象的API
    • 使用HttpRequest对象的不同属性值,可以获取请求中多种信息
    属性 说明
    content-type 请求的mime类型
    GET ⼀个类似于字典的QueryDict对象,包含get请求方式的所有参
    数,也就是“?”后面的内容
    POST ⼀个类似于字典的QueryDict对象,包含post请求方式的所有参
    COOKIES ⼀个标准的Python字典,包含所有的cookie,键和值都为字符串
    SESSION ⼀个类似于字典的对象,表示当前的会话,只有当Django启用会
    话的支持时才可用
    PATH ⼀个字符串,表示请求的页面的完整路径,不包含域名
    method ⼀个字符串,表示请求使⽤的HTTP方法,常用值包括:GET、
    POST,
    FILES ⼀个类似于字典的QueryDict对象,包含所有的上传文件
    META 请求的请求头的源信息(请求头中的键值对)
    encoding 字符编码
    scheme 协议

    META中常用的键:

    说明
    HTTP_REFERER 来源页面
    REMOTE_ADDR 客户端ip
    REMOTE_HOST 客户端主机

    下面是常用的方法

    方法名 说明
    get_host() 获取主机名+端口
    get_full_path() 获取请求路径+查询字符串
    is_ajax() 如果是ajax请求返回True
    build_absolute_uri() 完整的url

    2.1.1 QueryDict

    QueryDict是Dict的子类,和Dict最大的不同是,值都是列表。用于存储从请求中
    传递过来的参数,例如对于表单中select、checkbox等多值参数,QueryDict⾮常
    合适。get、post、files请求都对应⼀个QueryDict

    • HttpRequest中QueryDict是不可变的,只能获取值,不能修改
    • QueryDict键值对都是字符串
    • QueryDict中⼀个键可以对应多个值
    #QueryDict
    {'hobby':['打篮球','玩游戏','k歌'],'name':['tom'],'age':'21'}
    
    • 常用操作
    # 1.判断get或post请求中包含指定键
    if 'name' in req.GET
     # to do
     
    # 2.获取get或post请求中指定键对应的单⼀值
     print(req.GET.get('name','⽆名'))
     print(req.GET['name'])
     #两种⽅式的区别,如果⽤下标,键不存在,则包keyerror,get⽅法则会得到默认值,如果没有默认值则返回None
     
    #3 获取指定键对应的多个值(列表)
     print(req.GET.getlist('name'))
    #4 获取所有键值对
     for x in req.GET.lists():
     	print(x)
    

    2.2 HttpResponse

    每⼀个视图函数必须返回⼀个响应对象,HttResponse对象由程序员创建并返回。

    属性 说明
    content 字节字符串
    charset 字符编码
    status_code http状态码
    content_type 指定输出的MIME类型

    2.2.1 不调用模板,直接返回内容

    def hello(req): 
    	return HttpResponse("hello world")
    def goodbye(req):
        res = HttpResponse()
        res.content = b'good bye'
        res.charset = "utf-8"
        res.content_type = 'text/html'
        return res
    

    2.2.2 调用模板返回

    ⼀般用render函数返回,render只是HttpResponse的包装,还是会返回⼀个
    HttpResponse对象

    def render_to_response(template_name, context=None, content_type=None,
    status=None, using=None):

    template_name : 模板名称。

    context: ⼀组字典的值添加到模板中。默认情况下,这是⼀个空的字典。

    content_type :MIME类型用于生成⽂档。

    status :为响应状态代码。默认值为200

    def studentlist(req):
         for key in req.GET.lists():
             print(key)
         allstudent = Student.objects.all()
         return render(req,'studentlist.html',context={'data':allstudent})
    
    • 常用方法:
      • write(content) 设置内容 == obj.content
      • set_cookie() 设置cookie
      • delete_cookie() 删除cookie

    2.3 JsonResponse

    JsonResponse 是HttpResponse的子类,用于向客户端返回json数据。⼀般用于
    ajax请求。它的content-type缺省值为:application/json

    from django.http import JsonResponse #导包
    
    class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True,
    json_dumps_params=None, **kwargs)
    参数:
         data:可以是字典,如果safe设置为False,也可以是json序列化对象
         encoder:编码格式,缺省是
        django.core.serializers.json.DjangoJSONEncoder
         safe:缺省是True,如果传递⾮字典给data,则报TypeError
    
    • 系统模块⾃带的json和JsonResponse
    from django.http import JsonResponse
    import json as myJson
    #返回json数据
    def json(req):
         jsonStr = JsonResponse({'name':'zhangsan','age':18})
         jsonStr = myJson.dumps({'name':'zhangsan','age':18})
         return HttpResponse(jsonStr)
    

    json.dumps给ajax返回数据以后 js代码中需要将json数据使用Json.parse() 进行解
    析成js对象 而JsonResponse会自动转换为js对象(少了异步Json.parse()的转换)

    • QuerySet转Json
    def courselist(req):
         courses = Course.objects.all() #QuerySet
         data = {'course':list(courses.values())} #查询结果集QuerySet转字典
         return JsonResponse(data) #传字典给JsonResponse
        # 返回数据格式
        {'course': [{'cname': '计算机组成原理', 'cid': 1}, {'cname': '英语',
        'cid': 2}, {'cname': '数学', 'cidame': 'c语⾔程序设计', 'cid': 4},
        {'cname': 'python从⼊⻔到精通', 'cid': 5}]}
        
        
    def courselist(req):
         courses = Course.objects.all()
         data = json.dumps(list(courses.values())) #查询结果集QuerySet转
        Json字符串,序列化
         return JsonResponse(data,safe=False) #safe必须设置为False
        # 返回的数据格式
        [{"cname": "u8ba1u7b97u673au7ec4u6210u539fu7406", "cid": 1},
        {"cname": "u82f1u8bed", "cid": 2}, {"cname": "u6570u5b66", "cid":
        3}, {"cname": "cu8bedu8a00u7a0bu5e8fu8bbeu8ba1", "cid": 4},
        {"cname": "pythonu4eceu5165u95e8u5230u7cbeu901a", "cid": 5}]
    
    • 模型转Json
    class Course(models.Model):
         cname = models.CharField(max_length=50)
         cid = models.AutoField(primary_key=True)
    
        # 给模型添加to_dict⽅法
         def to_dict(self):
         return dict([(key, self.__dict__[key]) for key in
        self.__dict__.keys() if key != "_state"])
    
        # 视图函数
        def courseshow(req):
         course = Course.objects.get(pk=1) # 返回的是对象,不是QuerySet
         return JsonResponse(course.to_dict())
    

    2.4 重定向

    当浏览器向server发送⼀个请求,要求获取⼀个资源时,在server接收到这个请求
    后发现请求的这个资源实际存放在另⼀个位置,于是server在返回的response中
    写⼊那个请求资源的正确的URL,并设置reponse的状态码为301(表示这是⼀个
    要求浏览器重定向的response),当client接受到这个response后就会根据新的
    URL重新发起请求。重定向有⼀个典型的特症,即:当⼀个请求被重定向以后,最
    终浏览器上显示的URL往往不再是开始时请求的那个URL了。这就是重定向的由
    来。

    HttpResponseRedirect是HttpResponse的子类,可以完成页面的重定向,当执行
    完特定动作或出现错误时,我们会希望执行的页面,如果判定用户没有登录则转到
    登录页面。重定向可以使用

    • HttpResponseRedirect
    • redirect(是HttpResponseRedirect的简写)

    使⽤时需要导入:from django.shortcuts import HttpResponseRedirect,
    reverse, redirect

    HttpResponseRedirect只⽀持硬编码url,不能直接使用命名url,在使⽤URL命名
    时,我们需要先通过URL反向解析方法reverse先对命名URL进行解析,然后再使
    用HttpReponseRedirect定向。

    2.4.1不带参数重定向

    #urls.py
    urlpatterns = [
     path('',views.index),
     re_path(r'^list/$',views.list_user),
     #redirect 重定向路由地址
     url(r'^redirect/$',views.Redirect)
    ]
    #views.py
    def index(req):
     	return render(req,'index.html')
    def list_user():
     
    	return HttpResponse("list user")
    def Redirect(req):
     
        # return redirect('http://localhost:9000/')
    
        # return redirect('/')
    
        return redirect("list/")
    

    2.4.2 带参数重定向

    #urls.py
    path('repath/<int:num>/', views.repath),
    re_path(r'^parameter/(?P<num1>d+)/(?P<num2>d+)/$',views.parameter),
    
    #views.py
    def repath(req,num):
         return redirect("parameter/3/5")
    def index(request):
         return HttpResponse("⾸⻚")
    def parameter(req,num1, num2):
         return HttpResponse("num1={},num2={}".format(num1,num2))
    
    

    2.4.3 反向解析

    根据namespace 和 name 查找真实路径:

    • namespace 在根url 包含子url时指定
    • name 在具体的函数后 指定, 子url指定
    # urls.py中
    app_name = 'App' # namespace 命名空间
    
    urlpatterns = [
         path('', views.index),
         path('para/<int:num1>/<int:num2>/'),
    ]
    #python代码中写法
    def repath(req):
         #res = reverse("App:index")
         # print(res,type(res))
         #return redirect(res)
         # path中参数或re_path中的位置参数,args可以是列表或元组
         # return redirect(reverse("App:para",args=(1,2)))
         # re_path中命名组,带关键字参数
         return redirect(reverse("App:para",kwargs={'num1':1,'num2':3}))
        
    # 模板中的写法:
    <h2><a href="/form/">展示表单</a></h2>
    <h2><a href="/index/">死链接⽆参的跳转</a></h2>
    <h2><a href="/args/1/2/">死链接带参的跳转</a></h2>
    <h2><a href="{% url 'App:index' %}">动态⽣成路由地址不带参的跳转</a>
    </h2>
    <h2><a href="{% url 'App:args1' 1 2 %}">动态⽣成路由地址带参的跳转</a>
    </h2>
    <h2><a href="{% url 'App:args1' num1=1 num2=2 %}">re_path中命名组,动
    态⽣成路由地址带关键字参数的跳转</a></h2>
    

    2.5 错误视图

    Django内置了处理HTTP错误的视图(在django.views.defaults包下),主要错误
    及视图包括:

    • 403错误:permission_denied (权限拒绝)
    • 400错误: bad_request (错误的请求)
    • 404错误:page_not_found (找不到指定文件)
    • 500错误:server_error (服务器内部错误)

    2.5.1 404错误及视图

    url匹配失败后,django会调用内置的 django.views.defaults.page_not_found()函
    数,该视图函数会调用 404.html的模板进⾏显示。开发阶段可以开启调试模式,
    但产品上线后,要关闭调试模式。关闭调试模式后,会显示⼀个标准的错误页面。

    # 在项⽬的settings配置⽂件中设置
    # 关闭调试模式(开发模式)
    DEBUG = False
    

    404错误界面可以自定义: 在项目templates目录面创建404.html,django找不到
    界面时,就会显示该界面了。缺省会传递参数request_path,就是出错的url

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <title>404 Not Found</title>
    </head>
    <body>
    <h2>对不起 您所访问的地址被外星⼈抓⾛了....</h2>
    <h4>请求的地址为 {{ request_path }}</h4>
    </body>
    </html>
    

    2.5.2 500错误及视图

    若是在执行视图函数时出现运行时错误,Django会默认会调用
    django.views.defaults.server_error 视图,加载并显示 500.html 模板,可以在项
    ⽬的templates目录下,创建500.html来自定义该界面。

    同理403和400都是一样的

    溜了,peace

  • 相关阅读:
    ocos 信号量
    C 语言 输入字符串 并计算输入的字符的长度
    C 语言简历一个文件夹 并自己输入字符 来取文件夹名字
    C语言 创建一个 txt 文件 bin输入字符 保存文件在工作文件夹里
    C语言 之 printf () 函数你真的会用吗?
    Impala的命令COMPUTE STATS
    python 函数eval
    YouTube排名第一的励志英文演讲《Dream(梦想)》
    impala 表迁移方式 partquet数据文件移动方法
    Python中@staticmethod和@classmethod的作用和区别
  • 原文地址:https://www.cnblogs.com/williamweson/p/13606784.html
Copyright © 2011-2022 走看看