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个函数给开发者注册路由,字符串路由和正则路由

python 复制代码
from django.urls import path      # 字符串路由
from django.urls import re_path   # 正则路由,会把url地址看成一个正则模式与客户端的请求url地址进行正则匹配

# path和re_path 使用参数一致.仅仅在url参数和接收参数时写法不一样

1.1 基本使用

path and re_path 两种路由的使用:

python 复制代码
# 只要请求路径和正则匹配成功就会执行视图函数~
path(r'^articles/2003/$', views.special_case_2003),
re_path(r'^articles/([0-9]{4})/$', views.year_archive),# $ 符 不会被上面的覆盖掉 上面的就匹配不成功了
# 1、简单分组 ([0-9]{4})  ([0-9]{2})  是按位置传参的 和参数位置有关
re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),#加个小括号是正则的简单分组 符合小括号的正则内容 会按形参入到视图函数中 函数也要接收~

# 2、有名分组 ?P<year>  ?P<month> 是按关键字传参的 和参数位置无关 视图函数形参的参数名要保持一直
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive2),

'''
re_path(r'^articles/(\d{4}/(\d{1,2})/$',articles_archive_by_month)
请求路径:/articles/2010/12
# 简单分组
re.findall("articles/(\d{4}/(\d{1,2})","/articles/2010/12") # 左边是规则 后面是请求路径 
一旦匹配成功:调用articles_archive_by_month(request,2010,12) # (\d{4}/(\d{1,2})分组了 就会传参 视图函数就会在数据库里进行查询

# 有名分组
一旦匹配成功:
if 简单分组:
    调用articles_archive_by_month(request,2010,12)  # 位置传参
else if 有名分组:
    调用articles_archive_by_month(request,year = 2010,month = 12) # 关键字传参
'''

1.2 路由分发

python 复制代码
from django.urls import path, re_path, include

path('api/', include('erp_system.urls')),
path('api/', include('basic_info.urls')),
path('api/', include('goods_info.urls')),
path('api/', include('purchase_info.urls')),
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设置别名参数:

python 复制代码
from django.conf.urls import url
from . import views

urlpatterns = [
    #...name='news-year-archive'
    url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
    #...
]

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

python 复制代码
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
<a href="/articles/2012/">2012 Archive</a>
python 复制代码
from django.shortcuts import redirect
from django.urls import reverse

def redirect_to_year(request):
    year = 2006
    reverse_path=reverse('news-year-archive', args=(year,))
    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

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

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

python 复制代码
from django.contrib import admin
from django.urls import path
from home.views import timer
urlpatterns = [
    path('admin/', admin.site.urls),
    path("timer", timer),
    path("login", login),
]

2.2 请求对象

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

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

python 复制代码
# 进入注册页面的视图函数
@require_http_methods(["GET"])
def register(request):
    print('进入register视图函数')
    user_id = request.GET['id']
    print(user_id, type(user_id))
    return HttpResponse(f'你传入的用户ID是:{user_id}')

2.2.1 请求方式

python 复制代码
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 用得最多的子类。

python 复制代码
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 。示例代码如下:

python 复制代码
from django.http import JsonResponse

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

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

2.3.2 render() 渲染函数

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

参数:

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

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

2.3.3 redirect方法 (重定向)

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

参数可以是:

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

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

python 复制代码
# 传递要重定向到的一个具体的网址
def my_view(request):
    ...
    return redirect("/some/url/")
# 当然也可以是一个完整的网址
def my_view(request):
    ...
    return redirect("http://www.baidu.com")
# 传递一个视图的名称
def my_view(request):
    ...
    return redirect(reverse("url的别名"))

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

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

三 登录验证案例

3.1 html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

/*/users/auth 相对路径一定要加第一个/*/
<form action="/user/auth" method="post">
    用户名<input type="text" name="user">
    密码 <input type="password" name="pwd">
    /*span标签提示错误信息*/
    <input type="submit"> <span style="color: red">{{ msg }}</span>
</form>
</body>
</html>

3.2 路由配置

html 复制代码
from django.contrib import admin
from django.urls import path, re_path,include

from users.views import login,auth
urlpatterns = [
    path("login",login),
    path("auth",auth),
]

3.3 视图函数

python 复制代码
def login(request):
    return render(request,"login.html")

def auth(request):
    #  获取数据
    print("request.POST:",request.POST)

    user = request.POST.get("user")
    pwd = request.POST.get("pwd")

    # 模拟数据校验
    if user == "laomao" and pwd == "123456":
        # return HttpResponse("验证通过")
        return redirect("/users/")
    else:
        # return HttpResponse("用户名或者密码错误")
        # return redirect("/users/login")
        # 重定向适合动态页面 静态页面可以用render
        # 静态页面渲染一些信息一般用render
        msg = "用户名或者密码错误"
        return render(request,"login.html",{"msg":msg})
相关推荐
上进小菜猪4 小时前
把 KES 集群交给 Kubernetes 的九十天:一个 DBA 的试用实录
后端
两点王爷4 小时前
PostgreSQL 常用 SQL 语句与 GIS 相关函数详解
数据库·后端
麻雀飞吧4 小时前
先判断工具用来学习、开发还是执行
人工智能·python
考虑考虑5 小时前
Springboot环境变量占位符语法
spring boot·后端·spring
人邮异步社区5 小时前
学习Python的最佳学习路径是什么?
python·程序员
步行cgn7 小时前
Spring 基于 XML 的自动装配:byName 详解
java·后端·spring
troy1287 小时前
Python 基础语法(九):Django/Flask/FastAPI 三大 Web 框架详细对比解析
python·jupyter·django·flask·github·fastapi
jzshmyt7 小时前
我用 Python 从零“生成“了一个宇宙,然后让它观察自己(v14)
人工智能·pytorch·python·numpy·matplotlib·空间计算·scipy
高洁018 小时前
大模型的幻觉怎么治
人工智能·深度学习·django·transformer·tornado
RISCV_Explorer8 小时前
RISC-V启动与运行时规范机制解析——BRS约定、HSM多核启动与设备树要求
后端·risc-v