今日内容概要
-
作业讲解之用户管理系统(单表)
-
django请求生命周期流程图
-
路由系统
-
路由匹配(不同版本的django有一丢丢的区别)
无名分组
有名分组
反向解析
路由分发
名称空间
作业讲解之用户管理系统(单表)
1.步骤划分
- 配置文件
- 模型类
- 页面搭建
- 数据添加的逻辑
- 数据编辑的逻辑
- 数据删除的逻辑
2.源码展示
- view.py
from django.shortcuts import render,HttpResponse,redirect from app01 import models # Create your views here. def userlist(request): # 查询所有的用户数据,传递给html页面展示 data_queryset = models.Userinfo.objects.filter() # filter括号内不写参数,相当于没有筛选条件,等价于查询所有 return render(request,'userlist.html',{'data_queryset':data_queryset}) def useradd(requset): # 2.判断请求方式 if requset.method == 'POST': name = requset.POST.get('username') age = requset.POST.get('age') # 3.先判断用户名是否已存在 user_obj = models.Userinfo.objects.filter(name=name) if user_obj: return HttpResponse('用户名冲突!!!') # 4.写入数据库 models.Userinfo.objects.create(name=name,age=age) # 5.跳转到数据展示页 return redirect('/userlist/') # 1.先返回一个添加用户的页面 return render(requset,'useradd.html') def useredit(request): # 1.获取用户想要编辑的数据 edit_id = request.GET.get('id') if request.method == 'POST': name = request.POST.get('username') age = request.POST.get('age') # 3.更新数据 models.Userinfo.objects.filter(id=edit_id).update(name=name,age=age) # 4.跳转导数据展示页 return redirect('/userlist/') edit_obj = models.Userinfo.objects.filter(id=edit_id).first() # 2 返回编辑页面 return render(request,'useredit.html',{'edit_obj':edit_obj}) def userdel(request): delete_id = request.GET.get('id') models.Userinfo.objects.filter(id=delete_id).delete() return redirect('/userlist/')
- urls.py
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), # 用户数据展示 path('userlist/',views.userlist), # django学习小白阶段url的命名不需要遵循>restful规范 # 用户数据添加 path('useradd/',views.useradd), # 用户数据编辑 path('useredit/',views.useredit), # 用户数据删除 path('userdel/',views.userdel), ]
- models.py
from django.db import models # Create your models here. class Userinfo(models.Model): name = models.CharField(max_length=32) age = models.IntegerField()
- userlist.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> {# {% load static %}#} {# <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css'%}">#} </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h1 class="text-center">数据显示页</h1> <a href="/useradd/" class="btn btn-success">添加用户</a> <table class="table-hover table table-striped"> <thead> <tr> <th>Id</th> <th>Name</th> <th>Age</th> <th>Dperation</th> </tr> </thead> <tbody> {% for date_obj in data_queryset %} <tr> <td>{{ date_obj.id }}</td> <td>{{ date_obj.name }}</td> <td>{{ date_obj.age }}</td> <td> <a href="/useredit/?id={{ date_obj.id }}" class="btn btn-primary btn-xs">编辑</a> <a href="/userdel/?id={{ date_obj.id }}" class="btn btn-danger btn-xs">删除</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> </html>
- useradd.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h1 class="text-center">数据添加页</h1> <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" class="btn btn-warning btn-block" value="添加数据"> </form> </div> </div> </div> </body> </html>
- userdict.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h1 class="text-center">数据编辑页</h1> <form action="" method="post"> <p>username: <input type="text" name="username" class="form-control value="{{ edit_obj.name }}"> </p> <p>age: <input type="text" name="age" class="form-control value="{{ edit_obj.age }}"> </p> <input type="submit" class="btn btn-warning btn-block" value="添加数据"> </form> </div> </div> </div> </body> </html>
django请求生命周期流程图
参考截图:
路由匹配
1.语法结构
path('网址后缀',函数名)
2.特征
一旦网址后缀匹配上了就会自动执行后面的函数;
并结束整个路由的匹配。
3.路由结尾的斜杠
- 默认情况下不写斜杠,django会做二次处理。
第一次匹配不上 会让浏览器加斜杠再次请求- django配置文件(settings.py)中可以指定是否自动添加斜杠。
APPEND_SLASH = False
4.path转换器
- 当网址后缀不固定的时候,可以使用转换器来匹配。
'int': IntConverter(), 'path': PathConverter(), 'slug': SlugConverter(), 'str': StringConverter(), 'uuid': UUIDConverter(),
- 方法:
path('func/<int:year>/<str:info>/', views.func)
- 转换器匹配到的内容会当做视图函数的关键字参数传入
- 转换器有几个叫什么名字,那么视图函数的形参必须对应。
def func(request,year,info): pass
5.re_path正则匹配
re_path(正则表达式,函数名)
- 匹配特性:
一旦网址后缀的正则能够匹配到内容就会自动执行后面的函数 ;
并结束整个路由的匹配。re_path('^test/$', views.test)
当网址后缀不固定的时候 可以使用转换器来匹配
6.正则匹配之无名分组
re.path('^text/(\d+)/',viewa.text)
正则表达式匹配到的内容会当做视图函数的位置参数传递给视图函数。
7.正则匹配之有名分组
re_path('^test/(?P<year>\d+)/(?P<others>.*?)/', views.test)
正则表达式匹配到的内容会当做视图函数的关键字参数传递给视图函数
8.django版本区别
在django1.11中 只支持正则匹配 并且方法是 url()
django2,3,4中 path() ;re_path() 等价于 url()
反向解析
1.需求:
页面上提前写死了很多路由 ,一旦路由发送变化会导致所有页面相关链接失效;
为了防止出现该问题 我们需要使用反向解析。
2.概念:
反向解析:返回一个结果 该结果可以访问到对应的路由
3.具体用法
- 路由对应关系起别名
path('register/', views.reg, name='reg_view')
- 使用反向解析语法
在html页面<a herf" ">中修改: {% url 'reg_view' %}
- 后端
from django.shortcuts import reverse reverse('reg_view')
ps:反向解析的操作三个方法都一样path() re_path() url()
无名有名反向解析
path('reg/<str:info>/', views.reg, name='reg_view')
当路由中有不确定的匹配因素,反向解析的时候需要人为给出一个具体的值。
后端函数定义: reverse('reg_view', args=('jason',)) 前端<a herf=" ">链接: {% url 'reg_view' 'jason' %}
ps:反向解析的操作三个方法都一样path() re_path() url()
路由分发
1.django路由匹配
django中的应用都可以有自己独立的;
urls.py ;templates文件夹 ;static文件夹。
能够让基于django开发的多个应用完全独立,便于小组开发。
2总路由
只做路由的分发处理。from django.urls import path,re_path,include path('app01/', include('app01.urls')), path('app02/', include('app02.urls')),
3.子路由
path('after/', views.after) # app01 path('after/', views.after) # app02
当项目特别大 应用特别多的时候 可以使用路由分发 非常方便!!!
名称空间
有路由分发场景下多个应用在涉及到反向解析别名冲突的时候无法正常解析。
- 解决方式1
用到名称空间的概念:namespace: path('app01/', include(('app01.urls', 'app01'), namespace='app01')) path('app01/', include(('app01.urls', 'app02'), namespace='app02'))
- 解决方式2
别名不冲突即可
保证django项目下没有重复的别名即可