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

原文地址:https://www.cnblogs.com/williamweson/p/13606784.html