Django之ORM详解(字段与记录的增删改查)

Django ORM简介

简介:

# 什么是ORM : 其实就是对象关系的映射
简单来讲: ORM就是能够让一个不会sql语句的小白也能够通过python面向对象的代码方式简单快捷的操作数据库
不足之处: 封装程度太高 有时候sql语句的效率偏低 需要你自己写SQL语句

ORM中的类相当于>>>>>数据库中的表

ORM中的对象相当于>>>>>数据库中的记
	
对象的属性相当于>>>>>数据库中记录某个字段对应的值

models.py:

# ORM需要在应用下面的models.py文件来操作

# 示例:
class User(models.Model):  # 相当于创建一个表,表名为User
    id = models.AutoField(primary_key=True,verbose_name='主键')
    # 相当于SQL:id int primary_key auto_increment
    username = models.CharField(max_length=32,verbose_name='用户名')
    # 相当于SQL:username varchar(32)
    """
    CharField必须要指定max_length参数 不指定会直接报错
    verbose_name该参数是所有字段都有的 就是用来对字段的解释
    """
    password = models.IntegerField(verbose_name='密码')
    # 相当于SQL:password int
    
#  注意:orm只能操作表,所以需提前定义好库

注意:

# 在完成ORM语句操作后需要执行数据库迁移命令

************************* 数据库迁移命令 **************************
python3 manage.py makemigrations    # 将操作记录记录到migrations文件夹里

python3 manage.py migrate   # 将操作真正的同步到数据库中
******************************************************************

# 只要你修改了models.py中跟数据库相关的代码 就必须重新执行上述的两条命令

# app01_user就是利用ORM创建的表 
为什么自动加了前缀:因为django项目可以有多个应用,那么多个应用之间可能出现表名冲突的情况,加上前缀就可以完全避免这种情况。

# 举例:
app01应用创建了一个表名为User
app02应用也创建了一个表名为User
那么这时在迁移数据库的时候就会产生两个相同名字的表,这样就产生冲突,所以Django会自动给ORM创建的表前加一个应用名前缀。

# 验证是否同步:

主键字段的省略:

# 由于一张表中必须要有一个主键字段 并且一般情况下都叫id字段
# 所以orm当你不定义主键字段的时候 orm会自动帮你创建一个名为id主键字段
# 也就意味着 后续我们在创建模型表的时候如果主键字段名没有额外的叫法 那么主键字段可以省略不写

# eg :
    
class Author(models.Model):
    username = models.CharField(max_length=32)      # username varchar(32)
    password = models.IntegerField()    # password int

补充:

# 在pycharm中可直接通过
Tools >> Run manage.py Task.. 来直接进行数据库迁移命令,无需通过manage.py文件

# 命令:
makemigrations
migrate

利用ORM进行对字段的增删改查操作

# 字段的增加(在字段有数据的情况下,添加新的字段时,是需要给出新字段所对应的数据的)  方式如下:

	1.可以在终端内直接给出默认值

2.该字段可以为空
    info = models.CharField(max_length=32,verbose_name='个人简介',null=True)
3.直接给字段设置默认值
    hobby = models.CharField(max_length=32,verbose_name='兴趣爱好',default='study')

# 字段的修改
直接修改代码 然后直接执行数据库迁移的命令即可
eg: 
    # 将字段info字段的字符长度varchar(32)改为varchar(64)
    
info = models.CharField(max_length=64,verbose_name='个人简介',null=True)

# 注意只要修改了models文件下的ORM操作就必须实行数据库迁移命令
python3 manage.py makemigrations
python3 manage.py migrate
# 字段的删除
直接删除或者注释掉代码,然后执行数据库迁移命令即可

# 注意:执行完毕之后字段对应的数据也都没有了
总结:在操作models.py文件的时候一定要细心
	千万不要注释掉了一些字段
    执行迁移命令之前一定要检查一下自己的代码

利用ORM进行对数据的增删改查操作

我们来写一个简单的登录注册功能来介绍:

