框架第三课---作业讲解(数据增删改查),django请求生命周期流程图,django路由层,反向解析
上周内容回顾
-
静态文件及相关配置
1.静态文件的概念 简单的理解为html页面需要使用到的不经常变化的资源 css文件、js文件、img文件、第三方文件 2.访问静态文件配置 STATIC_URLS = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static') ] 3.接口前缀动态匹配 {% load static %} {% static 'bbb/ccc/d.txt' %} -
form表单相关注意事项
form标签重要属性 action 控制数据提交的地址!!! 三种编写方式: 什么都不写默认朝当前form表单所在页面提交 写全路径,写什么路径就朝什么路径提交 写一个路由,朝当前服务端对应的路由地址提交!! method 控制提交的方法 两种方法 默认是get 网络请求方式 get 朝服务端请求数据 并且可以携带一些额外的不敏感的条件(大小有限制2kb左右) URL?xxx=yyy&ooo=ppp post 朝服务端提交数据 也可以携带数据并且数据是放在请求体里面的(大小没有限制) 请求体 -
request对象方法
request.method 获取当前请求的请求方法 结果是纯大写的字符串 GET、POST
request.GET
获取URL问号后面携带的数据
结果是一个QueryDict拥有字典的特性
request.GET.get() 值列表最后一个数据值
request.GET.getlist() 整个值列表
request.POST
获取post请求请求体里面的数据
结果也是一个QueryDict拥有字典的特性
request.POST.get() 值列表最后一个数据值
request.POST.getlist() 整个值列表
* pycharm连接数据库
```python
1.database选项
2.对应的数据库驱动
-
django连接数据库
1.django默认自带sqlite3小型数据库 2.我们可以指定其他数据库 比如MySQL 3.配置文件中需要修改配置 DATABASES DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day51', 'HOST': '127.0.0.1', 'PORT': '3306', 'USER': 'root', 'PASSWORD': '222', 'CHARSET': 'utf8', }
}
1.添加相关配置mysql、NAME、HOST、PORT、USER、PASSWORD、CHARSET
2.需要下载mysqlclient模块(如果是django1.X版本可以用pymysql)
* orm简介
对象关系映射(Object Relational Mapping)
```python
对象关系映射
1.优势
简单方便快捷
2.劣势
效率可能会低
-
数据库迁移命令
1.models.py中编写了与数据库相关的代码 2.将代码操作记录下来 migrations目录 python38 manage.py makemigrations 3.将操作真正同步到数据库中 python38 manage.py migrate """ 首次创建django会额外创建很多内部需要用到的表 针对程序员自己创建的表名在表名前面加上应用前缀用于区分多个应用表名可能冲突的情况 """ -
orm基本操作
models.UserInfo.objects.create() # insert into models.UserInfo.objects.filter() # where models.UserInfo.objects.filter().update() # update models.UserInfo.objects.filter().delete() # delete from
models.表名.objects.creat()
models.表名.objects.filter()
models.表名.objects.filter().update()
models.表名.objects.filter().delete()
今日内容概要
- django请求生命周期流程图!!!
- 作业讲解(数据增删改查)
- django路由层
- python虚拟环境(跳过)
- 反向解析
- 路由分发
- 名称空间
今日内容详细
django请求生命周期流程图
这个图很重要 无论是学习阶段还是复习阶段
django默认的网关接口 能够承受并发量很低 开发阶段用的!!!
wsgiref web服务器网关接口模块 主要作用:帮我们解析http请求数据格式,帮我们处理请求数据的格式!!!
uwsgi网关接口模块,程序上线之后用的!!!
两个模块都是基于WSGI协议开发的
学习流程
路由层、视图层、模板层、模型层、组件、BBS项目
注意模板语法是在后端起作用的!!!
前端是不能识别模板语法的,只能识别css,js,jquery这些前端的语法
所以django项目里面里面的templete模板层里面的里面我们所写的XXX.html文件里面所用到的{{XXXX}}或者{% XXX %}这样的都是模板语法,花括号里面的实际上是python代码
要先被三板斧比如render将模板语法解析变成html的文本后,才能发给前端的!!!
django项目里面的templete里面的我们写的模板xx.html实际上并不是前端的html文件,只是python把该模板文件起成了.html后缀!!!
如果换一种语言模板文件的后缀是不一样的,比如在php中叫xxx.php
在java里面叫xxx.jsp 在go中叫xxx.tpl

