百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Django:URL调度器(三)(url csdn)

toyiye 2024-09-19 04:45 3 浏览 0 评论

URL 是 Uniform Resource Locator 的简写,统一资源定位符。 一个 URL 由以下几部分组成: scheme://host:port/path/?query-string=xxx#anchor

  • scheme:代表的是访问的协议,一般为 http 或者 https 以及 ftp 等。
  • host:主机名,域名,比如 https://www.toutiao.com 。
  • port:端口号。当你访问一个网站的时候,浏览器默认使用80端口。
  • path:查找路径。比如: https://docs.python.org/zh-cn/3/tutorial/venv.html ,后面的 zh-cn/3/tutorial/venv.html 就 是 path 。
  • query-string:查询字符串,比如: www.baidu.com/s?wd=python ,后面的 wd=python 就是查 询字符串。
  • anchor:锚点,后台一般不用管,前端用来做页面定位的。

注意: URL 中的所有字符都是 ASCII 字符集,如果出现非 ASCII 字符,比如中文,浏览器会进行编码再进行传输。

视图

视图一般都写在 app 的 views.py 中。并且视图的第一个参数永远都是request(一个HttpRequest)对象。这个对象存储了请求过来的所有信息,包括携带的参数以及一些头部信息等。在视图中,一般是完成逻辑相关的操作。比如这个请求是添加一篇博客,那么可以通过request来接收到这些数据,然后存储到数据库中,最后再把执行的结果返回给浏览器。视图函数的返回结果必须是HttpResponseBase 对象或者子类的对象。示例代码如下:

from django.http import HttpResponse
?
def articles_list(request):
    return HttpResponse("文章列表!")

URL映射

视图写完后,要与URL进行映射,也即用户在浏览器中输入什么 url 的时候可以请求到这个视图函数。在用户输入了某个 url ,请求到我们的网站的时候, django 会从项目的 urls.py 文件中寻找对应的视图。在 urls.py 文件中有一个 urlpatterns 变量,以后 django 就会从这个变量中读取所有的匹配规则。匹配规则需要使用 django.urls.path 函数进行包裹,这个函数会根据传入的参数返回 URLPattern 或者是 URLResolver 的对象。示例代码如下:

from django.contrib import admin
from django.urls import path
from articles import views
?
urlpatterns = [
 ? ?path('admin/', admin.site.urls),
 ? ?path('articles/',views.articles_list)
]

URL中添加参数

有时候, url 中包含了一些参数需要动态调整。比如今日头条某篇文章的详情页的url,是 https://www.toutiao.com/i6779587855070003726/后面的 i6779587855070003726 就是这篇文章的 id ,那么今日头条的文章详情页面的url就可以写成https://www.toutiao.com/<id> ,其中id就是文章的id。那么如何在 django 中实现这种需求呢。这时候我们可以在 path 函数中,使用尖括号的形式来定义一个参数。比如我现在想要获取一篇文章的详细信息,那么应该在 url 中指定这个参数。示例代码如下:

from django.contrib import admin
from django.urls import path
from articles import views
?
urlpatterns = [
 ? ?path('admin/', admin.site.urls),
 ? ?path('articles/',views.articles_list),
 ? ?path('articles/<articles_id>/',views.articles_detail)
]

而 views.py 中的代码如下:

def articles_detail(request, articles_id):
 ? ?# 通过articles_id接收传入的参数
 ? ?text = "您输入的文章的id是:%s" % articles_id
 ? ?return HttpResponse(text)

当然,也可以通过查询字符串的方式传递一个参数过去。示例代码如下:

urlpatterns = [
 ? ?path('admin/', admin.site.urls),
 ? ?path('articles/',views.articles_list),
 ? ?path('articles/detail/',views.articles_detail)
]

在 views.py 中的代码如下:

def articles_detail(request):
 ? ?articles_id = request.GET.get("id")
 ? ?text = "您输入的文章id是:%s" % articles_id
 ? ?return HttpResponse(text)

以后在访问的时候就是通过 /articles/detail/?id=1 即可将参数传递过去。

被包含的URLconf 会收到来自父URLconf 捕获的任何参数,所以下面的例子是合法的:

# In settings/urls/main.py
from django.urls import include, path
?
urlpatterns = [
 ? ?path('<username>/blog/', include('foo.urls.blog')),
]
?
# In foo/urls/blog.py
from django.urls import path
from . import views
?
urlpatterns = [
 ? ?path('', views.blog.index),
 ? ?path('archive/', views.blog.archive),
]

在上面的例子中,捕获的 "username" 变量将被如期传递给include()指向的URLconf

包含其它的URLconfs

在我们的项目中,不可能只有一个 app ,如果把所有的 app 的 views 中的视图都放在 urls.py 中进行映射,肯定会让代码显得非常乱。因此 django 给我们提供了一个方法,可以在 app 内部包含自己的 url 匹配规则,而在项目的 urls.py 中再统一包含这个 app 的 urls 。 使用这个技术需要借助 include 函数。示例代码如下:

# django_study1/urls.py文件:
from django.contrib import admin
?
from django.urls import path,include
urlpatterns = [
 ? ?path('admin/', admin.site.urls),
 ? ?path('articles/',include("articles.urls"))
]


在 urls.py 文件中把所有的和 articles 这个 app 相关的 url 都移动到 app/urls.py 中了,然后在 django_study1/urls.py 中,通过 include 函数包含 articles.urls ,以后在请求 articles 相关的url的时候都需要加一个 articles 的前缀。

# articles/urls.py文件:
from django.urls import path
from . import views
 ? ?urlpatterns = [
 ? ?path('list/',views.articles_list),
 ? ?path('detail/<articles_id>/',views.articles_detail)
]

以后访问书的列表的 url 的时候,就通过 /articles/list/ 来访问,访问文章详情页面的 url 的时候就通过 articles/detail/<id> 来访问。


include这种方法可以用来去除URLconf 中的冗余,其中某个模式前缀被重复使用。例如,考虑这个URLconf:

from django.urls import path
from . import views
?
urlpatterns = [
 ? ?path('<page_slug>-<page_id>/history/', views.history),
 ? ?path('<page_slug>-<page_id>/edit/', views.edit),
 ? ?path('<page_slug>-<page_id>/discuss/', views.discuss),
 ? ?path('<page_slug>-<page_id>/permissions/', views.permissions),
]

我们可以改进它,通过只声明共同的路径前缀一次并将后面的部分分组:

from django.urls import include, path
from . import views
?
urlpatterns = [
 ? ?path('<page_slug>-<page_id>/', include([
 ? ? ? ?path('history/', views.history),
 ? ? ? ?path('edit/', views.edit),
 ? ? ? ?path('discuss/', views.discuss),
 ? ? ? ?path('permissions/', views.permissions),
 ?  ])),
]


path函数

path 函数的定义为:path(route,view,name=None,kwargs=None)。以下对这几个参数进行讲解。

  1. route 参数: url 的匹配规则。这个参数中可以指定 url 中需要传递的参数,比如在访问文章详情页的时候,可以传递一个 id 。传递参数是通过 <> 尖括号来进行指定的。并且在传递参数的时候,可以指定这个参数的数据类型,比如文章的 id 都是 int 类型,那么可以这样写<int:id> ,以后匹配的时候,就只会匹配到 id 为 int 类型的 url ,而不会匹配其他的 url ,并且在视图函数中获取这个参数的时候,就已经被转换成一个 int 类型了。其中还有几种常用的类型:str:匹配除了 '/' 之外的非空字符串。如果表达式内不包含转换器,则会默认匹配字符串。int:匹配0或任何正整数。返回一个 int 。slug:匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。比如,building-your-1st-django-site 。uuid:匹配一个格式化的 UUID 。为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写。比如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID 实例。path:匹配非空的英文字符串,可以包含斜杠。
  2. view 参数:可以为一个视图函数或者是 类视图.as_view() 或者是 django.urls.include()函数的返回值。
  3. name 参数:这个参数是给这个 url 取个名字的,这在项目比较大, url 比较多的时候用处很大。
  4. kwargs 参数:有时候想给视图函数传递一些额外的参数,就可以通过 kwargs 参数进行传递。这个参数接收一个字典。传到视图函数中的时候,会作为一个关键字参数传过去。比如以下的 url 规则:
 ?from django.urls import path
 ?from . import views
?
 ?urlpatterns = [
    path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
  ]

那么以后在访问 blog/1991/ 这个url的时候,会将 foo=bar 作为关键字参数传给 year_archive 函数。

re_path函数

有时候我们在写url匹配的时候,想要写使用正则表达式来实现一些复杂的需求,那么这时候我们可以使用 re_path 来实现。 re_path 的参数和 path 参数一模一样,只不过第一个参数也就是 route 参数可以为一个正则表达式。 一些使用 re_path 的示例代码如下:

from django.urls import path, re_path
from . import views
?
?
urlpatterns = [
 ? ?path('articless/2020/', views.special_case_2020),
 ? ?re_path(r'articless/(?P<year>[0-9]{4})/', views.year_archive),
 ? ?re_path(r'articless/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/', views.month_archive),
 ? ?re_path(r'articless/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-_]+)/', views.articles_detail),
]

以上例子中我们可以看到,所有的 route 字符串前面都加了一个 r ,表示这个字符串是一个原生字符串。在写正则表达式中是推荐使用原生字符串的,这样可以避免在 python 这一层面进行转义。而且,使用正则表达式捕获参数的时候,是用一个圆括号进行包裹,然后这个参数的名字是通过尖括号 <year>进行包裹,之后才是写正则表达式的语法。

include函数

在项目变大以后,经常不会把所有的 url 匹配规则都放在项目的 urls.py 文件中,而是每个 app 都有自己的 urls.py 文件,在这个文件中存储的都是当前这个 app 的所有 url 匹配规则。然后再统一注册到项目的 urls.py 文件中。 include 函数有多种用法,这里讲下两种常用的用法。

  1. include(pattern,namespace=None):直接把其他 app 的 urls 包含进来。示例代码如下:
 from django.contrib import admin
 from django.urls import path,include
