Django----路由层

一、路由匹配

urls.py

from django.conf.urls import url

urlpatterns = [
     url(正则表达式, views视图函数,参数,别名)
]

参数说明:

  • 正则表达式:一个正则表达式字符串
  • views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
  • 参数:可选的要传递给视图函数的默认参数(字典形式)
  • 别名:一个可选的name参数

注意事项

  1. urlpatterns中的元素**按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续**。
  2. 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
  3. 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
  4. 每个正则表达式前面的’r’ 是可选的但是建议加上。

补充说明

# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项APPEND_SLASH=True

Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加’/’

访问 http://www.example.com/blog 时,默认将网址自动转换为 http://www.example/com/blog/

如果在settings.py中设置了 APPEND_SLASH=False,此时我们再请求 http://www.example.com/blog 时就会提示找不到页面

不同Django版本路由层的区别

1.x的版本

from django.urls import url
urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
"""
括号内参数--第一个是一个匹配用的正则表达式,第二个是对应视图函数
当项目特别大,路由特别多的时候需要注意路由顶替的问题
"""

使用^限制以什么开头,使用$限制以什么结尾

2.x及以后的版本

from django.urls import path, re_path
urlpatterns = [
    path('admin/', admin.site.urls),
]
"""
括号内参数--第一个不再是正则表达式,第一个参数写什么就是什么
re_path 跟url相同
第二个是对应视图函数
"""

并且提供了5种内置转换器,会将匹配的内容,当做关键字参数对应给视图函数中的形参入参,也可以自定义转换器

#1、五个内置转化器
	- str:匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
    - int:匹配正整数,包括0
    - slug:匹配字母、数字、下划线以及横杠组成的字符串
    - uuid:匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00
    - path:匹配任何非空字符串,包含了路径分隔符(/),不能用"?"
        
#2、示例:
	- path('login/<int:year>', views.login),
    - path('login/<str:name>', views.login),
    - path('login/<path:p>',views.article),
#3、自定义转换器
"参考:https://codeleading.com/article/13424069936/"

二、分组命名匹配

2.1 无名分组

urlpatterns = [
     url(正则表达式, views视图函数,参数,别名)
]

由于第一个参数是‘正则表达式’,那么就可以给正则的条件加上(),进行分组

urlpatterns = [
    url(r'^test/(\d+)/',views.test)
]

views.py

def test(request):
    return HttpResponse('test url')

在这里插入图片描述

会发现,多传入了一个位置>参数

views.py

def test(request, a):
    return HttpResponse(f'test url,{a}')

在这里插入图片描述
在这里插入图片描述

无名分组----路由匹配时,如果对正则表达式进行分组,那么会传入除了request参数外,还会分组后匹配到的内容

2.2 有名分组

有名分组其实就是对正则表达式分组之后,对分组的内容起了个别名

同时传入视图函数的时候,需要特定这个别名的关键字参数来接受

urlpatterns = [
    url(r'^test/(?P<user_id>\d+)/',views.test)
]

views.py

形参中必须要有 正则表达式分组起了别名的 关键字参数

def test(request, user_id):
    return HttpResponse(f'test url,{user_id}')

无名分组和有名分组不能在一个url中混用,但是可以某种类型重复使用

 

2.3 传递额外的参数给视图函数

URLconfs 具有一个钩子,让你传递一个Python 字典作为额外的参数传递给视图函数。

django.conf.urls.url() 函数可以接收一个可选的第三个参数,它是一个字典,表示想要传递给视图函数的额外关键字参数。

例如:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

在这个例子中,对于/blog/2005/请求,Django 将调用views.year_archive(request, year='2005', foo='bar')

三、命名URL和URL反向解析

3.1 命名 URL

通过name属性来命名,注意:多个 URL 命名是不可以重复的

urlpatterns = [
    url(r'^home/', views.home, name= 'home'),
]

那么,给 URL 命名的应用场景是什么?

 

3.2 URL反向解析–前端

urls.py中给某个路径的后缀起了别名之后;

在模板 (HTML文件)中 就可以直接根据{% url'别名' %}直接拿到起别名的路径,而不是手动拼接路径!!

这样做的好处在于,如果有修改url的时候,就不需要手动到 模板文件中 一个一个地修改了

示例:
urlpatterns = [
    url(r'^home/', views.home, name= 'home_view'),
  	url(r'^index/', views.index, name= 'index_view'),
]

views.py

from django.shortcuts import render, HttpResponse, redirect

def home(request):
  
  return render(request, 'home.html')

def index(request):
  return HttpResponse('from index')

home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href="/index/">点我!要你好看</a>
    <a href="{% url 'index_view' %}">点点点!!!!!</a>
</body>
</html>

此时修改urls.py

urlpatterns = [
    url(r'^home/', views.home, name= 'home_view'),
  	url(r'^index666/', views.index, name= 'index_view'),
]

