视图

视图可以在项目的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),

  1. # path('movie/', views.movie)

]

  1. - appviews.py中编写:
  2. ```python
  3. from django.http import HttpResponse
  4. def movie(request):
  5. # raise ValueError
  6. return HttpResponse("电影页面")

URL映射

视图定义完后,要与URL进行映射。即用户在访问某个URL,请求到网站时,django会从项目的urls.py文件中寻找对应的视图。
在urls.py文件中有一个 urlpatterns 变量,django会从这个变量中读取所有的匹配规则。匹配规则需要使用 django.urls.path 函数进行包裹,其会根据传入的参数返回 URLPattern 或者是 URLResolver 的对象。

  1. # URL映射
  2. urlpatterns = [
  3. path('admin/', admin.site.urls),
  4. path('', index),
  5. path('movie/', movie),
  6. # path('movie/', views.movie)
  7. ]

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=爱情片

定义视图:

  1. from django.http import HttpResponse
  2. # Create your views here.
  3. def movie(request):
  4. # raise ValueError
  5. return HttpResponse("电影页面")
  6. '''直接传参'''
  7. def movie_list(request, mid, uid):
  8. # raise ValueError
  9. return HttpResponse("电影第 %s 页, 动作片第 %s 页" % (mid, uid))
  10. '''关键字传参'''
  11. def movie_type(request):
  12. # request.GET其中GET会返回一个字典
  13. type_name = request.GET.get('name')
  14. return HttpResponse("电影类型是 %s" % type_name)

URL映射:

  1. # URL访问格式:http://127.0.0.1:8000/movie/3/1
  2. urlpatterns = [
  3. path('admin/', admin.site.urls),
  4. path('', index),
  5. path('movie/', mviews.movie),
  6. # 直接传参
  7. path('movie_list/<mid>/<uid>', mviews.movie_list),
  8. # 关键字传参
  9. path('movie_type/', mviews.movie_type)
  10. ]

URL模块化

在Django项目中,不可能只有一个app,如果把所有的app的views中的视图,都放在urls.py中进行映射,肯定会让代码显得非常乱。
因此,django提供了一个方法,可以在app内部包含自己的url匹配规则,然后在项目的urls.py中再统一包含这个app的urls,若要实现该方式,需要导入 include 函数。

定义app视图:

  1. from django.http import HttpResponse
  2. # Create your views here.
  3. def book(request):
  4. # raise ValueError
  5. return HttpResponse("图书页面")
  6. def book_detail(request):
  7. # raise ValueError
  8. res = request.GET.get('id')
  9. return HttpResponse("图书第 %s 页" % res)

创建app的urls.py文件:

  1. from django.urls import path
  2. from . import views
  3. urlpatterns = [
  4. path('', views.book), # 表示book/
  5. # http://127.0.0.1:8000/book/detail/?id=2
  6. path('detail/', views.book_detail) # 表示book/detail/
  7. ]

在urls.py文件中,把所有和book这个app相关的url都移动到app/urls.py中。

项目的urls文件:

  1. from django.contrib import admin
  2. from django.urls import path, include # 导入include
  3. urlpatterns = [
  4. path('admin/', admin.site.urls),
  5. # URL模块化
  6. path('book/',include("book.urls"))
  7. ]

通过include函数包含book.urls,以后再请求book相关的url时,都需要加一个book的前缀。

include其他用法

可以直接指定应用命名空间,以代替定义app_name。

  1. include(module, namespace=None)
  2. include(pattern_list)
  3. include((pattern_list, app_namespace), namespace=None)

Django内置转换器

通过正则表达式来进行规则匹配,内置转换器包含int、str、uuid和path。

  1. from django.urls import converters

UUID的使用:https://www.cnblogs.com/franknihao/p/7307224.html

内置转换器的使用:

  1. urlpatterns = [
  2. path('admin/', admin.site.urls),
  3. path('', index),
  4. path('movie/', mviews.movie),
  5. # 限制传入参数的类型
  6. 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:

  1. $ python manage.py startapp cms
  2. $ python manage.py startapp front
  3. '''项目的urls.py文件'''
  4. urlpatterns = [
  5. path('admin/', admin.site.urls),
  6. path('', include("front.urls")),
  7. path('cms/', include("cms.urls")),
  8. ]

URL命名与反转

  1. '''views.py'''
  2. def index(request):
  3. name = request.GET.get('name')
  4. if name:
  5. return HttpResponse('前台页面首页,name是 %s' % name)
  6. else:
  7. """重定向到login"""
  8. # return redirect('login/')
  9. # 反转,参数login对应urls中的name值
  10. return redirect(reverse('login'))
  11. '''url.py'''
  12. urlpatterns = [
  13. # 使用name给URL命名
  14. path('', views.index, name="index"),
  15. # path('login/', views.login, name="login"),
  16. # 若使用反转,url名称变动,不影响url映射
  17. path('signin/', views.login, name="login")
  18. ]

应用命名空间

  1. '''views.py'''
  2. def index(request):
  3. name = request.GET.get('name')
  4. if name:
  5. return HttpResponse('前台页面首页,name是 %s' % name)
  6. else:
  7. # 使用应用命名空间,指定跳转的app url
  8. return redirect(reverse('front:login'))
  9. '''urls.py'''
  10. # 定义应用命名空间
  11. app_name = 'front'
  12. urlpatterns = [
  13. # 使用name给URL命名
  14. path('', views.index, name="index"),
  15. # path('login/', views.login, name="login"),
  16. # 若使用反转,url名称变动,不影响url映射
  17. path('signin/', views.login, name="login")
  18. ]

实例命名空间

一个app可以创建多个实例,可以使用多个URL映射同一个App。在做反转时,如果使用应用命名空间,就会发生混淆,为了避免这个问题,可以使用实例命名空间。

使用 namespace 定义实例命名空间:

  1. '''项目的urls.py文件'''
  2. from django.contrib import admin
  3. from django.urls import path, include
  4. urlpatterns = [
  5. path('admin/', admin.site.urls),
  6. path('', include("front.urls")),
  7. path('cms/', include("cms.urls")),
  8. # 实例命名空间
  9. path('cms1/', include("cms.urls", namespace='cms1')),
  10. path('cms2/', include("cms.urls", namespace='cms2')),
  11. ]
  12. '''app的views.py文件'''
  13. from django.shortcuts import redirect, reverse
  14. from django.http import HttpResponse
  15. # Create your views here.
  16. def index(request):
  17. # 查看当前访问的实例命名空间
  18. current_namespace = request.resolver_match.namespace
  19. print(current_namespace)
  20. return HttpResponse('后台页面首页')

URL反转传递参数

如果这个url中需要传递参数,那么可以通过 kwargs 来传递参数。

  1. reverse("book:detail",kwargs={"book_id":1})

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

  1. login_url = reverse("front:singin") + "?name=jr"
  2. return redirect(login_url)

示例:

  1. 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)

  1. # return HttpResponse('后台页面首页')
  2. """url反转传参"""
  3. # 默认反转的URL:http://127.0.0.1:8000/cms/login/2/
  4. return redirect(reverse('cms:admin', kwargs={'lid': 2})) # 直接传参
  5. # 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)

  1. 2. appurls文件:
  2. ```python
  3. from django.urls import path
  4. from . import views
  5. # 定义应用命名空间
  6. app_name = 'cms'
  7. urlpatterns = [
  8. path('', views.index, name="index"),
  9. path('login/', views.login, name='login'),
  10. path('admin/<lid>/', views.admin, name='admin')
  11. ]

指定默认参数

  1. """views.py"""
  2. from django.http import HttpResponse
  3. def admin(request, lid=1): # 默认参数
  4. return HttpResponse('后台管理页面, id是 %s' % lid)
  5. """urls.py"""
  6. from django.urls import path
  7. from . import views
  8. urlpatterns = [
  9. path('admin/', views.admin, name='admin'), # 接收默认参数
  10. path('admin/<lid>/', views.admin, name='admin') # 传递指定参数
  11. ]

re_path正则匹配URL

使用re_path正则表达式可以实现一些复杂的URL规则匹配需求,re_path的参数和path参数一模一样,只不过第一个参数,也就是route可以为一个正则表达式。

  1. """views.py"""
  2. from django.http import HttpResponse
  3. def birthday_year(request, year):
  4. return HttpResponse('您的生日年份是%s' % year)
  5. """urls.py"""
  6. from django.urls import path, re_path
  7. from . import views
  8. # re_path()和url()都能达到同样的正则匹配效果
  9. from django.conf.urls import url
  10. urlpatterns = [
  11. # ?P<year>为传参固定格式
  12. re_path(r'byear/(?P<year>\d{4})$', views.birthday_year)
  13. ]