# 登录
def login(request):
    # 返回一个登录界面
    if request.method == 'POST':
        username = request.POST.get('username')   # 获取用户在前端页面书写的用户名与密码(post请求提交的数据)
        password = request.POST.get('password')
        # 去数据库中查询数据并校验
        from app01 import models   # 导入数据库
        
        
       
        user_obj = models.User.objects.filter(username=username).first()   # filter可看作为sql语句中的:where筛选条件
        # .first()相当于索引[0]取第一个对象(由于有筛选条件这里只有一个数据对象,但是为列表的形式,需要取出来进行下一步操作)
        # 相当于sql语句:select * from user where username='gary'
        # 返回结果 :<QuerySet [<User: User object>]>  [数据对象1,数据对象2...]

        if user_obj:
            if int(password) == user_obj.password:   # 这里因为存储的为int类型数据,需要转一下类型(也可存储时存为varchar类型)
                return HttpResponse('登陆成功')
            else:
                return HttpResponse('密码错误')
        else:
            return HttpResponse('用户名不存在')
    return render(request,'login.html')    #  初始页面

# 注册
def reg(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        from app01 import models
        res = models.User.objects.create(username=username,password=password)
        # .create为插入新的数据:指定字段username和password插入用户输入的用户名和密码
        print(res)   # 返回结果为:当前数据对象

    return render(request,'reg.html')
# 所以:数据的查
格式 :models.表名.objects.filter(条件)
res = models.User.objects.filter(username=username)
"""
返回值你先看成是列表套数据对象的格式
它也支持索引取值 切片操作 但是不支持负数索引
它也不推荐你使用索引的方式取值
user_obj = models.User.objects.filter(username=username).first()
"""
filter括号内可以携带多个参数 参数与参数之间默认是and关系
你可以把filter联想成where记忆
# 所以:数据的增
格式 :models.表名.objects.create(条件)
res = models.User.objects.create(username=username,password=password)
    
# 方式二:
user_obj = models.User(username=username,password=password)
user_obj.save()

这里我们再来写一个修改用户名和密码的功能来表述数据的修改功能的使用

补充几个知识点:在编写代码的时候都要用到

查询出用户表的所有数据:

views.py文件:

方式一:models.表名.objects.filter()   # 括号内不添加任何筛选条件
方式二:models.表名.objects.all()      # 通过all的内置方法获取(推荐使用)

# ORM提供的for循环
可在html代码体中 直接输入for然后按tab键即可自动补全,并且自动识别views.py文件中(locals())方法 所传过来的名称空间中的名字。

格式:
{% for 循环参数 in 所接收的对象 %}

{% endfor %}


# eg :  

{% for user_obj in user_queryset %}   # 循环所有的用户对象
	<p>{{ user_obj.username }}</p>   # 模板语法:拿到对象中的username对应的值
{% endfor %}
# 模板语法使用场景:

1.html编写<a>标签时href属性可编写url路由后缀
# eg:跳转到url后缀为/edit_user/
<a href="/edit_user/">a标签</a>

2.在编写路径时可使用?号后面的参数来代表不同属性的页面
<a href="/edit_user/?user_id={{ user_obj.id }}">a标签</a>  # 通过模板语法{{}}就可以使用后端传过来的对象的方法和属性
# 所以这里用到模板语法来取到每一个数据的主键值,这样就可作为每一个页面的唯一标识(每一个用户的id),这样即可操作不同的用户数据。

实操:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    # 登录功能
    url(r'^login/',views.login),
    # 注册
    url(r'^reg/',views.reg),
    # 所用用户列表
    url(r'^userlist/',views.userlist),
    # 编辑页面
    url(r'^edit_user/',views.edit_user),
    # 删除页面
    url(r'^/delete_user/',views.delete_user)
]

views.py

from app01 import models
# 展示用户所有的数据
def userlist(request):
    # 查询用户表里面所有的数据
    # 方式一:不添加筛选条件
    # data = models.User.objects.filter()
    # print(data)

    # 方式二:
    user_queryset = models.User.objects.all()
    return render(request,'userlist.html',locals())  # locals会将当前名称空间(userlist函数中)中的名字全部传给ureslist.html



