Django Orm 查询总结

lxf2023-05-16 01:14:32

Django提供了一套非常方便的类似lingQ的通过对象调用的方式操作数据库表的Orm框架,关于Django Orm的操作方式做下整理。

Django Orm 操作主要分为以下几类:

  1. 增-向表内插入一条数据
  2. 删-删除表内数据(物理删除)
  3. 改-update操作更新某条数据
  4. 查-基本的表查询(包括多表、跨表、子查询、联表查询)

其中比较复杂的是表查询,放到最后讲解。

下面分类讲解这几种操作方式:

1. 增-向表内插入一条数据

关于 新增记录的操作这里分为两种方式

第一种方式,通过模型对象的save()方法

        userObj=User()
        userObj.username= request.data.get('username')
        # userObj.password= make_password(request.POST.get('password'),None,'pbkdf2_sha256')  # 创建django密码,第三个参数为加密算法
        userObj.set_password(request.data.get('password'))  # 创建django密码,第三个参数为加密算法
        userObj.name= request.data.get('name')
        userObj.phone= request.data.get('phone')
        userObj.email= request.data.get('email')
        userObj.create_name= request.data.get('create_name')
        userObj.update_name= request.data.get('update_name')
        userObj.is_superuser= 0
        print(userObj.username)
        print('username %s' % (userObj.username))
        print('password %s' % (userObj.password))
        userObj.save()

这种方式通过线创建一个模型对象,赋值,最后调用模型的 .save()方法的方式向数据库插入一条数据。

第二种方式,通过objects.create的方式直接新增,类似一种缩略的方式,比较简单

res = models.User.objects.create(username='admin',make_password='123456',register_time=datetime.datetime.now())

2. 删-删除表内数据(物理删除)

django删除表数据是通过 .delete()方法,举例:

如果我们只删除 user表 主键为1的记录

ret = models.User.objects.get(pk=1).delete()

上述是只删一条记录,删除多条记录类似:

ret = models.User.objects.filter(pk__gt=1).delete()

这样我们可以批量删除user表中主键值大于1的其他所有记录。

需要提醒的是,这种方式属于物理删除,删除后不可恢复,如需逻辑删除,参考下面 update的方式。

3. 改-update操作更新某条数据

django orm 的改操作,这里分为三种方式。

我们先按单记录的更新讲解,批量更新类似:

第一种,指定更新字段更新:

ret = models.User.objects.get(pk=1).update(username='admin',password='123456')

第二种,通过 Json 更新:

object = {'username':'admin','password':'123456'}
ret = models.User.objects.get(pk=1).update(**object)

第三种,类似增操作,直接通过.save()方法更新整条记录

        userObj=User()
        userObj.id= request.data.get('id')
        userObj.username= request.data.get('username')
        # userObj.password= make_password(request.POST.get('password'),None,'pbkdf2_sha256')  # 创建django密码,第三个参数为加密算法
        userObj.set_password(request.data.get('password'))  # 创建django密码,第三个参数为加密算法
        userObj.name= request.data.get('name')
        userObj.phone= request.data.get('phone')
        userObj.email= request.data.get('email')
        userObj.create_name= request.data.get('create_name')
        userObj.update_name= request.data.get('update_name')
        userObj.is_superuser= 0
        print(userObj.username)
        print('username %s' % (userObj.username))
        print('password %s' % (userObj.password))
        userObj.save()

这种方式不太建议用,需要注意数据的完整性。

4. 查-基本的表查询(包括多表、跨表、子查询、联表查询)

基本查询

需要了解如下方法的使用: (1)all() 查询所有数据

(2)filter() 带有过滤条件的查询 where

(3)get() 获取单条,查询不到会报错

(4)first() 取queryset里第一条记录

(5)last() 取queryset里最后一条记录

(6)values() 指定要获取的字段

eg. `models.User.objects.filter(pk=1).values('username','phone')`

    #返回 <QuerySet [{'username': 'admin', 'phone': '176****'}]>

(7)values_list() 列表套元祖

```js
 eg. models.User.objects.filter(pk=1).values_list('username','phone')

        #返回 <QuerySet [('admin','176***')]>
```

(8)distinct() 去重

```js
ret = models.User.objects.filter(pk=1).distinct()
```

需要注意,这里去重是针对整条数据的去重,主键不一样也不会去重

(9)order_by() 排序

```js
ret = models.User.objects.order_by('username')# 默认升序
ret = models.User.objects.order_by('-username')# 降序
```

(10)reverse() 反转,前提已排序

```js
ret = models.User.objects.order_by('username').reverse()# 默认升序
ret = models.User.objects.order_by('-username').reverse()# 降序
```

(11)count() 当前查询条件的记录数

```js
ret = models.User.objects.filter(pk=1).count()
```

(12)exclude() 排除 ,相当于查询条件不等于

```js
ret = models.User.objects.exclude(pk=1)
```

(13)exists()记录是否存在,不太实用,不过多讲

双下划线查询条件

django不支持 类似:>=,<=等查询判断方式,但提供了一套很好用的方法:

__gt <=> 大于

ret = models.User.objects.filter(id__gt=1)#查询id>1的记录

__lt <=> 小于

ret = models.User.objects.filter(id__lt=1)#查询id<1的记录

__gte <=> 大于等于

ret = models.User.objects.filter(id__gte=1)#查询id>=1的记录

__lte <=> 小于等于

ret = models.User.objects.filter(id__lte=1)#查询id<=1的记录

__in <=> 条件是否归属所给的选择

