URL视图

视图

一般写在appviews.py中。视图的第一个参数必须是request(一个HttpResponse)对象。此对象存储了请求的所有信息,包括携带的参数以及一些头部信息。在视图中,一般完成逻辑相关的操作。视图返回的结果必须是HttpResponseBase对象或者其子类对象。
【例】

from django.http import HttpResponse
def index(request):
return HttpResponse("首页")

URL映射

1.在settings.py中配置的ROOT_URLCONF为django寻找映射的位置

2.在urls.py中所有的映射放在urlpatterns变量中

URL参数

URL传递参数

1.在url中使用变量方式:在path函数的第一个参数中,添加<参数名>方式,然后在对应的视图函数中添加命名相同的参数。url中可以传递多个参数。

【例】访问http://127.0.0.1:8000/book/1/

urls.py代码

from django.contrib import admin
from django.urls import path
from book import views

urlpatterns = [
path('admin/', admin.site.urls),
path('book/', views.book_list),
path('book/<book_id>/', views.book_detail)
]

views.py代码

def book_detail(request, book_id):
text = "书籍id为:%s" % book_id
return HttpResponse(text)

2.查询字符串方式:不需要单独匹配查询字符串,只需要在视图函数中使用request.GET.get('参数名称')的方式来获取。

【例】访问http://127.0.0.1:8000/book/author/?id=1

urls.py代码

...
urlpatterns = [
...
path('book/author/', views.author_detail)
]

views.py代码

def author_detail(request):
author_id = request.GET['id']
text = '作者的id为:%s' % author_id
return HttpResponse(text)

指定默认参数

应用场景
# 第一页 http://example.com/
# 第二页 http://example.com/page/2
# 第三页 http://example.com/page/3

如果没有传递page参数,指定 默认的page参数

# URL(in blog/urls.py)
from django.urls import path

from . import views

urlpatterns = [
path('blog/', views.page),
path('blog/page/<int:num>', views.page)
]

# View(in blog/views.py)
def page(request, num=1):
# 根据传入的num返回对应的页面
return HttpResponse("第%s页" % num)

url参数转换器

可以去django.urls import converters中具体查看

  • str/以外所有字符
  • int 一个或多个数字
  • path 所有字符
  • uuid 满足uuid.uuid4()格式的字符串
  • slug 满足[-a-zA-Z0-9_]+格式的字符串

urls模块化

如果项目越来越大。url会越来越多。如果都放在主urls.py文件中,会变得难以管理。因此可以将每个app的urls放在自己的项目下管理。一般在app中新建一个urls.py文件用来存储所有和此app相关的子url。

【例】子urls.py文件

from django.urls import path
from . import views

urlpatterns = [
path('', views.book),
path('detail/<book_id>', views.book_detail),
]

urls.py文件

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
path('book/', include('book.urls')),
path('admin/', admin.site.urls),
]

注意:url是根据主urls.py和app中的urls.py各自path中的第一个参数进行拼接的,注意不要多加/

url命名

为什么需要url命名

url是经常变化的。如果在代码中写死可能会经常修改代码。给url取个名字,以后使用url时只要将url命名反转即可。

如何给url指定名称

path函数中,传递name参数。

【例】

from django.urls import path
from . import views

urlpatterns = [
path('', views.index, name='index'),
path('signin/', views.login, name='login')
]
from django.urls import reverse
url = reverse('login') # /signin/

应用命名空间

防止当多个app中出现同名的url时,反转url会产生混淆。

【例】

# 应用命名空间
app_name = 'front'

urlpatterns = [
path('', views.index, name='index'),
path('signin/', views.login, name='login')
]
from django.urls import reverse

url = reverse('front:login') # /signin/

实例命名空间

必须先指定应用命名空间app_name

防止当多个url映射同一个app时会发生混淆。

【例】

urlpatterns = [
path('cms1/', include('cms.urls', namespace='cms1')),
path('cms2/', include('cms.urls', namespace='cms2'))
]

url反转时可以根据实例命名空间来指定具体的url

def index(request):
current_namespace = request.resolver_match.namespace
return redirect(reverse(f"{current_namespace}:login"))

include函数详解

  1. include(module, namespace=None)
    • module:子url的模块字符串
    • namespace:实例命名空间。前提必须先指定应用命名空间(在子urls.py中添加app_name变量)
  2. include((pattern_list, app_namespace), namespace=None)
    • pattern_list:子urls.py模块的字符串
    • app_namespace:应用命名空间
  3. include(pattern_list)
    • pattern_list:由path()或者re_path()实例构成的可迭代序列

reverse函数

1.添加参数,可以使用kwargs参数

detail_url = reverse('detail', kwargs={"article_id": 1, "page": 2})

2.查询字符串参数,手动拼接

login_url = reverse('login') + '?next=/'

自定义URL(PATH)转换器

需求

实现一个获取文章列表demo,用户可以根据articles/文章分类/的方式获取文章。其中文章分类采用分类1+分类2+分类3...方式进行拼接。示例如下

# 1.获取python分类下的文章
# /articles/python/

# 2.获取python和django分类下的文章
# /articles/python+django/

文章分类参数传到视图函数之前将这些分类分开存储到列表中。在使用reverse反转url时,限制传递文章分类参数为一个列表,并且将列表中的参数转变回原本的url样式。

实现

urls.py文件

from django.urls import re_path
from django.urls import converters, register_converter

from . import views

class CategoryConverter:
regex = '\w+|(\w+\+\w+)+'

def to_python(self, value):
return value.split('+')

def to_url(self, value):
assert type(value) == list
return '+'.join(value)

register_converter(CategoryConverter, 'cate')

urlpatterns = [
path('', views.article),
path('list/<cate:categories>', view.article_list, name='list'),
]

优化

在app下新建一个converters.py文件,将上面urls.py文件中转换器相关的代码放到converters.py文件中(由于该代码并没有执行,所以无法使用cate转换器),在app下的__init__.py文件中导入from . import converters (app相当于一个包,每次导入app时,会自动执行__init__.py文件中的代码)