# 编辑功能
def edit_user(request):
    edit_id = request.GET.get('user_id')   # 获取url问好(?)后面的参数
    # 查询当前用户想要编辑的对象
    edit_obj = models.User.objects.filter(id=edit_id).first()
    if request.method == 'POST':
        username = request.POST.get('username')  # 这里获取的是用户输入的值(post请求提交的数据)
        password = request.POST.get('password')
        
        # 去数据库中修改对应的数据内容
        # 修改方式一:(推荐使用) 能够自动识别被修改的字段,只修改被修改的字段,其他字段不动
        models.User.objects.filter(id=edit_id).update(username=username,password=password)
        # 筛选出id=edit_id的对象,并使用.update将filter筛选出来的数据进行修改(括号内为修改指定的元素)

        # 修改数据方式二:通过对象(.)属性的方式然后在.save()的方式保存
        '''
        edit_obj.username = username
        edit_obj.password = password
        edit_obj.save()
        ''' 
        # 缺点: 当字段特别多的时候效率会特别的低  这种方式会从头到尾将数据的所有字段全部更新 无论该字段是否被修改

        return redirect('/userlist/')  # 重定向:跳转到最初的页面

    # 将数据对象展示到页面上
    # 编辑页面这里暂时展示的是和注册页面大致一样
    return render(request,'edit_user.html',locals())
# 删除功能
def delete_user(request):
    # 获取用户想要删除的数据id值
    delete_id = request.GET.get('user_id')
    # 直接去数据库中找到对应的数据删除即可
    models.User.objects.filter(id=delete_id).delete()  # 批量删除:将id匹配到的这行数据全部删除

    return redirect('/userlist/')   # 删除完数据后,再重定向到初始页面即可。

userlist.html

<h1 class="text-center">数据展示</h1>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <table class="table table-striped table-hover">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>USERNAME</th>
                        <th>PASSWORD</th>
                        <th>ACTION</th>
                    </tr>
                </thead>
                <tbody>
                    <!--for循环出接收到的对象列表中的所有对象-->
                    {% for user_obj in user_queryset %}
                        <tr>
                            <td>{{ user_obj.id }}</td>
                            <td>{{ user_obj.username }}</td>
                            <td>{{ user_obj.password }}</td>
                            <td>
<!--跳转到url后缀为/edit_user/,将编辑按钮所在的那一行数据发送给后端,?后边的参数不参与路径匹配 携带当前按钮所对应的主键值--> 
                                <a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a>
                                <a href="/delete_user/" class="btn btn-danger btn-xs">删除</a>
                            </td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>

edit_user.html

<!--此处编辑功能暂时和注册页面相仿-->
<h1 class='text-center'>编辑</h1>
<div class="container">
    <div class="col-md-8 col-md-offset-2">
        <form action="" method="post">
            <p>username:
                <!--这里的value值是为了展示用户编辑之前的数据-->
                <input type="text" name="username" class="form-control" value="{{ edit_obj.username }}">
            </p>
            <p>password:
                <input type="password" name="password" class="form-control" value="{{ edit_obj.password }}">
            </p>
            <input type="submit" class="btn btn-block btn-info" value="编辑">
        </form>
    </div>
</div>

#综上 故: 数据的修改

        # 修改方式一:(推荐使用) 能够自动识别被修改的字段,只修改被修改的字段,其他字段不动
        # 筛选出id=edit_id的对象将filter查询出来的列表中所有的对象全部更新 但是有筛选条件的限制,从逻辑上这里只修改符合筛选谈条件的
        			models.User.objects.filter(id=edit_id).update(username=username,password=password)

        # 修改数据方式二:通过对象(.)属性的方式然后在.save()的方式保存
        '''
        edit_obj.username = username
        edit_obj.password = password
        edit_obj.save()
        ''' 
        # 缺点: 当字段特别多的时候效率会特别的低  这种方式会从头到尾将数据的所有字段全部更新 无论该字段是否被修改
#综上 故: 数据的删除
models.User.objects.filter(id=edit_id).delete()

补充:
# 真正的删除功能应该需要二次确认 我们这里只是为了演示删除的功能。
# 删除数据内部其实并不是真正的删除 我们会给数据添加一个标识字段用来表示当前数据是否被删除了,如果数据被删了仅仅只是讲字段修改一个状态
username   password	     is_delete(状态)
 gary		123				0
 jack		123				1
# 如果用户注销了该用户 只是将这条用户数据的状态改为1而已 并没有从数据库删除掉。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值