Django框架学习——2—(视图、URL映射、URL中添加参数、URL模块化、Django内置转换器、url命名与反转、应用命名空间和实例命名空间、URL反转传递参数)

1、视图

视图一般都写在app的views.py中。并且视图的第一个参数永远都是request(一个HttpRequest)对象。这个对象存储了请求过来的所有信息,包括携带的参数以及一些头部信息等。在视图中,一般是完成逻辑相关的操作。比如这个请求是添加一篇博客,那么可以通过request来接收到这些数据,然后存储到数据库中,最后再把执行的结果返回给浏览器。视图函数的返回结果必须是HttpResponseBase对象或者子类的对象。

视图文件:book/views.py

from django.shortcuts import render

# Create your views here.

from django.http import HttpResponse


# django框架中写视图函数,必须要传参request
def book(request):
    return HttpResponse("图书首页")           # 返回值必须是 HttpResponse包裹住的类型


# django框架中写视图函数,必须要传参request
def index(request):
    return HttpResponse("hello world")       # 返回值必须是 HttpResponse包裹住的类型

定义路由文件:项目名称 /urls.py, 该路由文件与其他文件相互关联的原因在frist_django/settings.py文件中的ROOT_URLCONF = 'frist_django.urls'设置,frist_django是项目app名称。