会发现反向解析的链接,能够自动解析新的路径!!

 

3.3 URL反向解析–后端

方式一:reverse模块

views.py文件

# 模块导入
from django.shortcuts import redirect, reverse


def func(request):
    _url = reverse('index_view')

    return redirect(f'{_url}')

urls.py

urlpatterns = [
    url(r'^home/', views.home, name= 'home_view'),
  	url(r'^index/', views.index, name= 'index_view'),
  	url(r'^func/', views.func, name= 'func_view'),
]

结果:

“GET /func/ HTTP/1.1” 302 0
“GET /index/ HTTP/1.1” 200 10

方式二:

views.py文件

# 模块导入
from django.shortcuts import redirect


def func(request):
		# 可以直接写别名,也会自动跳转
    return redirect('index_view')

“GET /func/ HTTP/1.1” 302 0
“GET /index/ HTTP/1.1” 200 10

3.4 无名分组反向解析

urlpatterns = [
    url(r'^test/(\d+)/',views.test,name='test_view'),
]
def test(request,a):
  	res = reverse('index_view')
    print(res)
    return HttpResponse('from test')

在这里插入图片描述

url中对正则表达式进行分组之后,视图函数反向解析出/test/之后,需要继续做后缀的匹配,如果不给一个确切的值的话,那么/test/1//test/2//test/666/都符合匹配规则,所以视图函数还需要一个参数来匹配/test/之后的参数

后端语法:

def test(request,a):
  	res = reverse('index_view', args=(666,))
    print(res)
    return HttpResponse('from test')

结果展示为:/test/666/

如果无名分组有多个,那么在args括号内一次传入多个即可

前端模板语法:

{% url 'index_view' 666 %}

3.5 有名分组反向解析

urlpatterns = [
    url(r'^test/(?P<user_id>\d+)/',views.test,name='test_view'),
]

后端语法:

def test(request, user_id):
  	res = reverse('index_view', kwargs={'user_id':666, })
    print(res)
    return HttpResponse('from test')

前端模板语法

{% url 'index_view' user_id=666 %}

四、路由分发

当一个项目的应用非常多时,在urls.py文件中urlpatterns列表中的路由会非常多,这样会导致非常不好管理路由,这时考虑将一个urls.py文件拆分开,每一个应用单独新建一个urls,py,通过总的路由文件对每个应用的路由文件进行统筹管理

子路由中的路由配置还是按照之前的方式,但是总路由的配置需要改变

导入模块include

#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.

#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:


from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^app01/', include('app01.urls')),  # 可以包含其他的URLconfs文件
 	 url(r'^app02/', include('app02.urls')),  # 可以包含其他的URLconfs文件
]

路由匹配时,如果匹配到/app01/会直接到app01.urls.py文件中去继续做路由匹配

五、名称空间

Django 项目中有两个应用–app01app02,分别有其各自的urls.py

如果两个项目都有一个url(r'^index/',views.index,name='index_view'), 即多个应用出现路由命名冲突的情况!

此时,index_view这个别名进行反向解析时,能够解析出是属于app01的,还是app02的呢?

直接说结论:当一个项目中有相同的路由命名,只会识别到最后一个起了这个名字的路由,其他的相同命名的路由,无法被反向解析出来

解决办法:在总路由进行路由分发的时候,给每个应用进行命名空间namesapce=的起别名操作

from django.conf.urls import include, url

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls',namespace='app01')),
    url(r'^app02/', include('app02.urls',namespace='app02')),
]

这样在各自的视图函数进行反向解析的时候会有不同的提示

在这里插入图片描述

