文章目录
urls.py介绍
对于路由来说,urls.py至关重要,他负责告诉路由如何做,怎么样做,我们所有针对路由的操作基本都是在urls.py中完成的。官方有关urls的讲解
官方也进行了一些简单的实例(现在看不懂实例没关系,下面我们会对路由详细讲解,相信你看懂下方的讲解后,官方的实例对你来说就很容易看懂了)
功能视图
1. 添加导入: from my_app import views
2. 给 urlpatterns 添加一个 URL: path('', views.home, name='home')
基于类的视图
1. 添加导入: from other_app.views import Home
2. 给 urlpatterns 添加一个 URL: path('', Home.as_view(), name='home')
包括另一个 URLconf
1. 导入include()函数: from django.url import include,path
2. 给 urlpatterns 添加一个 URL: path('blog/', include('blog.urls'))
路由
最简单的路由
我们创建最简单的路由只需要引入两个库,分别是用来创建路由的path
与创建页面相应的HttpResponse
即可。如下,最简单的路由就创建完成了。我们再次打开页面(默认为127.0.0.1:8000)即可看到首页已经被"我的首页"所替代。
from django.urls import path
from django.http import HttpResponse
def home(request):
return HttpResponse("我的首页")
urlpatterns = [
path('', home)
]
跨文件路由
上述事例中,我们的页面就在路由中,但真实的情况下,我们不可能把所以页面都写在路由中,这里我们可以将页面写在不同的APP中统一导入我们的路由。我们只需把需要路由的文件引入即可
# 当前APP的app_demo中的views.py中代码为
from django.shortcuts import render
from django.http import HttpResponse
# 在此处创建视图。
def demo(request):
return HttpResponse('我是一个测试页面')
我们可以把这个文件添加进入我们的路由
# 主项目的urls.py中的代码为
from django.urls import path
from app_demo.views import demo
urlpatterns = [
path('demo', demo)
]
或使用下列方式添加效果和上方完全相同
# 主项目的urls.py中的代码为
from django.urls import path
from app_demo import views
urlpatterns = [
path('demo/', views.demo)
]
APP中内置路由
如果存在大量APP可能会导致命名冲突,因为每个APP中的视图页面默认都叫views.py,解决这个问题其实也很简单,只需要我们内置APP路由即可。我们需要在APP中自行创建一个urls.py
并在内部写入下列代码,即可
from django.urls import path
from . import views
urlpatterns = [
path('', views.demo)
]
在主项目的路由中,我们需要使用urls库中的include方法即可导入在APP中创建的urls
from django.urls import path, include
urlpatterns = [
path('demo/', include('app_demo.urls'))
]
传参
URL中传参也是非常重要的功能之一
简单传参
最简单的传参方式,我们只需要在视图函数中传入参数即可。
from django.urls import path
from django.http import HttpResponse
def home_page(request, home_id):
return HttpResponse("首页的第"+home_id+'页')
urlpatterns = [
path('<home_id>', home_page),
]
- 要从 URL 中取值,使用尖括号。
- 这里不需要添加反斜杠,因为每个 URL 都有。比如,应该是 demo 而不是 /demo。
路径转化器
默认情况下,我们可以接收任何形式的参数,但大多数时候,我们希望接收到的参数并不是任何形式都可以,比如说翻页的时候我们想要接收到纯数字的参数,或者我们想要接收纯文本、uuid等。路径转化器就是为此准备的。
假设我们现在想要接收一个纯数字的id和一个由 ASCII 字母或数字以及连字符和下划线组成的用户名,我们可以写成
from django.urls import path
from django.http import HttpResponse
def home_uid(request, home_id, home_name):
# <br>为HTML的换行符
return HttpResponse('用户的id:{}<br>用户姓名:{}'.format(home_id, home_name))
urlpatterns = [
path('<int:home_id>/<slug:home_name>', home_uid),
]
路径转换器 | 作用 |
---|---|
str | 匹配除了 ‘/’ 之外的非空字符串。(默认选项) |
int | 匹配0或任何正整数。返回一个 int 。 |
slug | 匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。比如,building-your-1st-django-site 。 |
uuid | 匹配一个格式化的 UUID 。为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写。 |
path | 匹配非空字段,包括路径分隔符 ‘/’ 。它允许你匹配完整的 URL 路径而不是像 str 那样匹配 URL 的一部分。 |
除了内置的这五个路径转化器外,你还可以自定义路径转化器,自定义路径转化器方法
正则表达式识别参数(re_path)
除了使用路径转化器来接收指定形式的参数,我们还可以使用re_path来识别参数,使用他之前,我们需要先将其导入from django.urls import re_path
命名正则表达式组的语法是 (?P<name>pattern)
,其中 name 是组名,pattern 是要匹配的模式。注意:?P\<name>
这里的必须写,并且P必须为大写。
from django.urls import re_path
from django.http import HttpResponse
def home_year(request, year):
return HttpResponse('当前是{}年'.format(year))
urlpatterns = [
re_path('year/(?P<year>(1|2)[0-9]{3})', home_year),
]
常用传参方式
我们在网站中见到的大部分传参都已?
问号后方携带参数,Django实现这种传参也相对容易,我们先假设一个需求,在app_demo这个APP中,我们需要多个以?
问号实现传参翻页的需求。
?
问号传参的关键是request.GET.get('参数名')
传参时,必须以指定的参数名传入的参数才能接收到,否则无法接收,比如我在app_demo/views.py中写入
from django.http import HttpResponse
def demo_page(request):
page = request.GET.get('data')
return HttpResponse('我第{}个测试页面'.format(page))
URL中的就必须写成http://127.0.0.1:8000/demo/page/?data=1
才能传入参数
如果想自行上述代码,需要在app_demo\urls.py中添加path('page/', views.demo_page)
,总路由中也要有path('demo/', include('app_demo.urls'))
指定默认参数
当一下特殊请求,直接进入指定网址后可能没有携带参数,这时候我们可以使用指定参数让页面正确的跳转到我们想要的地方
方法一: 我们可以直接在创建视图函数时候给参数一个默认值,这里需要注意的是,下方路由时需要给指定默认参数的页面多一个默认的路由。
from django.urls import path, include
from django.http import HttpResponse
def home_uid(request, home_id=1, home_name='xunmi'):
return HttpResponse('用户的id:{}<br>用户姓名:{}'.format(home_id, home_name))
urlpatterns = [
path('home', home_uid),
path('home/<int:home_id>/<slug:home_name>', home_uid),
]
方法二: 使用request.GET.get('参数名')
方式接受参数的时候,我们会发现,如果没有参数或接收失败,会返回一个None,我们可以给一个if语句判断返回值是否为None即可。
def demo_page(request):
page = request.GET.get('data')
if page is None:
page = 1
return HttpResponse('我第{}个测试页面'.format(page))
重定向
如果页面中,我们接收到了错误的参数,如果不作为,那么页面很可能会出现404等错误信息。为了降低404的出现,我们可以做一些简单的判断,让错误的id被重定向。这时候就需要用到redirect
这个方法,比如说下列代码中就用到重定向将参数输入错的也页面定向到上一层。
from django.shortcuts import render, redirect
from django.http import HttpResponse
# 在此处创建视图。
def demo(request):
return HttpResponse('我是测试页面')
def demo_page(request):
page = request.GET.get('data')
if page:
return HttpResponse('我第{}个测试页面'.format(page))
else:
return redirect('../')
当前路由
from django.urls import path
from . import views
urlpatterns = [
path('', views.demo),
path('page/', views.demo_page)
]
URL 的反向解析
上述代码中,我们的URL往往都是被写死在代码中的,要是出现一个在网站中多次被引用的的URL突然需要我们修改,这会是一个很麻烦的工作,并且可能会因为漏改造成网页错误跳转引起bug。URL翻转就是为了解决此问题所诞生的,URL反转也非常简单,只需要在设置页面路由的时候在path()
中添加name属性,并在使用的的时候添加reverse
方法即可(在django.shortcuts
库中,这个库也是创建APP时携带的viwes.py中会带的)
应用命名空间
在path中添加name即可比如path('home/', home_uid, name='index')
,在应用命名空间时,直接使用此命名即可,比如说反转的时候调用,直接输入reverse('index')
即可
from django.urls import path
from django.http import HttpResponse
from django.shortcuts import render, redirect, reverse
def home(request):
data = request.GET.get('id')
print(data)
if data:
return redirect(reverse('index'))
else:
return HttpResponse("我的首页")
def home_uid(request, home_id=1, home_name='xunmi'):
return HttpResponse('用户的id:{}<br>用户姓名:{}'.format(home_id, home_name))
urlpatterns = [
path('', home),
path('home/', home_uid, name='index'),
path('home/<int:home_id>/<slug:home_name>', home_uid),
path('demo/', demo),
]
注: 应用命名空间与include
不能同时存在,比如path('demo/', include('app_demo.urls'), name='index')
此语句中的name就会失效。(如果上述情况我们想命名,可以去app_demo/urls.py
中添加name)
实例命名空间
我们在使用include时候为了防止多个APP中出现了一样的页面造成命名冲突,还可以在自定义的urls.py中添加命名空间。我们可以在使用include的时候使用命名空间,不过命名空间用的最多的情况是反转(反向解析)的时候,当我们反转设置比较多的时候,可能就会造成冲突,且默认反转是去APP本身的路由和项目总路由中寻找name,如果name存在在其他APP中,直接寻找就无法找到
# 在app_demo.py中添加
app_name = 'demo'
# 在使用include读取路由的时候添加demo
path('demo/', include('app_demo.urls', 'demo')),
# 使用反转(反向解析)添加命名空间
reverse('demo:index')
URL携参反转
可以直接在reverse()
反转中添加kwargs
属性即可比如return redirect(reverse('page', kwargs={'page': 1}))
如果需要使用带?
问号的参数,可以用字符串拼接的方式,如下
from django.shortcuts import render, redirect, reverse
from django.http import HttpResponse
# Create your views here.
def copy(request):
# data = request.GET.get('id')
uid = request.GET.get('id')
if uid:
# 常规已反斜线形式传参
# return redirect(reverse('page', kwargs={'page': data}))
# 已?形式传参
data = reverse('copy:uid')+'?id='+uid
return redirect(data)
else:
return redirect(reverse('page', kwargs={'page': 1}))
def copy_page(request, page):
return HttpResponse('我是第{}页'.format(page))
def copy_uid(request):
uid = request.GET.get('id')
return HttpResponse('我的id是{}'.format(uid))
此路由为
from django.urls import path
from . import views
app_name = 'copy'
urlpatterns = [
path('', views.copy),
path('page/<page>', views.copy_page, name='page'),
path('uid/', views.copy_uid, name='uid')
]