day61——orm数据的删改查、django请求生命周期流程图、路由层

orm数据的删改查

需求:将数据库中user表中的数据全部以表格的形式展示到前端,并且在前端就能够对数据库的数据进行操作(每条数据加一个编辑按钮和一个删除按钮),操作完后实时的展现到前端。

urls.py中开设接口,

首先想要请求到资源就必需要开设接口(路由), 假设url为http://127.0.0.1:8000/userlist/,

from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^userlist/',views.userlist),  # 新增接口
]

根据路由与视图函数的对应关系,去app01的视图文件view.py中书写视图函数

书写视图函数

def userlist(request):
    # 查询出用户表中所有的数据
    # 方式1
    user_queryset = models.User.objects.filter()
    # 方式2
    user_queryset = models.User.objects.all()
    
    # 将用户页面返回前端,同时将查询到的用户表数据传给页面进行展示
    # 方式1
    # return render(request,'userlist.html',{'user_queryset':user_queryset})
    # 方式2 
    return render(request,'userlist.html',locals())  # 将当前名称空间(函数体局部名称空间)的所有数据传过去

接下来书写返回写用户页面userlist.html

在templates文件夹下书写userlist.html文件

展示数据功能

用表格标签table来展示数据,主要的代码就是在tbody中用模版语法for循环将每条数据展示,多写一列用于存放按钮。

<tbody>
	{% for user_obj in user_queryset %}
		<tr>
			<td>{{ user_obj.id }}</td>
			<td>{{ user_obj.username}}</td>
			<td>{{ user_obj.password }}</td>
			<td>
				<a href="" class="btn btn-success btn-xs " >编辑</a>
				<a href="" class="btn btn-danger btn-xs">删除</a>
			</td>
		</tr>
	{% endfor %}
</tbody>

编辑功能

如何能够做到用户点击编辑功能跳转到编辑界面,

方法:给用于编辑的a标签的href指定一个后缀,去urls.py中加对应的路由,然后书写视图函数,最后创建编辑页面edit_user.html

  • 第一步

    <a href="/edit_user/" class="btn btn-success btn-xs " >编辑</a>

  • 第二步

    url(r'^edit_user/',views.edit_user),

  • 第三步

    def edit_user(request):
        return render(request,'edit_user.html',locals())
    
  • 第四步

    <form action="" method="post">
    <p>用户名<input type="text" class="form-control" name="username"></p>
    <p>密码<input type="password"class="form-control" name="password"></p>
    <p><input type="submit" value="编辑" class="form-control btn btn-success btn-block"></p>
    </form>
    

如何告诉后端用户具体想要编辑哪条数据?

方法:将编辑按钮所在的那一行数据的主键值发送给后端,后端通过GET请求获取url问号后面携带参数的方式,获取编辑数据的id,通过id查找到数据对象传给编辑页面。

修改第二步:

<a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a>

修改第三步:

def edit_user(request):
    # 获取url问号后面的参数获取用户编辑的那个数据的id
    edit_id = request.GET.get('user_id')
    # 通过id查询当前用户想要编辑的数据对象
    edit_obj = models.User.objects.filter(id=edit_id).first()
    if request.method == "POST":
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 去数据库中修改对应的数据内容
        # 修改数据方式1
        # models.User.objects.filter(id=edit_id).update(username=username,password=password)
        """
            将filter查询出来的列表中所有的对象全部更新            批量更新操作
            只修改被修改的字段
        """

        # 修改数据方式2
        edit_obj.username = username
        edit_obj.password= password
        edit_obj.save()
        """
            上述方法当字段特别多的时候效率会非常的低
            从头到尾将数据的所有字段全部更新一边 无论该字段是否被修改
        """
        
        # 跳转到数据的展示页面
        return redirect('/userlist/')
    # 将数据对象展示到页面上
    return render(request,'edit_user.html',locals())

为了让用户能够知道自己编辑的那条数据原来的内容,可以将input标签value设置为数据之前的内容

修改第四步:

<p>用户名<input type="text" value="{{ edit_obj.username}}" class="form-control" name="username"></p>
<p>密码<input type="password" value="{{ edit_obj.password}}" class="form-control" name="password"></p>

这样简单的在前端编辑修改数据库中数据的功能就基本完成了。

删除数据功能

跟编辑功能的逻辑类似,但是不需要跳转到删除界面,只要在后端删除数据后跳转到展示页面即可,实时展示数据库中的数据。

删除功能视图函数:

def delete_user(request):
    # 获取用户想要删除的数据id值
    delete_id = request.GET.get('user_id')
    # 直接去数据库中找到对应的数据删除即可
    models.User.objects.filter(id=delete_id).delete()  # 批量删除
    # 跳转到展示页面
    return redirect('/userlist/')	

Ps:

真正的删除功能应该需要二次确认;删除数据内部其实并不是真正的删除,一般会给数据添加一个标识字段用来表示当前数据是否被删除了,如果数据被删了仅仅只是将字段修改一个状态,如下表:

username password id_delete
tom 123 0
jerry 123 1

0,1表示数据是否被删除,标记为删除的数据只是在查找的时候会被过滤掉而已。


djagno ORM如何建立表关系