ret = models.User.objects.filter(id__in=[1,2])#查询id=1或id=2的记录

__range <=> 范围

ret = models.User.objects.filter(id__range=[1,3])#查询1<=id<=3的记录

__contains <=> 模糊查询 ,区分大小写

ret = models.User.objects.filter(username__contains='a')#查询 username like '%a%'的记录

__icontains <=> 模糊查询 ,不区分大小写

ret = models.User.objects.filter(username__icontains='a')#查询 username like '%a%'的记录

__startswith <=> 模糊查询 ,指定内容开始

ret = models.User.objects.filter(username__icontains='a')#查询 username like 'a%'的记录

__endswith <=> 模糊查询 ,指定内容结束

ret = models.User.objects.filter(username__icontains='a')#查询 username like '%a'的记录

多表查询:

一对多 多表外键查询参考另一篇博客:

Dgango 外键关联查询

表结构 多对多结构。

我们先定义两张表:User表(用户表),Artile表(文章表),一篇文章可以被多个用户关注,一个用户也可以关注多篇文章,二者是多对多的关系。

graph TD
用户表 --> 文章表
文章表 --> 用户表

from django.db import models
import datetime

class Artile(models.Model):
    """
        title: 标题
        sub_title: 子标题
        content: 内容
    """
    def __str__(self):
        return self.title
    title = models.CharField(max_length=250,default='',verbose_name='标题')
    sub_title = models.CharField(max_length=250,default='',verbose_name='子标题')
    content = models.CharField(max_length=2000,default='',blank=True,verbose_name='内容')
    # 与User表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
    users = models.ManyToManyField(to='User', )
    create_time = models.DateTimeField(default=datetime.datetime.now(),verbose_name='创建时间')
    create_name = models.CharField(max_length=20,verbose_name='创建人')
    update_time = models.DateTimeField(default=datetime.datetime.now(),blank=True,verbose_name='更新时间')
    update_name = models.CharField(max_length=20,verbose_name='更新人',blank=True,)
    is_delete = models.IntegerField(default=0,verbose_name='删除状态',blank=True,) # 逻辑删除 0 正常 1:删除

    class Meta:
        verbose_name = "文章"
        verbose_name_plural = verbose_name
        app_label = 'webApi'
from django.db import models
import datetime
#引入系统用户的分类
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.hashers import make_password #密码加密

#userProfile继承AbstractUser分类,进行拓展
class User(AbstractUser):
    """
        name: 昵称
        account: 用户名
        pwd: 密码
        phone:手机号
        email:邮箱
        avator:头像
        group_id:归属组
    """
    def __str__(self):
        return self.account
    name = models.CharField(max_length=20,default='',verbose_name='昵称')
    phone = models.CharField(max_length=20,default='',blank=True,verbose_name='手机号')
    email = models.CharField(max_length=20,default='',blank=True,verbose_name='邮箱')
    avator = models.CharField(max_length=200,default='',blank=True,verbose_name='头像')
    group_id = models.CharField(max_length=50,default='',blank=True,verbose_name='组')
    create_time = models.DateTimeField(default=datetime.datetime.now(),verbose_name='创建时间')
    create_name = models.CharField(max_length=20,verbose_name='创建人')
    update_time = models.DateTimeField(default=datetime.datetime.now(),blank=True,verbose_name='更新时间')
    update_name = models.CharField(max_length=20,verbose_name='更新人',blank=True,)
    is_delete = models.IntegerField(default=0,verbose_name='删除状态',blank=True,) # 逻辑删除 0 正常 1:删除
    # blank=True, 可选字段

    class Meta:
        verbose_name = "用户"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username
    # 明文密码转加密
    def set_password(self, password):
        print('set_password %s' % (password))
        self.password = make_password(password,'jxy','pbkdf2_sha256')
    # 验证密码是否匹配
    def check_password(self, password):
        print('password: %s' % (password))
        print('check_password: %s' % (make_password(password,'jxy','pbkdf2_sha256')))
        print('self.password: %s' % (self.password))

        return self.password == make_password(password,'jxy','pbkdf2_sha256')

注意我们在Artile表中定义的 users = models.ManyToManyField(to='User'),通过这种定义方式,我们在 Artile表与User表之间创建了一个针对这两张表的关系表。

接下来我们向这张关系表中添加几条关系。

比如,我们将 Artile表主键为1的一条记录,添加User表 主键为1,2两条关系。

user1 = models.User.object.filter(pk=1).first()
user2 = models.User.object.filter(pk=2).first()

artile1 = models.Artile.object.filter(pk=1).first()
artile1.users.add(user1,user2)

# 方法二
userSet = models.User.object.filter(pk__in=[1,2]).all()
artile1.users.add(*userSet)

这样便在关系表中创建了 Artile表主键为1的记录 与 User表 主键为1,2的两条关系

另外清除关系绑定用法类似,使用remove替代add:

artile1 = models.Artile.object.filter(pk=1).first()
userSet = models.User.object.filter(pk__in=[1,2]).all()
artile1.users.remove(*userSet) #解绑指定关系
artile1.users.clear() #清空所有关系

多对多查询:

正向查询,例如查询Artile表第一条记录有哪些用户关注:

artile1 = models.Artile.object.filter(pk=1).first()
print(artile1.users.all().values('username')) # 打印关注Artile表第一条记录的用户名称

逆向查询,例如查询User表第一条记录关注过哪些Artile:

user1 = models.User.object.filter(pk=1).first()
print(user1.artile__set.all().values('title')) # 打印User表第一条记录关注的文章名称
本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!