July's Blog

花有重开日,人无再少年

0%

django笔记02 - 视图和url

视图函数

  1. 第一个参数必须是request
  2. 返回值必须是django.http.response.HttpResponseBase的子类的对象
1
2
3
4
from django.http import HttpResponse

def book(request):
return HttpResponse('图书首页')

urls.py

settings.py文件中配置了ROOT_URLCONFurls.py,所以会在这个文件中寻找映射
路径和视图函数对应

1
2
3
4
5
6
7
8
9
10
11
12
from django.contrib import admin
from django.urls import path
from book import views

urlpatterns = [
path('admin/', admin.site.urls),
path('book/', views.book),
# /book/detail/1/
path('book/detail/<book_id>/<category_id>/', views.book_detail),
path('book/author/', views.author_detail),
path('book/publisher/<int:publisher_id>/', views.publisher_detail),
]

url传递参数

  1. urls.py文件,<参数名>传递,默认使用str转换器,如<int:publisher_id>。视图函数中,参数名要和它一致
  2. 查询字符串的方式,访问浏览器时参数如?id=2http://127.0.0.1:8000/book/author/?id=2
  3. 转换器:int,path,slug,str,uuid
1
2
3
4
5
def author_detail(request):
author_id = request.GET.get('id')
#author_id = request.GET['id'] #这种写法也可以,GET类似字典,获取值方式与字典相同
text = '作者的id是:%s' % author_id
return HttpResponse(text)

url映射时指定默认参数

views.py中,可以给函数指定默认参数,url中没有传递的话,使用默认参数

1
2
def books(request, page=0):
return HttpResponse(book_list[page])

url参数内置的转换器

  1. str:除了/以外的所有字符
  2. int:一个或多个数字
  3. path:所有字符
  4. uuid:只有满足uuid.uuid4()函数返回的字符串格式
  5. slug:-_,英文字母,数字任意组合

自定义url(path)转换器

  1. 定义一个类,直接继承自object就可以了
  2. 在类中定义一个属性regex,这个属性是用来保存url转换器规则的正则表达式
  3. 实现to_python(self, value)方法,作用是将url中的值转换一下,然后传给视图函数
  4. 实现to_url(self, value)方法,作用是在做url反转时,将传进来的参数转换后拼接成一个正确的url
  5. 将定义好的转换器,使用django.urls.converters.register_converter方法注册到django中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django.urls import converters, register_converter

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

def to_python(self, value):
# python+django+flask
# ['python', 'django', 'flask']
result = value.split('+')
return result

def to_url(self,value):
# value: ['python', 'django', 'flask']
# python+django+flask
if isinstance(value, list):
result = '+'.join(value)
return result
else:
raise RuntimeError('转换url时,分类参数必须为列表')

# 注册
register_converter(CategoryConverter, 'cate')

:可以将以上代码单独存为converters.py文件,在__init__.py中导入,from . import converters,自动执行

urls模块化

  1. 主url对app的url引用,将url进行拼接,注意/,只写在末尾
1
2
3
4
5
6
7
8
#主url
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('book/',include('book.urls'))
]
  1. app中的url单独放在自己的urls.py文件中,如下面名为的book的app
1
2
3
4
5
6
7
8
9
10
#app的url
from django.urls import path
from . import views

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

url命名

url经常变换,取个名字,调用时用reverse('name')进行反转,方便调用修改等

1
2
3
4
5
6
7
from django.urls import path
from . import views

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

应用(app)命名空间

多个app中,有可能出现同名的url,避免混淆,使用应用命名空间。
appurls.py中,定义一个叫app_name的变量。

1
2
3
4
5
6
7
8
9
from django.urls import path
from . import views

app_name = 'front' #命名空间

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

反转时使用应用命名空间:url名称

1
login_url = reverse('front:login')

实例命名空间

一个app,可以创建多个实例,可以用多个url映射同一个app。为了避免在url反转时发生混淆,使用实例命名空间。
在项目根目录的urls.py文件中,在include函数中传递一个namespace变量即可。

1
2
3
4
5
6
urlpatterns = [
path('', include('front.urls')),
#同一个app下有两个实例
path('cms1/', include('cms.urls',namespace='cms1')),
path('cms2/', include('cms.urls',namespace='cms2')),
]

在url反转时,根据实例命名空间来指定具体的url。

1
2
3
4
5
6
7
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))

include函数

根目录urls.py中,path()

  1. include(module, namespace=None)
  • module:子url的模块字符串

  • namespace:实例命名空间,需先指定应用命名空间。即在子urls.py中添加app_name变量

    path('cms1/', include('cms.urls',namespace='cms1'))

  1. include((pattern_list, app_namespace), namespace=None)

    元组(tuple)第一个参数是urls.py模块字符串,第二个参数是应用命名空间。
    应用命名空间,可以在子urls.py中通过app_name指定,也可以在include函数中指定。

    path('book/', include(('book.urls', 'book'), namespace='book'))

  2. include(pattern_list)

    pattern_list是一个列表,元素为pathre_path

1
2
3
4
path('movie/', include([
path('', views.movie),
path('list/', views.movie_list),
]))

re_path

  1. 推荐使用原生字符串,即r开头的字符串
  2. 定义的变量,需要用()括起来,?P<参数的名字>,后面添加正则表达式规则
  3. 优先用path
1
2
3
4
5
6
7
8
9
from django.urls import re_path
from . import views

urlpatterns = [
re_path('^$', views.article),
# /article/list/<year>/
re_path(r'^list/(?P<year>\d{4})/$', views.article_list),
re_path(r'^list/(?P<month>\d{2})/$', views.article_list_month),
]

reverse()

  1. 反转url时,如果需要添加参数,使用kwargs参数传递
1
2
3
from django.shortcuts import redirect, reverse

detail_url = reverse('detail', kwargs={'article_id':1, 'page':2})
  1. 如果添加查询字符串的参数,必须手动进行拼接
1
login_url = reverse('login') + '?next=/'
请作者喝冰阔落