【Django】 02.URL

视图函数(FBV):

1.视图函数第一个参数必须是request,这个参数绝对不能少。

2.视图函数的返回值必须是django.http.response.HttpResponseBase的子类的对象

  • 视图函数映射关系写在项目下的url.py文件下

  • 视图函数的具体内容写在app下的views.py文件下

视图类(CBV):

  1. 创建视图类需继承django.views.View类

  2. 在url.py映射关系下,若指定映射为视图类需要调用类的as.view()方法

  3. 类方法中要加request参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
### view.py
from django.shortcuts import render, HttpResponse
from django.views import View

class Index(View):
# get方法访问时调用
def get(self, request):
return HttpResponse('get')
# post方法访问时调用
def post(self, request):
return HttpResponse('post')

### url.py
from django.urls import path
from app01 import views

urlpatterns = [
# 调用as_view()方法,表示映射的是类
path('', views.Index.as_view()),
]

url传参数:

1.url需要传参可以在path的url中<参数名>的形式加入参数,参数名与视图函数的参数对应。可传递多个参数。

  • 指定参数类型(其实是将进行url转换)<int:publisher_id>指定参数为int类型,输入其他类型会找不到页面

  • 默认是str转换器,其他转换器还有int,slug,uuid,path

    • str:[^/] 除了/
    • int:[0-9]
    • slug:[-0-9a-zA-Z_]
    • path:.+
    • uuid

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

1
2
3
4
def author_detail(request):
author_id = request.GET.get('id')
text = '作者的id是%s' % author_id
return HttpResponse(text)

在浏览器输入url时http://127.0.0.1:8000/book/author/?id=1需要在链接后跟?[参数名]=[内容]

映射模块化–include函数:

1.为了便于管理,将一个app的url链接放在app模块下,在主url.py文件中通过include函数拼接url。

1
2
3
4
urlpatterns = [
path('admin/', admin.site.urls),
path('book/', include('book.book_urls'))
]

2.在app文件下的url.py中,url也要放在urlpatterns的变量下。

3.url会根据主urls.py和app中的url.py文件进行拼接

url命名:

1.为什么要对url命名:
url是经常变换的,一个url的改变会引起很多url的改变,为了减少修改代码的工作量

2.如何命名:path函数中,传递一个name参数

1
2
3
4
urlpatterns = [
path('', views.index, name='index'),
path('login/', views.login, name='login')
]

3.应用命名空间:解决不同app间name重名问题

  • app内的urls.py中定义app_name变量

1
2
3
4
5
6
app_name = 'front'

urlpatterns = [
path('', views.index, name='index'),
path('login/', views.login, name='login')
]

以后在做反转(revese)的时候就可以使用app_name:name的方式进行反转

1
login_url = reverse('front:login')

4.实例命名空间:解决同一app下不同实例url访问问题

使用应用命名空间:
- cms1 --> cms1/login
- cms2 --> cms1/login
使用实例命名空间:    
- cms1 --> cms1/login
- cms2 --> cms2/login
  • include函数中传递namespace参数

1
2
3
4
5
6
7
8
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('front.urls')),

# 同一个app下的两个实例
path('cms1/', include('cms.urls', namespace='cms1')), # namespace定义实例命名空间
path('cms2/', include('cms.urls', namespace='cms2'))
]

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

1
2
3
4
5
6
7
8
def index(request):
username = request.GET.get('username')
if username:
return HttpResponse('CMS首页')
else:
# 获得访问页面的实例命名
current_namespace = request.resolver_match.namespace
return redirect(reverse('%s:login' % current_namespace))

re_path函数:

1.re_path和path的作用一样,不过re_path在写url时可用正则表达式。

2.在正则表达式中若有参数,要用圆括号括起来,参数名字使用?P<name>的方式,再在后面添加正则规则。

1
2
3
4
5
6
urlpatterns = [
path('', views.index),
re_path(r'list/(?P<year>\d{4})', views.article_list_y),
re_path(r'list/(?P<month>\d{2})', views.article_list_m)
]

reverse()反转:

1.如果反转的url带有参数,可以传递参数给kwarg参数。

1
2
3
4
5
6
7
def index(request):
username = request.GET.get('username')
if username:
return HttpResponse('图书首页')
else:
detail_url = reverse('detail', kwargs={'article_id': 1})
return redirect(detail_url)

2.如果反转的函数带有查询字符串,只能手动拼接。

1
2
3
4
5
6
7
def index(request):
username = request.GET.get('username')
if username:
return HttpResponse('图书首页')
else:
login_url = reverse('login') + '?next=/'
return redirect(login_url)

自定义url转换器:

1.定义一个类

2.在类中定义regex属性,用来限制url转换器的规则

3.类中定义to_python(self,value)函数,这个方法是用来将url中的值转换后传递给视图函数

4.实现to_url(self,value)方法,这个方法是在url做反转的时候,将传进来的参数转换后拼接成一个正确的url

5.将定义好的转换器注册到django中

1
2
# converters.register_converter(类名, '调用时的命名')
converters.register_converter(CategoryConverter, 'cate')

定义转换器实例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from django.urls import converters


# converter的写法,照着源码改就行
class CategoryConverter:
regex = r'\w|(\w+\+\w+)+'

# to_python 是用在path路径转换时
def to_python(self, value):
# value : python + django + flask
result = value.split('+')
return result

# to_url是用在反转(reverse)时
def to_url(self, value):
# value : [python, django, flask]
if isinstance(value, list):
return '+'.join(value)
else:
raise RuntimeError('转换url时出错')

# 注册到django
converters.register_converter(CategoryConverter, 'cate')
  • 若要把转换器写到独立的py文件中,要在包的__init__文件中import一下该文件。(import时会执行文件内容,把自定义的转换器注册到django中,__init__.py文件是初始化文件,默认执行)

url映射时指定默认参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
urlpatterns = [
path('', views.books),
path('page/<int:page>',views.books)
]


# views.py
book_list = [
'三国演义',
'水浒传',
'红楼梦',
'西游记'
]
def books(request, page=1):
return HttpResponse(book_list[page-1])

在访问path('', views.books)的时候因为没有参数传递,会用views.books的默认参数1,在访问 path('page/<int:page>',views.books)时,传递了参数,则用传递的参数。


【Django】 02.URL
http://blog.rainna.xyz/2020/11/22/2020-11-22-02.URL/
作者
rainnalv
发布于
2020年11月22日
许可协议