• Django基础讲解-路由控制器和视图(Django-02)


    一 路由控制器

    参考链接: Django源码阅读:路由(二) - 知乎

    Route路由, 是一种映射关系!路由是把客户端请求的 url路径与视图进行绑定 映射的一种关系。

    这个/timer通过路由控制器最终匹配到myapp.views中的视图函数 timer

    在django中所有的路由最终都被保存到一个变量 urlpatterns, urlpatterns必须声明在主应用下的urls.py总路由中。这是由配置文件settings设置的。

    在django运行中,当客户端发送了一个http请求到服务端,服务端的web服务器则会从http协议中提取url地址, 从程序内部找到项目中添加到urlpatterns里面的所有路由信息的url进行遍历匹配。如果相等或者匹配成功,则调用当前url对象的视图方法。

    在给urlpatterns路由列表添加路由的过程中,django一共提供了2个函数给开发者注册路由,字符串路由和正则路由

    1. from django.urls import path # 字符串路由
    2. from django.urls import re_path # 正则路由,会把url地址看成一个正则模式与客户端的请求url地址进行正则匹配
    3. # path和re_path 使用参数一致.仅仅在url参数和接收参数时写法不一样

    1.1 基本使用

    path and re_path 两种路由的使用:

    1. # 只要请求路径和正则匹配成功就会执行视图函数~
    2. path(r'^articles/2003/$', views.special_case_2003),
    3. re_path(r'^articles/([0-9]{4})/$', views.year_archive),# $ 符 不会被上面的覆盖掉 上面的就匹配不成功了
    4. # 1、简单分组 ([0-9]{4}) ([0-9]{2}) 是按位置传参的 和参数位置有关
    5. re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),#加个小括号是正则的简单分组 符合小括号的正则内容 会按形参入到视图函数中 函数也要接收~
    6. # 2、有名分组 ?P ?P 是按关键字传参的 和参数位置无关 视图函数形参的参数名要保持一直
    7. re_path(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/$', views.month_archive2),
    8. '''
    9. re_path(r'^articles/(\d{4}/(\d{1,2})/$',articles_archive_by_month)
    10. 请求路径:/articles/2010/12
    11. # 简单分组
    12. re.findall("articles/(\d{4}/(\d{1,2})","/articles/2010/12") # 左边是规则 后面是请求路径
    13. 一旦匹配成功:调用articles_archive_by_month(request,2010,12) # (\d{4}/(\d{1,2})分组了 就会传参 视图函数就会在数据库里进行查询
    14. # 有名分组
    15. 一旦匹配成功:
    16. if 简单分组:
    17. 调用articles_archive_by_month(request,2010,12) # 位置传参
    18. else if 有名分组:
    19. 调用articles_archive_by_month(request,year = 2010,month = 12) # 关键字传参
    20. '''

    1.2 路由分发

    1. from django.urls import path, re_path, include
    2. path('api/', include('erp_system.urls')),
    3. path('api/', include('basic_info.urls')),
    4. path('api/', include('goods_info.urls')),
    5. path('api/', include('purchase_info.urls')),
    6. path('api/', include('warehouse_info.urls')),

    1.3 反向解析

    在使用Django 项目时,一个常见的需求是获得URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。人们强烈希望 不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 毫不相关的专门的URL 生成机制,因为这样容易导致一定程度上产生过期的URL。

    反向解析:就是路由不想写死

    在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:

    在模板中:使用url模板标签

    在Python 代码中:使用from django.urls import reverse 函数。(视图函数重定向中写url时)

    urls.py中为url设置别名参数:

    1. from django.conf.urls import url
    2. from . import views
    3. urlpatterns = [
    4. #...name='news-year-archive'
    5. url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
    6. #...
    7. ]

    应用之在模板中反向解析: {% url 'news-year-archive' 2012 %} 别名:'news-year-archive' 正则参数:2012。

    1. from django.shortcuts import redirect
    2. from django.urls import reverse
    3. def redirect_to_year(request):
    4. year = 2006
    5. reverse_path=reverse('news-year-archive', args=(year,))
    6. return redirect(reverse_path) # 等效 redirect("/articles/2006/")

    二 视图

    Django的视图主要有2种,分别是视图函数视图类 ,现在我们先从视图函数(FBV)进行入手,后面再学习视图类(CBV)

    • Function BaseView:函数基本视图

    • Class BaseView:类基本视图

    2.1 请求方式

    web项目运行在http协议下,默认肯定也支持用户通过不同的http请求发送数据来。django支持让客户端只能通过指定的Http请求来访问到项目的视图。

    home/views.py

    1. # 让用户发送POST才能访问的内容
    2. from django.views.decorators.http import require_http_methods
    3. @require_http_methods(["POST"])
    4. def login(request):
    5. # 获取请求方式 GET/POST
    6. print(request.method)
    7. # 获取请求体数据
    8. print(request.body) # 一个字符串,代表请求报文的请求体的原数据
    9. print(request.POST) # 只有请求数据格式是 urlencoded 时才能获取到
    10. # 获取具体数据
    11. user = request.POST.get("user"# get()获取键对应值的列表里的最后一个元素
    12. hobby = request.POST.getlist("hobby"# 获取值列表里的所有元素
    13. return HttpResponse("登录成功!")

    路由绑定,demo/urls.py,代码:

    1. from django.contrib import admin
    2. from django.urls import path
    3. from home.views import timer
    4. urlpatterns = [
    5. path('admin/', admin.site.urls),
    6. path("timer", timer),
    7. path("login", login),
    8. ]

    2.2 请求对象

    django将请求报文中的请求行、首部信息、内容主体封装成 HttpRequest 类中的属性。 除了特殊说明的之外,其他均为只读的。

    HttpRequest 对象包含当前请求URL的一些信息:

    1. # 进入注册页面的视图函数
    2. @require_http_methods(["GET"])
    3. def register(request):
    4. print('进入register视图函数')
    5. user_id = request.GET['id']
    6. print(user_id, type(user_id))
    7. return HttpResponse(f'你传入的用户ID是:{user_id}')

    2.2.1 请求方式

    print(request.method)

    2.2.2 请求数据

    1. HttpRequest.GET:一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。

    2. HttpRequest.POST:一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。# 注意:键值对的值是多个的时候, # 比如checkbox类型的input标签,select标签,需要用:request.POST.getlist("hobby")。
    3. HttpRequest.body:一个字符串,代表请求报文的请求体的原数据。

    2.2.3 请求路径

    HttpRequest.path:  表示请求的路径组件(不含get参数)只是路径部分。
    HttpRequest.get_full_path():含get参数的路径。

    2.2.4 请求头

    HttpRequest.META:一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,HttpRequest.META.get('HTTP_HOST')。

    2.3 响应对象

    响应对象主要有三种形式:

    HttpResponse()     # 响应基础类
    JsonResponse()     # json格式的响应 (接口编程,DRF)

    render()     # 内核都是HttpResponse()

    redirect()   # 内核都是HttpResponse()

    2.3.1 HttpResponse()

    Django服务器接收到客户端发送过来的请求后,会将提交上来的这些数据封装成一个 HttpRequest 对象传给视图函数。那么视图函数在处理完相关的逻辑后,也需要返回一个响应给浏览器。

    而这个响应,我们必须返回 HttpResponseBase 或者他的子类的对象。而 HttpResponse 则是 HttpResponseBase 用得最多的子类。

    return HttpResponse("登录成功!",status=404,content_type='text/plain')

    常用属性:

    content:返回的内容。

    status_code:返回的HTTP响应状态码。

    content_type:返回的数据的MIME类型,默认为 text/html 。浏览器会根据这个属性,来显示数据。如果是 text/html ,那么就会解析这个字符串,如果 text/plain ,那么就会显示一个纯文本。

    设置响应头: response['X-Access-Token'] = 'xxxx' 。

    2.3.1.2 JsonResponse类:

    用来对象 dump 成 json 字符串,然后返回将 json 字符串封装成 Response 对象返回给浏览器。并且他的 Content-Type 是 application/json 。示例代码如下:

    1. from django.http import JsonResponse
    2. def index(request):
    3. book = {"title":"三国演义","price":199}
    4. books = [{"title":"三国","price":99},{"title":"三国演义","price":199}]
    5. # JsonResponse(book)本质 是先序列化json.jump, ensure_ascii=False 使数据正常显示 。content_type='application/json' 声明一下响应类型
    6. # return HttpResponse(json.jump(book,ensure_ascii=False),content_type='application/json')
    7. # return JsonResponse(book) # 默认是序列化一个字典
    8. return JsonResponse(books,safe=False) # 序列化一个非字典数据(列表)

    默认情况下 JsonResponse 只能对字典进行 dump ,如果想要对非字典的数据进行 dump ,那么需要给 JsonResponse 传递一个 safe=False 参数。

    2.3.2 render() 渲染函数

    1. render(request, template_name,[context])
    2. #结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。\
    3. render(request,'users/index.html',['ip':2013])

    参数:

    1. /*
    2. request: 用于生成响应的请求对象。ip
    3. template_name:要使用的模板的完整名称,可选的参数。模板文件非html文件因为里面有模板语句{{ip}},渲染后呈现在浏览器中的才是htm页面
    4. context:添加到模板上下文的一个字典,
    5. 默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
    6. */

    render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。

    2.3.3 redirect方法 (重定向)

    当您使用Django框架构建Python Web应用程序时,您在某些时候必须将用户从一个URL重定向到另一个URL,通过redirect方法实现重定向。

    参数可以是:

    • 一个绝对的或相对的URL, 将原封不动的作为重定向的位置.

    • 一个url的别名: 可以使用reverse来反向解析url

    1. # 传递要重定向到的一个具体的网址
    2. def my_view(request):
    3. ...
    4. return redirect("/some/url/")
    5. # 当然也可以是一个完整的网址
    6. def my_view(request):
    7. ...
    8. return redirect("http://www.baidu.com")
    9. # 传递一个视图的名称
    10. def my_view(request):
    11. ...
    12. return redirect(reverse("url的别名"))

    重定向 会有两次请求 第一次返回一个响应头location:/index/ (/index/ 是 resirect里写的相对路径) code:301 只要浏览器读取到301或302 就会发起新的请求 第二次返回一个index.html页面。

    APPEND_SLASH的实现就是基于redirect,默认补充浏览器请求路径的 / 在setting文件中配置 APPEND_SLASH=False 将默认补充关闭。

    三 登录验证案例

    3.1 html

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>Titletitle>
    6. head>
    7. <body>
    8. /*/users/auth 相对路径一定要加第一个/*/
    9. <form action="/user/auth" method="post">
    10. 用户名<input type="text" name="user">
    11. 密码 <input type="password" name="pwd">
    12. /*span标签提示错误信息*/
    13. <input type="submit"> <span style="color: red">{{ msg }}span>
    14. form>
    15. body>
    16. html>

    3.2 路由配置

    1. from django.contrib import admin
    2. from django.urls import path, re_path,include
    3. from users.views import login,auth
    4. urlpatterns = [
    5. path("login",login),
    6. path("auth",auth),
    7. ]

    3.3 视图函数

    1. def login(request):
    2. return render(request,"login.html")
    3. def auth(request):
    4. # 获取数据
    5. print("request.POST:",request.POST)
    6. user = request.POST.get("user")
    7. pwd = request.POST.get("pwd")
    8. # 模拟数据校验
    9. if user == "laomao" and pwd == "123456":
    10. # return HttpResponse("验证通过")
    11. return redirect("/users/")
    12. else:
    13. # return HttpResponse("用户名或者密码错误")
    14. # return redirect("/users/login")
    15. # 重定向适合动态页面 静态页面可以用render
    16. # 静态页面渲染一些信息一般用render
    17. msg = "用户名或者密码错误"
    18. return render(request,"login.html",{"msg":msg})

  • 相关阅读:
    《Aerosol Science and Technology》期刊介绍(SCI 3区)
    测试用例设计方法之:入门试招,等价边界初探
    maven构建项目报错:Failure to find com.microsoft.sqlserver:sqljdbc4:jar:4.0 in
    Ubuntu22.04+Nvidia驱动+Cuda11.8+cudnn8.6
    飞行动力学 - 第33节-螺旋模态机理 之 基础点摘要
    [附源码]计算机毕业设计ssm新能源电动汽车充电桩服务APP
    Springboot 集成 RocketMQ(进阶-消息)
    vSAN7.0更换硬盘步骤
    预测明天什么股能涨起来,预测明天什么股能涨停
    nvm:轻松管理多个 Node 版本 | 开源日报 No.80
  • 原文地址:https://blog.csdn.net/March_A/article/details/133501212