表关系复习:

  • 表与表之间的关系

    一对多、多对多、一对一、没有关系

  • 判断表关系的方法:

    "换位思考",看是单向的一对多,还是双向的一对多,或者是双向都不满足一对多。

  • 表关系实例

    图书表、出版社表、作者表、作者详情表

    关系:

    ​ 图书和出版社是一对多的关系 外键字段建在多的那一方 book

    ​ 图书和作者是多对多的关系 需要创建第三张表来专门存储

    ​ 作者与作者详情表是一对一

ORM建立表关系

  • 图书表(Book)

    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalFielf(max_digits=8,decimal_places=2)
        # 建表关系
        # 1.图书与出版社为一对多关系,图书是多的一方,所以外键字段建在图书表里
        publish = models.ForeignKey(to='Publish')  # 默认就是与出版社表的主键字段做外键关联
        # 2.图书与作者是多对多个关系,外键建在任意一方均可,但推荐建在查询频率较高的一方,这里建在图书表中
        authors = models.ManyToManyField()  
        # 该字段是一个虚拟字段,在图书表中并不存在;是用来告诉orm图书表和作者表是多对多关系,让orm自动帮你创建第三张关系表,与MySQL中建立多对多关系不同,不需要我们自己创建多对多关系表。
    
  • 出版社表(Pubish)

    出版社表无需建外键

    class Pubish(models.Model):
        name = models.CharField(max_length=32)
        addr = models.CharField(max_length=32)
    
  • 作者表(Author)

    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.integerField()
        # 建表关系
        # 作者与作者详情是一对一的关系 外键字段建在任意一方都可以 但是推荐建在查询频率较高的表中,这里建在作者表中
        author_detail = models.OneToOneField(to='AuthorDetail')
    
  • 作者详情表(AuthorDetail)

    class AuthorDetail(models.Model):
        phone = models.BigIntegerField()  # 电话号码数字较长所以用长整型,或者直接字符类型也可以
        addr = models.CharField(max_length=32)
    

注意:如果字段对应的是ForeignKey或者是OneToOne ,那么会orm会自动在字段的后面加_id后缀,如果在创建这两个字段的时候已经加了 _id,orm还会自动在字段后继续加_id后缀,所有我们在创建的时候就不要画蛇添足了。

总结:orm建立表关系只需要在模型表中添加外键字段即可,即使是多对多关系也无需自己手动创建关系表,且方法非常的见名知意;一对多:.ForeignKey(to='Publish')、多对多:.ManyToMany...、一对一:.OneToOne...


django请求生命周期流程图

各部分作用

  • wsgiref网关接口

    1. 请求来的时候解析封装(字典)
    2. 响应走的时候打包处理(html)
  • 中间件

  • 路由层

    路由匹配,给应用程序分发路由

  • 视图层

    书写前后端交互数据的核心逻辑,

  • 模版层

    存放html文件

  • 模型层

    通过orm外接数据库,操作数据。

ps:

  1. django自带的wsgiref模块本身能够支持的并发量很小,上线后会换成uwsgi

  2. 大写WSGI跟小写的wsgiref和uwgi的关系:

    ​ 大写的WSGI表示的是协议,而wsgiref、uwsgi是实现该协议具体的功能模块

  3. 缓存数据库:

    提前已经将你想要的数据准备好了 ,可以直接获取可以提高效率和响应时间,没有再通过请求流程到数据库中拿数据,拿到数据后中间件会在缓存中存放一份数据,下次再次请求该数据直接从缓存拿即可。


路由层

路由匹配

url(r'test',views.test),
url(r'testadd',views.testadd)
"""
url方法第一个参数是正则表达式
	只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
	直接执行对应的视图函数

你在输入url的时候会默认加斜杠
	django内部帮你做到重定向
		一次匹配不行
		url后面加斜杠再来一次
"""
# 取消自动加斜杠
APPEND_SLASH = False/True	# 默认是自动加斜杠的


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 首页
    url(r'^$',views.home),
    # 路由匹配
    url(r'^test/$',views.test),
    url(r'^testadd/$',views.testadd),
    # 尾页(了解)
    url(r'',views.error),
]

无名分组

"""
分组:就是给某一段正则表达式用小括号扩起来
"""
url(r'^test/(\d+)/',views.test)

def test(request,xx):
    print(xx)
    return HttpResponse('test')
  
# 无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数

有名分组

"""
可以给正则表达式起一个别名
"""
url(r'^testadd/(?P<year>\d+)',views.testadd)

def testadd(request,year):
    print(year)
    return HttpResponse('testadd')

# 有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数

单个分组可以重复使用

url(r'^index/(\d+)/(\d+)/(\d+)/',views.index),
url(r'^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/',views.index),

有名无名分组不能混合使用

方向解析

# 通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数

# 先给路由与视图函数起一个别名
	url(r'^func_kkk/',views.func,name='ooo')
# 反向解析
	# 后端反向解析
  	from django.shortcuts import render,HttpResponse,redirect,reverse
  	reverse('ooo')
  # 前端反向解析
  	<a href="{% url 'ooo' %}">111</a>

猜你喜欢

转载自www.cnblogs.com/zhangtieshan/p/12975268.html