其实,该问题的解决方法还可以在给路由重命名时,加上应用的前缀app01_index_view这样可以不使用名称空间,同样达到相同的效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Django-Channels 是一个基于 Django 框架的 WebSocket 库,用于实现实时应用程序。要发送 WebSocket 消息,您可以按照以下步骤进行操作: 1. 在 Django-Channels 的 consumer 中定义一个 WebSocket 处理函数,例如: ```python from channels.generic.websocket import AsyncWebsocketConsumer import json class MyConsumer(AsyncWebsocketConsumer): async def connect(self): await self.accept() async def disconnect(self, close_code): pass async def receive(self, text_data): text_data_json = json.loads(text_data) message = text_data_json['message'] await self.send(text_data=json.dumps({ 'message': message })) ``` 2. 在前端代码中创建 WebSocket 连接并发送消息,例如: ```javascript const socket = new WebSocket('ws://localhost:8000/ws/my_consumer/'); socket.onopen = function(event) { console.log('WebSocket is connected.'); }; socket.onmessage = function(event) { console.log('Message received:', event.data); }; socket.onclose = function(event) { console.log('WebSocket is closed.'); }; const message = { 'message': 'Hello, world!' }; socket.send(JSON.stringify(message)); ``` 在这个例子中,我们创建了一个 WebSocket 连接,并将消息发送到 `MyConsumer` consumer 中。当 `MyConsumer` consumer 接收到消息时,它将发送一个响应消息回到前端,前端代码将在 `onmessage` 回调函数中接收到响应消息并在控制台中打印出来。 注意,在生产环境中,您应该将 WebSocket 连接配置为使用 HTTPS 而不是 HTTP,并使用适当的身份验证和授权方法来保护您的应用程序。 ### 回答2: Django-Channels是一个用于构建实时Web应用程序的库,它支持使用WebSocket进行实时通信。在Django-Channels中,我们可以使用`channels.layers`模块来发送socket消息。 首先,我们需要在Django的设置文件中配置Channels。我们需要添加Channels的应用,并设置`ASGI_APPLICATION`为我们的应用名称。如下所示: ```python INSTALLED_APPS = [ ... 'channels', ] ASGI_APPLICATION = 'myproject.routing.application' ``` 接下来,我们需要创建一个routing.py文件来配置Channels路由。在这个文件中,我们可以定义消息路由的处理函数。示例如下: ```python from channels.routing import ProtocolTypeRouter, URLRouter from myapp import consumers application = ProtocolTypeRouter({ 'websocket': URLRouter([ url(r'^ws/myapp/(?P<room_name>\w+)/$', consumers.ChatConsumer), ]), }) ``` 然后,我们可以创建一个消费者类来处理接收到的消息,并使用Channels的`channels.layers`模块发送socket消息。在这个类中,我们可以重写`connect`、`disconnect`、`receive`等方法来处理连接、断开连接和接收消息的逻辑。以下是一个简单的示例: ```python from channels.generic.websocket import AsyncWebsocketConsumer from channels.layers import get_channel_layer from asgiref.sync import async_to_sync class MyConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = self.scope['url_route']['kwargs']['room_name'] self.room_group_name = 'chat_%s' % self.room_name await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() async def disconnect(self, close_code): await self.channel_layer.group_discard( self.room_group_name, self.channel_name ) async def receive(self, text_data): await self.channel_layer.group_send( self.room_group_name, { 'type': 'chat_message', 'message': text_data } ) async def chat_message(self, event): message = event['message'] await self.send(text_data=message) ``` 最后,我们可以在需要发送socket消息的地方,使用`channel_layer`模块获取channel对象,并使用其`group_send`方法来发送消息。以下是一个简单的示例: ```python from channels.layers import get_channel_layer from asgiref.sync import async_to_sync channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)( 'chat_room', { 'type': 'chat_message', 'message': 'Hello, World!' } ) ``` 以上是使用Django-Channels发送socket消息的基本实现代码。当有客户端连接到我们定义的WebSocket路由时,将会触发对应的消费者类方法,并通过`channel_layer`发送消息给指定的群组或客户端。 ### 回答3: Django-Channels是一个基于Django的扩展,用于为Web应用程序添加实时功能。它可以通过WebSocket协议发送和接收消息。以下是一个使用Django-Channels发送socket的代码示例: 首先,安装Django-Channels和其依赖项。可以使用pip命令来安装: ``` pip install channels ``` 然后,将Channels添加到您的Django项目的`INSTALLED_APPS`中。在您的项目的`settings.py`文件中进行如下配置: ```python INSTALLED_APPS = [ ... 'channels', ... ] ``` 接下来,创建一个名为`consumers.py`的文件,用于定义处理WebSockets连接的消费者: ```python from channels.generic.websocket import WebsocketConsumer class MyConsumer(WebsocketConsumer): def connect(self): # 连接成功时调用 self.accept() def disconnect(self, close_code): # 断开连接时调用 pass def receive(self, text_data): # 接收到来自客户端的消息时调用 pass def send_message(self, text_data): # 向客户端发送消息 self.send(text_data) ``` 在您的Django项目的`routing.py`文件中,配置将传入的WebSocket连接传递给相应的消费者: ```python from django.urls import path from . import consumers websocket_urlpatterns = [ path('ws/my-consumer/', consumers.MyConsumer.as_asgi()), ] ``` 最后,在您的Django项目的`settings.py`文件中启用Channels: ```python ASGI_APPLICATION = 'myapp.routing.application' ``` 现在,您可以在任何视图或其他地方使用以下代码来向客户端发送WebSocket消息: ```python from asgiref.sync import async_to_sync from channels.layers import get_channel_layer channel_layer = get_channel_layer() def send_socket_message(message): async_to_sync(channel_layer.group_send)('my-group', { 'type': 'send_message', 'text': message }) ``` 这将向名称为`my-group`的组中的所有客户端发送消息。 以上就是使用Django-Channels发送socket的代码实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值