.
.
.
.
准备工作
先pycharm连接数据库
settings里面注掉一行代码!!!防止post请求报错!!
MIDDLEWARE = [
# 'django.middleware.csrf.CsrfViewMiddleware',
]
TEMPLATES里面路径重新写一下'DIRS': [os.path.join(BASE_DIR, 'templates')]
django连接数据库 settings里面也要配置一下,如果是用的django自带的数据库可以不用改
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day51', # 写你要操作的库名
'HOST': '127.0.0.1',
'PORT': '3306',
'USER': 'root',
'PASSWORD': '222',
'CHARSET': 'utf8',
}
}
.
.
.
可视化界面之数据增删改查
针对数据对象主键字段的获取可以使用更加方便的 obj.pk获取
在模型类中定义双下str方法可以在数据对象被执行打印操作的时候方便的查看
'''
{# 前端需要获取数据,并且发送给后端,目前只有form表单能实现!!#}
form表单中能够触发调剂动作的按钮只有两个
<input type='submit'/>
<button></button>
'''
1.数据展示功能
开设接口、获取数据、传递页面、展示数据
获取user表里面所有的数据!!
利用模板语法传递数据到html页面并完成处理,最终返回浏览器展示!!
--------------------------------------------------
--------------------------------------------------
2.数据添加功能
开设接口、获取数据、发送数据、校验数据、录入数据、重定向
先返回一个获取新增用户数据的html页面
根据不同的请求方式做不同的处理
获取用户相关数据
一些小判断(不如用户名密码不能为空,)
筛选用户名是否已存在!
如果用户名也没用重复就可以往数据库添加了一条数据了!!
数据添加完了后,重定向到数据展示页!!!
--------------------------------------------------
--------------------------------------------------
3.数据编辑功能
开设接口、
后端如何区分所要编辑的数据(问号携带参数)、后端获取用户数据、前端展示默认数据、获取用户并完成更新
-------
{# a标签的href=网址 点击a标签就会跳转到该网址去!就是朝该网址发了一个get请求!!!#}
get请求有想加点东西,在路由的后面通过问号?的方式携带一些数据!!
-------
编辑页展示出来的时候,需要在后端提前将拿到的用户数据,然后给两个input框加默认值,这样就展示出来的时候input框里面就有用户想要改的数据了!!!这样用户就比较方便了!!!
给input框添加value属性性!!!
--------
获取用户想要编辑的数据主键值
根据主键值去数据库查找筛选获取对应的数据
根据拿到的数据返回一个编辑数据的页面,并且该页面上需要提前展示出原来的数据!!
根据不同的请求处理不同逻辑,先对获取的前端post请求信息来点小判断!!
用户在编辑页面编辑的信息提交后,经过判断后确定没问题后,开始更新数据库里面对应的信息
数据更新完了后,重定向到数据展示页!!!
--------------------------------------------------
--------------------------------------------------
4.数据删除功能
开设接口、问号携带参数、删除二次确认
获取用户想要编辑的数据主键值
在html页面利用对删除按钮的点击事件触发确认框,并根据返回值,确认用户到底想不想删,如果不想删,利用jQuery事件的return false取消掉a标签自身的点击跳转到删除视图函数的功能,这样就删不成数据了!!!
根据主键值去数据库查找筛选获取对应的数据
数据更新完了后,重定向到数据展示页!
--------------------------------------------------
--------------------------------------------------
.
整体全部的代码!!!
views.py 文件代码
from django.shortcuts import render, HttpResponse, redirect
from app01 import models
# Create your views here.
def user_list_func(request):
# 1.获取user表里面所有的数据展示到html页面上!!
user_data = models.Users.objects.filter() # 查所有数据 列表套字典或者说列表套对象 Queryset [对象1,对象2,]
# 2. 利用模板语法传递数据到html页面并完成处理,最终返回浏览器展示
return render(request, 'userList_page.html', {'user_data': user_data})
# 返回html页面,并将列表也传给html页面!!!
--------------------------------------------------
--------------------------------------------------
def user_add_func(request):
# 2.根据不同的请求方式做不同的处理
if request.method == 'POST':
# 3.获取用户相关数据
username = request.POST.get('username') # 拿前端post请求提交的数据
user_age = request.POST.get('age')
# 4.一些小判断(不如用户名密码不能为空,)
if len(username) == 0 or len(user_age) == 0:
return HttpResponse('用户名年龄不能为空!')
# 5.筛选用户名是否已存在!
res = models.Users.objects.filter(name=username)
if res:
return HttpResponse('用户名已存在!')
# 6. 如果用户名也没用重复就可以往数据库添加了一条数据了!!
models.Users.objects.create(name=username, age=user_age)
# 7. 数据添加完了后,重定向到数据展示页!!!
return redirect('/user_list/')
# return HttpResponse('添加用户数据')
# 1. 先返回一个获取新增用户数据的html页面
return render(request, 'userAdd_page.html')
--------------------------------------------------
--------------------------------------------------
def user_edit_func(request):
# return HttpResponse('用户数据编辑')
# 1.获取用户想要编辑的数据主键值
target_edit_id = request.GET.get('edit_id')
# 4. 根据不同的请求处理不同逻辑
if request.method == 'POST':
username = request.POST.get('username') # 拿前端post请求提交的数据
user_age = request.POST.get('age')
if len(username) == 0 or len(user_age) == 0:
return HttpResponse('用户名年龄不能为空!')
# 5. 用户在编辑页面编辑的信息提交后,经过判断后确定没问题后,开始更新数据库里面对应的信息
models.Users.objects.filter(pk=target_edit_id).update(name=username, age=user_age)
# 6. 数据更新完了后,重定向到数据展示页!!!
return redirect('/user_list/')
# 2.根据主键值去数据库查找筛选获取对应的数据
target_edit_obj = models.Users.objects.filter(pk=target_edit_id)[0] # 注意filter拿到的是Queryset是列表套对象所以要索引0才能拿到对象
# 3.根据拿到的数据返回一个编辑数据的页面,并且该页面上需要提前展示出原来的数据!!
return render(request, 'userEdit_page.html', {'target_edit_obj': target_edit_obj})
--------------------------------------------------
--------------------------------------------------
def user_delete_func(request):
# return HttpResponse('删除数据')
# 1.获取用户想要编辑的数据主键值
target_edit_id = request.GET.get('delete_id')
# 2.根据主键值去数据库查找筛选获取对应的数据,然后删除
target_edit_obj = models.Users.objects.filter(pk=target_edit_id).delete()
# 3.数据更新完了后,重定向到数据展示页!!!
return redirect('/user_list/')
.
urls.py 文件代码
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
# 访问用户数据的接口
path('user_list/', views.user_list_func),
# 添加用户数据的接口
path('user_add/', views.user_add_func),
# 编辑用户数据的接口
path('user_edit/', views.user_edit_func),
# 删除用户数据的接口
path('user_delete/', views.user_delete_func),
]
.
models.py 文件代码
from django.db import models
# Create your models here.
class Users(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
def __str__(self):
return '用户对象:%s'% self.name
# 此处写个魔法方法,当我们打印对象的时候会触发它执行,作用就是能让我在打印对象的时候看下对象的内容,
# 就是为了便于对象打印之后查看,不影响数据库,所以不需要执行数据库迁移命令!!
# python38 manage.py makemigration
# python38 manage.py migrate
.
三个html页面
userlist_pagehtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class=text-center>数据展示页</h1>
<div class="col-md-8 col-md-offset-2">
<a href="/user_add/" class="btn btn-success">数据添加</a>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Age</th>
<th class="text-center">Operation</th>
</tr>
</thead>
<tbody>
{% for user_obj in user_data %}
<tr>
<td>{{ user_obj.pk }}</td>
<td>{{ user_obj.name }}</td>
<td>{{ user_obj.age }}</td>
<td class="text-center">
<a href="/user_edit/?edit_id={{ user_obj.pk }}" class="btn btn-primary btn-xs">编辑</a>
<a href="/user_delete/?delete_id={{ user_obj.pk }}" class="btn btn-danger btn-xs delBtn">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script>
$('.delBtn').click(function () {
let res = confirm('你确定要删除吗???')
if (res){}else{return false}
})
{#给删除按钮加一个点击事件,触发确认框,根据确认框的返回值,来决定是否要删除数据#}
{#如果返回值是true说明用户确实要删,什么操作都不用做,删除函数会自动删!!#}
{#如果返回值是false说明用户不想删了,此时利用jQuery事件先执行绑定的事件然后return false取消掉自身的功能#}
{#这样点a标签就只能触发绑定的单击事件,但是a标签自身的点击跳转到对应页面的功能就被取消掉了,就不执行删除函数了!#}
</script>
</body>
</html>
{# a标签的href=网址 点击a标签就会跳转到该网址去!就是朝该网址发了一个get请求!!!#}
useradd_pagehtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class="text-center">数据添加页</h1>
<div class="col-md-6 col-md-offset-3">
<form action="" method="post">
<p>username:
<input type="text" name="username" class="form-control">
</p>
<p>age:
<input type="text" name="age" class="form-control">
</p>
<input type="submit" value="添加用户" class="btn btn-warning btn-block">
</form>
</div>
</div>
</div>
</body>
</html>
{# 前端需要获取数据,并且发送给后端,目前只有form表单能实现!!#}
.
useredit_pagehtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class="text-center">数据编辑页</h1>
<div class="col-md-6 col-md-offset-3">
<form action="" method="post">
<p>username:
<input type="text" name="username" class="form-control" value="{{ target_edit_obj.name }}">
</p>
<p>age:
<input type="text" name="age" class="form-control" value="{{ target_edit_obj.age }}">
</p>
<input type="submit" value="编辑用户" class="btn btn-primary btn-block">
</form>
</div>
</div>
</div>
</body>
</html>
.
{# a标签的href=网址 点击a标签就会跳转到该网址去!就是朝该网址发了一个get请求!!!#}


.
.
form表单action后面不写默认朝当前页面提交数据!!


.
.
可以看出每一个a标签都带了额外的数据了!当我们点击按钮跳转到编辑页面的时候,网址路由的后面是跟了后缀的,这样我们用request.GET()就能拿到问号后面的信息,从而后端就知道你要编辑那条数据了!!!


.
.
可以看出随机点一个用户编辑按钮后,跳转的编辑页面,自动已经将用户数据放input框里面了!!


.
.


.
.
.
.
.
django路由层
1.针对路由匹配
urls.py文件里面
django2.X及以上 path() 括号里面第一个参数写什么就匹配什么
django1.X path() 括号里面第一个参数是 正则表达式
无论什么版本django都自带加斜杠后缀的功能 也可以取消
配置文件中加一行代码 APPEND_SLASH = False
slash 劈 砍 斜线
-------------------------------------------------
-------------------------------------------------
.
2.转换器 将对应位置匹配到的数据转化成固定的数据类型!!!
正常情况下很多网站都会有很多相似的网址 如果我们每一个都单独开设路由很不合理!!!
django2.X及以上版本路由动态匹配有转换器(五种) 记前两个就行了!!!
--------------------------------------------------------------------
--------------------------------------------------------------------
str:匹配除路径分隔符外的任何非空字符串。
int:匹配0或者任意正整数。
slug:匹配任意一个由字母或数字组成的字符串。
uuid:匹配格式化后的UUID。
path:能够匹配完整的URL路径
ps:还支持自定义转换器(自己写正则表达式匹配更加细化的内容)
--------------------------------------------------------------
path('index/<str:info>/', views.index_func)
在用转化器捕捉一些数据的时候,
index/后面所匹配到的内容会当成关键字参数传给后面的视图函数!!!
打个比方我输入了网址:http://127.0.0.1:8000/index/aa/
<str:info>会接收到aa并转为字符串,以info=aa关键字参数形式传给views.index_func函数!!!
我们可以叫转换器里面的info这种变量名为分组名!
index_func(实参request,分组名='转换器匹配到的类型转换之后的内容')
由于我们的函数只定义了一个位置参数,并且是框架拿到请求数据整理好直接传给函数的
我们并没有在函数定义阶段定于关键字参数,所以转换器得到的字符串,没法传给函数!!!
路由这样写的目的是:比如接口前缀index/将来不知道要接什么后缀,但是我就想让index/后面接后缀,就可以这样用!!!
---------------------------------------
# 转换器 将对应位置匹配到的数据转换成固定的数据类型
index_func(实参request,info='转换器匹配到的类型转换之后的内容')
path('index/<str:info>/', views.index_func)
-------------------------------------------------
-------------------------------------------------
path('index/<str:info>/<int:id>/', views.index_func)
同理如果再加一个转换器!那么对应的自定义函数就要在加一个id关键字参数传进去,才能不报错
这时候http://127.0.0.1:8000/index/aaaa/12235456/
函数里面info参数就拿到了info=aaaa id参数就拿到了id=12235456
# index_func(实参request对象,info='转换器匹配到的类型转换之后的内容',id='转换器匹配到的类型转换之后的内容')
当如如果在视图函数里面不需要用到,转换器匹配到的数据,又不想一个一个写对应的关键字参数,就直接这样写就行了!!!
def index_func(request, **kwargs):
-------------------------------------------------
-------------------------------------------------
urlpatterns = [
path('index/str:info/', views.index_func),]
由于我们的函数只定义了一个位置参数,并且是框架拿到请求数据整理好直接传给函数的
我们并没有在函数定义阶段定于关键字参数,所以转换器得到的字符串,没法传给函数!!!
所以报错!!
index_func(实参request,info='转换器匹配到的类型转换之后的内容')
由于我们的函数只定义了一个位置参数,并且是框架拿到请求数据整理好直接传给函数的
我们并没有在函数定义阶段定义关键字参数,所以转换器得到的字符串,没法传给函数!!!
.
也就是如果不想让函数报错,必须要在函数的定义阶段在括号里面加个info,才能不报错!!!



.


.
.
3.正则匹配
django2.X及以上版本 urls.py 文件里面 re_path()第一个参数是正则
正则匹配的特点:
只要第一个正则表达式能够从用户输入的路由中匹配到数据,就算匹配成功!!!
会立刻停止路由层其他的匹配,直接执行对应的视图函数
只要正则表达式能够从用户输入的网址中,匹配到内容就算匹配成功,立刻触发后面的视图函数的运行!!并接受路由层的匹配!!!
-------------------------------------------------
-------------------------------------------------
路由的正则的最终版:把网址后缀的前后都限制死!!!
re_path('^test/$', views.test)
django1.X路由匹配使用的是url() 功能与django2.X及以上的re_path()一致
from django.urls import path,re_path
-------------------------------------------------
-------------------------------------------------
只要第一个正则表达式能够从用户输入的路由中匹配到数据就算匹配成功!!!
会立刻停止路由层其他的匹配直接执行对应的视图函数
路由testadd 也能被正则test 匹配上 所有就直接执行test的视图函数了!!!




.
也就是如果网址后缀testadd这样写,那testadd的视图函数永远执行不了!!!
如何解决了?屁股后面加个斜杆就行了!!!


输入网址后 http://127.0.0.1:8000/testadd django会自动给你添加一个斜杆
这时候就匹配上了testadd/的路由了!!!

.
.
.
4.正则匹配的无名有名分组
--------------------------------------------------
无名分组
re_path('^test/(\d{4})/', views.test)
匹配开头是text/后面是4个数字的路由!!!
会将括号内正则匹配到的内容,当做位置参数!,传递给视图函数!
路由匹配成功后调用视图函数运行 test(实参request对象,括号内正则匹配到的内容)
正则表达式加括号就是分组!!!!
re_path('^test/(\d{4})/(.*?)/', views.test)
如果有两个分组,函数里面就要多加两个位置参数!!!
--------------------------------------------------
--------------------------------------------------
有名分组(把正则分组后的东西,起个别名,正则表达式前面的?P<year>不影响\d{4}正则匹配)
re_path('^test/(?P<year>\d{4})/', views.test)
会将括号内正则匹配到的内容!,当做关键字参数!,传递给视图函数!
re_path('^test/(?P<year>\d{4})/(?P<others>).*?/', views.test)
路由匹配成功后调用视图函数运行
test(实参request对象,year='\d{4}匹配到的内容',others='.*?匹配到的内容')
注意上述的分组不能混合使用!!!
--------------------------------------------------
--------------------------------------------------
.
.
.
.
反向解析
路由有时候根据需求可能会变,但是html页面上的比如a标签跳转的路由又是写死的情况下
如果大量的a标签都绑定了该固定的路由,此时改路由,a标签对应的绑定地址就全部要改!!!
这个时候就要用到反向解析!!!
通过一个名字可以反向解析出一个结果 该结果可以访问到某个对应的路由!!!
---------------------------------------------------------------
基本使用
1.路由匹配关系起别名
path('login001/', views.login, name='login_view')
要使用反向解析,要提前给要用的这对路由与函数的绑定关系,用name打个标记!!!name='login_view'
这样以后就可以通过这个'login_view'动态的解析到里面的路由。无论你路由怎么变化!!!
都能拿到对应的变化后的路由!!!
注意如果urls.py文件里面有很多路由与函数的绑定关系都要用name打标记
那么name对应的值不能重复!!!!
只有了别名,无论在html页面还是在视图层 都能用别名动态解析出路由出来!!!
---------------------------------------------------------------
---------------------------------------------------------------
2.反向解析基本使用语法!!!
html页面上固定的模板语法: {% url 'login_view' %}
{% url 'login_view' %} 这样一写的意思就是将名字动态解析出一个结果,该结果又能访问到对应的路由!!!无论你路由怎么变化!!!
后端语法重定向redirect也可以用: reverse('login_view')
要提前在导入的三板斧后面,再导一个reverse
from django.shortcuts import render, HttpResponse, redirect,reverse
----------------------------------------------------------------

.

.
.
.
.
动态路由的反向解析!!!
注意反向解析的目的是:根据一个名字解析出一个路由结果!!!!这句话是重点!!!
那么动态匹配的路由怎么反向解析了???
比如这种动态匹配的路由 path('func1/<str:others>/', views.func1_func)
怎么反向解析了???
------------------------------------------------------
------------------------------------------------------
1. 还是要先起别名!!!
path('func1/<str:others>/', views.func1_func, name='func1_view')
----------
----------
2. 该反向解析必须再传一个参数,告诉django这个<str:others>动态的部分到底对应的是个啥!!
django才能准确的解析出该路由!!! 比如你给个jason 动态解析出的路由就是 func1/jason/
html页面上模板语法 {% url 'func1_view' 'jason' %}
后端语法 reverse('func1_view', args=('jason',))
同理如果你用正则匹配有多个分组,那就会传多个产数给函数,如果有起别名就会按照关键字参数,一起传给函数!!!对应到html页面上也是一样要多传几个参数!!!
.
.
.
作业
1.利用路由匹配与反向解析改写作业讲解
2.整理今日内容及博客

浙公网安备 33010602011771号