"""frist_django URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.http import HttpResponse
from book.views import book             # 从其他app模块中导入定义的路由方法
from book.views import index


urlpatterns = [
    path('admin/', admin.site.urls),         # django默认路由前面有/,不需要添加
    path('', index),                         # 路由为/,绑定的方法是book模块中views.py的index方法
    path('book/', book),                     # 路由为book/,绑定的方法是book模块中views.py的index方法
]

2、URL映射

视图写完后,要与URL进行映射,也即用户在浏览器中输入什么url的时候可以请求到这个视图函数。在用户输入了某个url,请求到我们的网站的时候,django会从项目的urls.py文件中寻找对应的视图在urls.py文件中有一个urlpatterns变量,以后django就会从这个变量中读取所有的匹配规则。匹配规则需要使用django.urls.path函数进行包裹,这个函数会根据传入的参数返回URLPattern或者是URLResolver的对象。

from django.contrib import admin
from django.urls import path
from book import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/',views.book_list)
]

3、URL中添加参数

创建新的Django项目

# 首先先进入虚拟环境下
cd /d E:\ENV\Django项目\2-课

# 创建django项目,名称为django_url
django-admin startproject django_url

# 进入
cd django_url\


# 创建新的app模块,名称为book
python manage.py startapp book

有时候,url中包含了一些参数需要动态调整。比如简书某篇文章的详情页的url,是https://www.jianshu.com/p/a5aab9c4978e后面的a5aab9c4978e就是这篇文章的id,那么简书的文章详情页面的url就可以写成https://www.jianshu.com/p/,其中id就是文章的id。那么如何在django中实现这种需求呢。这时候我们可以在path函数中,使用尖括号的形式来定义一个参数。比如我现在想要获取一本书籍的详细信息,那么应该在url中指定这个参数。(后面的a5aab9c4978e就是这篇文章的id,是为了安全考虑,防止SQL注入等手段;还有就是隐藏网站中的真实文章数量等功能)

1. 第一种url传参方式

视图文件:book/views.py

from django.shortcuts import render
from django.http import HttpResponse


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


def book_detail(request, book_id, cate_id):
    return HttpResponse("图书详情,id为%s,分类id%s" % (book_id, cate_id))

定义路由文件:项目名称 /urls.py

from django.contrib import admin
from django.urls import path
from book import views


urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/', views.book),
    path('book/<book_id>/<cate_id>', views.book_detail), # <book_id>必须与views.book_detail方法中的参数名称相同
]

使用反斜线 / 隔开传参参数方式,实现的路由效果:
在这里插入图片描述

2. 第二种url传参方式

视图文件:book/views.py

from django.shortcuts import render
from django.http import HttpResponse


def book_list(request):
    print(type(request))               # 类<class 'django.core.handlers.wsgi.WSGIRequest'>
    book_id = request.GET.get('id')    # 从urls.py传输过来的参数id,GET是request类中的方法,request.GET返回的是字典,get获取字典中的参数
    return HttpResponse("图书列表%s" % book_id)

定义路由文件:项目名称 /urls.py

from django.contrib import admin
from django.urls import path
from book import views


urlpatterns = [
    path('admin/', admin.site.urls),
   
    path('book_list/', views.book_list),   # 关键字传参,不需要在路由中写参数
]

关键字传参,以? 号隔开传参参数,不需要在路由中写参数,实现的路由效果:
在这里插入图片描述

def book_list(request):
    print(type(request))               # 类<class 'django.core.handlers.wsgi.WSGIRequest'>
    book_id = request.GET.get('id')    # 从urls.py传输过来的参数id,GET是request类中的方法,request.GET返回的是字典,get获取字典中的参数
    c_id = request.GET.get('cid')

    return HttpResponse("图书列表%s, 图书类别是%s" % (book_id, c_id))

多个传参以&号隔开,根据键值对的参数来显示
在这里插入图片描述

4、URL模块化

URL中包含另外一个urls模块:
在我们的项目中,不可能只有一个app,如果把所有的app的views中的视图都放在urls.py中进行映射,肯定会让代码显得非常乱。因此django给我们提供了一个方法,可以在app内部包含自己的url匹配规则,而在项目的urls.py中再统一包含这个app的urls。使用这个技术需要借助include函数。

定义路由文件:项目名称 /urls.py

from django.contrib import admin
from django.urls import path, include   # include是url模块化


urlpatterns = [
    path('admin/', admin.site.urls),
    # path('book/', views.book),
    # path('book/<book_id>/<cate_id>', views.book_detail),     # <book_id>必须与views.book_detail方法中的参数名称相同
    # path('book_list/', views.book_list),          # 关键字传参,不需要在路由中写参数
    
    
    # url模块化,定义book模块的前缀路由,关联book模块下的urls.py文件
    path("book/", include("book.urls"))
]

book模块app文件下的路由文件:book/urls.py

# -*- encoding: utf-8 -*-
"""
@File    : urls.py
@Time    : 2020/6/17 15:54
@Author  : chen
book模块app文件下的路由文件:book/urls.py
"""
from django.urls import path
from . import views          # 引用当前文件夹下的views.py文件

# 此时的路由是book模块下定义的,需要被整体项目下的urls.py文件包含,而且路由前缀是需要在django_url/urls.py文件中定义
urlpatterns = [
    path('', views.book),
    path('book/<book_id>/<cate_id>', views.book_detail),     # <book_id>必须与views.book_detail方法中的参数名称相同
    path('book_list/', views.book_list),                     # 关键字传参,不需要在路由中写参数
]

在urls.py文件中把所有的和book这个app相关的url都移动到app/urls.py中了,django_first/urls.py中,通过include函数包含book.urls,以后在请求book相关的url的时候都需要加一个book的前缀。

实现效果如下:
在这里插入图片描述

5、Django内置转换器

from django.urls import converters

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

from django.urls import path
from . import views          # 引用当前文件夹下的views.py文件
from django.urls import converters

# 此时的路由是book模块下定义的,需要被整体项目下的urls.py文件包含,而且路由前缀是需要在django_url/urls.py文件中定义
urlpatterns = [
    path('', views.book),
    # 需要限制book_id和cate_id的数据类型,采用int类型数据
    path('book/<int:book_id>/<int:cate_id>', views.book_detail),     # <book_id>必须与views.book_detail方法中的参数名称相同
    path('book_list/', views.book_list),                     # 关键字传参,不需要在路由中写参数
]

6、url命名与反转

  • 1.为什么需要URL命名
    因为在项目开发的过程中URL地址可能经常变动,如果写死会经常去修改

  • 2.如何给一个URL指定名称

path("",views.index,name="index")    # 将路由地址命名为index
  • 3.应用命名空间
    在多个app之间可能产生同名的URL,这时候为了避免这种情况,可以使用命名空间来加以区分。在urls.py中添加app_name即可。

实例如下:
视图文件:front/views.py

from django.shortcuts import render, redirect,reverse      # 重定向
from django.http import HttpResponse


def front_index(request):
    # 传参
    username = request.GET.get('username')         # 传参username,模拟传递用户名
    if username:
        return HttpResponse("前台首页")             # 模拟用户登录后,转到首页界面
    else:                                          # 用户未登陆的时候,需要重定向到登录界面
        # 重定向
        # return redirect('login/')                  # 地址与front/urls.py文件中的路由地址要绑定
        return redirect(reverse('front:login'))      # 通过路由的name来进行反转,查找到定义的路由"signin/",front:是限制该路由的应用命名空间名称


def front_login(request):
    return HttpResponse("前台登录界面")

注意:代码中的front:是限制该路由的应用命名空间名称,防止不同app模块命名路由相同,访问出现重定义,限制路由访问,该命名从urls.py文件中传入。

定义前台路由文件:front/urls.py

# -*- encoding: utf-8 -*-
"""
@File    : urls.py
@Time    : 2020/6/17 16:56
@Author  : chen
定义前台路由文件:front/urls.py
"""
from django.urls import path
from . import views

# 应用命名空间
app_name = "front"

urlpatterns = [
    path("", views.front_index, name="index"),
    path("signin/", views.front_login, name="login"),           # 路由名称signin/,如果后期项目需要修改路由,只需修改这里的路由地址,其他的都可以不用修改了
]

在这里插入图片描述

7、应用命名空间和实例命名空间

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

django_url/urls.py ,定义实例命名空间

from django.contrib import admin
from django.urls import path, include   # include是url模块化
# from book import views


urlpatterns = [
    path('admin/', admin.site.urls),
    # path('book/', views.book),
    # path('book/<book_id>/<cate_id>', views.book_detail),     # <book_id>必须与views.book_detail方法中的参数名称相同
    # path('book_list/', views.book_list),          # 关键字传参,不需要在路由中写参数
    
    
    # url模块化,定义book模块的前缀路由,关联book模块下的urls.py文件
    path("book/", include("book.urls")),
    path("cms/", include("cms.urls")),
    path("", include("front.urls")),       # 前台界面直接访问
    path("cms1/", include("cms.urls", namespace='cms1')),        # 实例命名空间
    path("cms2/", include("cms.urls", namespace='cms2')),        # 实例命名空间
]

cms/views.py, 显示当前访问的实例命名空间名称

from django.shortcuts import render
from django.http import HttpResponse


def cms_index(request):
    current_namespace = request.resolver_match.namespace             # 获取当前访问的实例命名空间名称
    print(current_namespace)
    
    return HttpResponse("后台首页")


def cms_login(request):
    return HttpResponse("后台登录界面")

8、URL反转传递参数

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

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

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

login_url = reverse("front:singin") + "?name=xxx"
return redirect(login_url)

两种反转传递参数方式:

front/views.py

from django.shortcuts import render, redirect,reverse      # 重定向
from django.http import HttpResponse


def front_index(request):
    # 传参
    username = request.GET.get('username')         # 传参username,模拟传递用户名
    if username:
        return HttpResponse("前台首页")             # 模拟用户登录后,转到首页界面
    else:                                          # 用户未登陆的时候,需要重定向到登录界面
        # 重定向
        # return redirect('login/')                  # 地址与front/urls.py文件中的路由地址要绑定
        # return redirect(reverse('front:login'))      # 通过路由的name来进行反转,查找到定义的路由"signin/",front:是限制该路由的应用命名空间名称
        
        # 第一种传参:url反转重定向传参,关键字传参
        # return redirect(reverse('front:article', kwargs={"article_id": 3}))

        # 第二种传参:url反转重定向传参,字符串拼接传参
        return redirect(reverse('front:login') + "?name = 详情信息")


def front_login(request):
    name = request.GET.get('name')
    return HttpResponse("前台登录界面% s" % name)        # 这种选择字符拼接传参


def front_article(request, article_id):
    return HttpResponse("前台登录界面 %s" % article_id)          # 这种选择关键字传参

定义前台路由文件:front/urls.py

# -*- encoding: utf-8 -*-
"""
@File    : urls.py
@Time    : 2020/6/17 16:56
@Author  : chen
定义前台路由文件:front/urls.py
"""
from django.urls import path
from . import views

# 应用命名空间
app_name = "front"

urlpatterns = [
    path("", views.front_index, name="index"),
    path("signin/", views.front_login, name="login"),           # 路由名称signin/,如果后期项目需要修改路由,只需修改这里的路由地址,其他的都可以不用修改了
    path("article/<article_id>", views.front_article, name="article"),      # 定义路由
]

两种传参方式的选择不同,效果如下:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章