2019-08-06 Django从 URL获取参数的几种方式
URL也就是网址了,是django所有视图函数的门面,通过它才能进入纷繁复杂的django世界,下面根据官方文档总结一下URL获取参数的集中方式
url配置的根节点是 ROOT_URLCONF,这个配置是在项目的settings.py文件里,一般当你创建完项目后这个配置就自动出现在settings文件里而它的值就是项目名.urls, 知道这个配置你就可以任意修改url配置的根路径。上面这是普遍的情况,如果使用了某些中间件,那么请求HttpRequest本身可能会带有urlconf参数,这时候我们设置的urlconf就会被覆盖。
找到ROOT_URLCONF后,django加载这个模块,查找其中的变量urlpatterns,这个变量是一个list数据类型,而list里元素的类型因版本不同会有差异,django版本2.0之前使用的是django.conf.urls.url()对象,2.0及以后使用的是django.urls.path()和 django.urls.re_path(),
在1.X时代,只有django.conf.urls.url(),形式如下:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
这种类型的urlpattern都是使用正则表达式匹配的,如果需要获取参数,可以把对应的正则表达式部分放到括号里,
比如请求/articles/2005/03/,就会匹配到上面第三条,因为有两个括号,所以就会有两个参数,实际调用的视图函数方式为:views.month_archive(request, '2005', '03'),这种类型的参数叫unamed group参数,在写视图函数的时候有两种写法:
#第一种
def month_archive(request,year_p,month_p):
print(year_p,month_p)
...
#第二种
或者第二种可变参数形式:
def month_archive(request,*args):
year=args[0]
month=args[1]
...
这种参数也叫位置参数positional arguments
(注意:/articles/2005/3/ 这种请求不会匹配上面任一种url,因为位数不对)
上面这种叫unamed group,那必然有一种叫named group,这种匹配的参数叫关键字参数keyword arguments.
这种urlpattern写法为:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
可见相比于第一种,第二种在前面增加了?P<year>部分,这就可以给获取到的参数取个名字放在字典里了,
例如:/articles/2005/03/ 这种url调用的函数就是: views.month_archive(request, year='2005', month='03')
视图里获取这种参数的形式为:
#第一种
def month_archive(request,year,month):
print(year,month)
...
**注意这里的参数名year和month必须和url里定义的参数名一致,不然会报错,这和unamed group的位置参数不一样
#第二种
def month_archive(request,**kwargs):
print(kwargs['year'],kwargs['month'])
...
上面这些是django 1.X版本的写法,到了2.X版本,django不仅提供了正则表达式匹配,还有常规的匹配,具体来说就是把1.X里的url()匹配改成了re_path(),而普通的字符串匹配用的是path(),正则表达式匹配re_path()的用法和1.X里的url()一样,下面看一下path()匹配的用法示例:
from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
可见新的写法看上去更加简练了,获取参数的形式变成了中括号<>,这里面的第一个参数叫转换器converter ,第二个参数就是变量名了,注意在1.X版本里获取的变量都是字符串类型,这在2.X版本你不同,2.X可以定义变量的类型,使用的就是转换器converter ,例如这里的int就是将获取的参数转化成数字型传给视图直接用,django内置的转换器有如下几种:
-
str
- Matches any non-empty string, excluding the path separator,'/'
. This is the default if a converter isn’t included in the expression. -
int
- Matches zero or any positive integer. Returns an <cite>int</cite>. -
slug
- Matches any slug string consisting of ASCII letters or numbers, plus the hyphen and underscore characters. For example,building-your-1st-django-site
. -
uuid
- Matches a formatted UUID. To prevent multiple URLs from mapping to the same page, dashes must be included and letters must be lowercase. For example,075194d3-6885-417e-a8a8-6c931e272f00
. Returns aUUID
instance. -
path
- Matches any non-empty string, including the path separator,'/'
. This allows you to match against a complete URL path rather than just a segment of a URL path as withstr
.
django同样赋予了开发者自定义转换器的功能,这里不做介绍,详见https://docs.djangoproject.com/en/2.1/topics/http/urls/#registering-custom-path-converters
上面介绍的是从urlpattern里获取参数,是django内置实现的,还有一种是从HTTP请求里获取参数:
常见的是GET和POST请求,这里的参数被封装在请求request里,GET请求的数据在request.GET里,POST的请求放在request.POST里
对于GET请求,一般参数直接出现在url里,如domain/search/?q=haha ,可以用request.GET.get('q')或request,GET['q']获取到q参数,POST请求的数据不会出现在url里。
一般我们获取参数使用request.GET.get('xx','')/request.POST.get('xx','')的形式,get函数的第二个参数是当没有xx参数时返回的默认值