?
?
 urlpatterns = [
 ? ? ? path('admin/', admin.site.urls),
 ? ? ? path('articles/',include("articles.urls"))
 ]

也可以传递 namespace 参数来指定一个实例命名空间,但是在使用实例命名空间之前,必须先指定一个应用命名空间。示例代码如下:

# 主urls.py文件:
from django.urls import path,include
?
?
	urlpatterns = [
  path('movie/',include('movie.urls',namespace='movie'))
]

然后在 movie/urls.py 中指定应用命名空间。实例代码如下:

from django.urls import path
from . import views
?
# 应用命名空间
app_name = 'movie'
?
?
urlpatterns = [
	path('',views.movie,name='index'),
	path('list/',views.movie_list,name='list'),
]
  1. include(pattern_list):可以包含一个列表或者一个元组,这个元组或者列表中又包含的是 path 或者是 re_path 函数。
  2. include((pattern,app_namespace),namespace=None):在包含某个 app 的 urls 的时候,可以指定命名空间,这样做的目的是为了防止不同的 app 下出现相同的 url ,这时候就可以通过命名空间进行区分。示例代码如下:
from django.contrib import admin
from django.urls import path,include
?
?
urlpatterns = [
	path('admin/', admin.site.urls),
	path('articles/',include(("articles.urls",'articles')),namespace='articles')
]

但是这样做的前提是已经包含了应用命名空间。即在myapp.urls.py中添加一个和 urlpatterns 同级别的变量 app_name。


指定默认的参数

使用 path 或者是 re_path 的后,在 route 中都可以包含参数,而有时候想指定默认的参数,这时候可以通过以下方式来完成。示例代码如下:

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):
 ? ?# Output the appropriate page of blog entries, according to num.
 ?  ...

当在访问 blog/ 的时候,因为没有传递 num 参数,所以会匹配到第一个url,这时候就执行 view.page 这个视图函数,而在 page 函数中,又有 num=1 这个默认参数。因此这时候就可以不用传递参数。而如果访问 blog/1 的时候,因为在传递参数的时候传递了 num ,因此会匹配到第二个 url ,这时候也会执行 views.page ,然后把传递进来的参数传给 page 函数中的 num 。

URL 的反向解析

之前我们都是通过url来访问视图函数。有时候我们知道这个视图函数,但是想反转回他的url。这时候就可以通过 reverse 来实现。

Django 提供执行反转 URL 的工具,这些工具与需要 URL 的不同层匹配:

  • 在模板里:使用 url 模板标签。
  • 在 Python 编码:使用 reverse() 函数。
  • 在与 Django 模型实例的 URL 处理相关的高级代码中: get_absolute_url() 方法。
reverse("list")
> /articles/list/

如果有应用命名空间或者有实例命名空间,那么应该在反转的时候加上命名空间。示例代码如下:

reverse('articles:list')
> /articles/list/

如果这个url中需要传递参数,那么可以通过 kwargs 来传递参数。示例代码如下:

reverse("articles:detail",kwargs={"articles_id":1})
> /articles/detail/1

因为 django 中的 reverse 反转 url 的时候不区分 GET 请求和 POST 请求,因此不能在反转的时候添加查询字符串的参数。如果想要添加查询字符串的参数,只能手动的添加。示例代码如下:

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

自定义URL转换器

之前已经学到过一些django内置的 url 转换器,包括有int、 uuid等。有时候这些内置的 url转换器 并不能满足我们的需求,因此django给我们提供了一个接口可以让我们自己定义自己的url转换器。 自定义 url 转换器按照以下五个步骤来走就可以了:

  1. 定义一个类。
  2. 在类中定义一个属性 regex ,这个属性是用来保存 url 转换器规则的正则表达式。
  3. 实现to_python(self,value)方法,这个方法是将 url 中的值转换一下,然后传给视图函数 的。
  4. 实现 to_url(self,value)方法,这个方法是在做 url 反转的时候,将传进来的参数转换后拼 接成一个正确的url。
  5. 将定义好的转换器,注册到django中。

比如写一个匹配四个数字年份的 url 转换器。示例代码如下:

# 1. 定义一个类
class FourDigitYearConverter:
 ? ?# 2. 定义一个正则表达式
 ? ?regex = '[0-9]{4}'
 ? ?
 ? ?# 3. 定义to_python方法
 ? ?def to_python(self, value):
 ?      return int(value)
 ? ?
 ? ?# 4. 定义to_url方法
 ? ?def to_url(self, value):
 ?      return '%04d' % value

在 URLconf 中使用 register_converter() 来注册自定义的转换器类:

# 5. 注册到django中
from django.urls import register_converter
?
register_converter(converters.MyUrl, 'yyyy')
urlpatterns = [
 ? ?path('articless/2020/', views.special_case_2020),
 ? ?# 使用注册的转换器
 ? ?path('articless/<yyyy:year>/', views.year_archive),
...
]

官方文档:https://docs.djangoproject.com/zh-hans/3.0/topics/http/urls/

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码