视图
视图可以在项目的urls.py中编写,但一般都写在app的views.py中。
需要注意的是:
- 视图的第一个参数永远都是request(一个HttpRequest)对象。
- 这个对象存储了请求过来的所有信息,包括携带的参数以及一些头部信息等。
- 这个对象存储了请求过来的所有信息,包括携带的参数以及一些头部信息等。
- 视图函数的返回结果,必须是HttpResponseBase对象或者子类的对象。
定义视图
- 在项目的urls.py中编写: ```python from django.contrib import admin from django.urls import path, include from django.http import HttpResponse from movie import views # 导入创建的app
“”” 1、必须传参request 2、返回值必须为HttpResponse “””
定义视图
def index(request): return HttpResponse(“Hello World”)
def movie(request): return HttpResponse(“电影页面”)
URL映射
urlpatterns = [ path(‘admin/‘, admin.site.urls), path(‘’, index), path(‘movie/‘, movie),
# path('movie/', views.movie)
]
- 在app的views.py中编写:
```python
from django.http import HttpResponse
def movie(request):
# raise ValueError
return HttpResponse("电影页面")
URL映射
视图定义完后,要与URL进行映射。即用户在访问某个URL,请求到网站时,django会从项目的urls.py文件中寻找对应的视图。
在urls.py文件中有一个 urlpatterns
变量,django会从这个变量中读取所有的匹配规则。匹配规则需要使用 django.urls.path
函数进行包裹,其会根据传入的参数返回 URLPattern
或者是 URLResolver
的对象。
# URL映射
urlpatterns = [
path('admin/', admin.site.urls),
path('', index),
path('movie/', movie),
# path('movie/', views.movie)
]
urls官网手册:https://docs.djangoproject.com/en/3.0/ref/urls/
URL中添加参数
有时候,url中包含了一些参数需要动态调整。一般有两种传参方式:直接传参和关键字传参。
比如,想要获取电影的第几页,传参方式如下:
直接传参:http://127.0.0.1:8000/movie_list/3/2
关键字传参:http://127.0.0.1:8000/movie_type/?name=爱情片
定义视图:
from django.http import HttpResponse
# Create your views here.
def movie(request):
# raise ValueError
return HttpResponse("电影页面")
'''直接传参'''
def movie_list(request, mid, uid):
# raise ValueError
return HttpResponse("电影第 %s 页, 动作片第 %s 页" % (mid, uid))
'''关键字传参'''
def movie_type(request):
# request.GET其中GET会返回一个字典
type_name = request.GET.get('name')
return HttpResponse("电影类型是 %s" % type_name)
URL映射:
# URL访问格式:http://127.0.0.1:8000/movie/3/1
urlpatterns = [
path('admin/', admin.site.urls),
path('', index),
path('movie/', mviews.movie),
# 直接传参
path('movie_list/<mid>/<uid>', mviews.movie_list),
# 关键字传参
path('movie_type/', mviews.movie_type)
]
URL模块化
在Django项目中,不可能只有一个app,如果把所有的app的views中的视图,都放在urls.py中进行映射,肯定会让代码显得非常乱。
因此,django提供了一个方法,可以在app内部包含自己的url匹配规则,然后在项目的urls.py中再统一包含这个app的urls,若要实现该方式,需要导入 include
函数。
定义app视图:
from django.http import HttpResponse
# Create your views here.
def book(request):
# raise ValueError
return HttpResponse("图书页面")
def book_detail(request):
# raise ValueError
res = request.GET.get('id')
return HttpResponse("图书第 %s 页" % res)
创建app的urls.py文件:
from django.urls import path
from . import views
urlpatterns = [
path('', views.book), # 表示book/
# http://127.0.0.1:8000/book/detail/?id=2
path('detail/', views.book_detail) # 表示book/detail/
]
在urls.py文件中,把所有和book这个app相关的url都移动到app/urls.py中。
项目的urls文件:
from django.contrib import admin
from django.urls import path, include # 导入include
urlpatterns = [
path('admin/', admin.site.urls),
# URL模块化
path('book/',include("book.urls"))
]
通过include函数包含book.urls,以后再请求book相关的url时,都需要加一个book的前缀。
include其他用法
可以直接指定应用命名空间,以代替定义app_name。
include(module, namespace=None)
include(pattern_list)
include((pattern_list, app_namespace), namespace=None)
Django内置转换器
通过正则表达式来进行规则匹配,内置转换器包含int、str、uuid和path。
from django.urls import converters
UUID的使用:https://www.cnblogs.com/franknihao/p/7307224.html
内置转换器的使用:
urlpatterns = [
path('admin/', admin.site.urls),
path('', index),
path('movie/', mviews.movie),
# 限制传入参数的类型
path('movie_list/<int:mid>/<str:uid>', mviews.movie_list)
URL命名与反转
- 1.为什么需要URL命名?
因为在项目开发的过程中,URL地址可能经常变动,如果写死会经常去修改。给url取个名字,以后进行反转时,使用url的名字即可,无需关心URL是什么。 - 2.如何给一个URL指定名称?
path("",views.index,name="index")
- 3.应用命名空间
在多个app之间可能产生同名的URL,为了避免这种情况,可以使用命名空间来加以区分。需在app的urls.py中添加app_name
。
新建两个app:
$ python manage.py startapp cms
$ python manage.py startapp front
'''项目的urls.py文件'''
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("front.urls")),
path('cms/', include("cms.urls")),
]
URL命名与反转
'''views.py'''
def index(request):
name = request.GET.get('name')
if name:
return HttpResponse('前台页面首页,name是 %s' % name)
else:
"""重定向到login"""
# return redirect('login/')
# 反转,参数login对应urls中的name值
return redirect(reverse('login'))
'''url.py'''
urlpatterns = [
# 使用name给URL命名
path('', views.index, name="index"),
# path('login/', views.login, name="login"),
# 若使用反转,url名称变动,不影响url映射
path('signin/', views.login, name="login")
]
应用命名空间
'''views.py'''
def index(request):
name = request.GET.get('name')
if name:
return HttpResponse('前台页面首页,name是 %s' % name)
else:
# 使用应用命名空间,指定跳转的app url
return redirect(reverse('front:login'))
'''urls.py'''
# 定义应用命名空间
app_name = 'front'
urlpatterns = [
# 使用name给URL命名
path('', views.index, name="index"),
# path('login/', views.login, name="login"),
# 若使用反转,url名称变动,不影响url映射
path('signin/', views.login, name="login")
]
实例命名空间
一个app可以创建多个实例,可以使用多个URL映射同一个App。在做反转时,如果使用应用命名空间,就会发生混淆,为了避免这个问题,可以使用实例命名空间。
使用 namespace
定义实例命名空间:
'''项目的urls.py文件'''
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("front.urls")),
path('cms/', include("cms.urls")),
# 实例命名空间
path('cms1/', include("cms.urls", namespace='cms1')),
path('cms2/', include("cms.urls", namespace='cms2')),
]
'''app的views.py文件'''
from django.shortcuts import redirect, reverse
from django.http import HttpResponse
# Create your views here.
def index(request):
# 查看当前访问的实例命名空间
current_namespace = request.resolver_match.namespace
print(current_namespace)
return HttpResponse('后台页面首页')
URL反转传递参数
如果这个url中需要传递参数,那么可以通过 kwargs
来传递参数。
reverse("book:detail",kwargs={"book_id":1})
因为django中的reverse反转url时,不区分GET请求和POST请求,因此不能在反转的时候,添加查询字符串的参数。如果想要添加查询字符串的参数,只能手动的添加。
login_url = reverse("front:singin") + "?name=jr"
return redirect(login_url)
示例:
- app的views.py文件: ```python from django.shortcuts import render, redirect, reverse from django.http import HttpResponse
Create your views here.
def index(request): “””查看当前访问的实例命名空间””” current_namespace = request.resolver_match.namespace print(current_namespace)
# return HttpResponse('后台页面首页')
"""url反转传参"""
# 默认反转的URL:http://127.0.0.1:8000/cms/login/2/
return redirect(reverse('cms:admin', kwargs={'lid': 2})) # 直接传参
# return redirect(reverse('cms:login') + '?name=Rick') # 关键字传参
def admin(request, lid): return HttpResponse(‘后台管理页面, id是 %s’ % lid)
def login(request): name = request.GET.get(‘name’) return HttpResponse(‘后台登录页面, name是 %s’ % name)
2. app的urls文件:
```python
from django.urls import path
from . import views
# 定义应用命名空间
app_name = 'cms'
urlpatterns = [
path('', views.index, name="index"),
path('login/', views.login, name='login'),
path('admin/<lid>/', views.admin, name='admin')
]
指定默认参数
"""views.py"""
from django.http import HttpResponse
def admin(request, lid=1): # 默认参数
return HttpResponse('后台管理页面, id是 %s' % lid)
"""urls.py"""
from django.urls import path
from . import views
urlpatterns = [
path('admin/', views.admin, name='admin'), # 接收默认参数
path('admin/<lid>/', views.admin, name='admin') # 传递指定参数
]
re_path正则匹配URL
使用re_path正则表达式可以实现一些复杂的URL规则匹配需求,re_path的参数和path参数一模一样,只不过第一个参数,也就是route可以为一个正则表达式。
"""views.py"""
from django.http import HttpResponse
def birthday_year(request, year):
return HttpResponse('您的生日年份是%s' % year)
"""urls.py"""
from django.urls import path, re_path
from . import views
# re_path()和url()都能达到同样的正则匹配效果
from django.conf.urls import url
urlpatterns = [
# ?P<year>为传参固定格式
re_path(r'byear/(?P<year>\d{4})$', views.birthday_year)
]