Django-ORM数据库操作及多表查询

在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据。

django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。

创建数据表对象
  • 先创建两个模型类
    图书类和英雄类,一本图书中有多个英雄。
from django.db import models

#定义图书模型类BookInfo
class BookInfo(models.Model):
    btitle = models.CharField(max_length=20, verbose_name='名称')
    bpub_date = models.DateField(verbose_name='发布日期')
    bread = models.IntegerField(default=0, verbose_name='阅读量')
    bcomment = models.IntegerField(default=0, verbose_name='评论量')
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    class Meta:
        db_table = 'tb_books'  # 指明数据库表名
        verbose_name = '图书'  # 在admin站点中显示的名称
        verbose_name_plural = verbose_name  # 显示的复数名称

    def __str__(self):
        """定义每个数据对象的显示信息"""
        return self.btitle

#定义英雄模型类HeroInfo
class HeroInfo(models.Model):
    GENDER_CHOICES = (
        (0, 'female'),
        (1, 'male')
    )
    hname = models.CharField(max_length=20, verbose_name='名称') 
    hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')  
    hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息') 
    hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 外键
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    class Meta:
        db_table = 'tb_heros'
        verbose_name = '英雄'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.hname
  • 自增主键id不需单独设置,会自动创建。
  • ForeignKey外键是设置在英雄类中的,也就是一对多关系中属于多的那一方。
  • ForeignKey不指定绑定的字段时,默认绑定主键id。
增、删、改、查
  • 增:save、create
  1. 直接通过创建模型类对象,执行save()方法保存到数据库中。
>>> from datetime import date
>>> book = BookInfo(
    btitle='西游记',
    bput_date=date(1988,1,1),
    bread=10,
    bcomment=10
)
>>> book.save()
  1. 通过模型类.objects.create()保存。
>>> HeroInfo.objects.create(
    hname='沙悟净',
    hgender=0,
    hbook=book
)
<HeroInfo: 沙悟净>
  • 删:delete
  1. 采用get获取的对象.delete()
hero = HeroInfo.objects.get(id=13)
hero.delete()
  1. 采用filter获取的对象.delete()
HeroInfo.objects.filter(id=14).delete()
  • 改:save、update
  1. 对模型类对象属性重新赋值并保存
hero = HeroInfo.objects.get(hname='猪八戒')
hero.hname = '猪悟能'
hero.save()
  1. 更新模型类对象属性,会返回受影响的行数
HeroInfo.objects.filter(hname='沙悟净').update(hname='沙僧')

  • 查询是使用得最多也是使用情况相对更复杂的,特别是涉及有外键的多表查询时。
    1. 单表基础查询:get、all

    • get
      get查询时若未扎到数据会抛出异常。
    >>> book = BookInfo.objects.get(btitle='西游记')
    >>> book.id
    
    • all
      返回所有结果对象
      >>> BookInfo.objects.all()
    
    • first
      返回符合条件的第一个结果对象。

    2. 过滤查询
    只列举filter的使用。

    • 相等:exact(可省略)
    BookInfo.objects.filter(id__exact=1)
    # 可简写为:
    BookInfo.objects.filter(id=1)
    
    • 包含:contains
      查询书名包含'传'的图书。
    BookInfo.objects.filter(btitle__contains='传')
    
    • 空查询:isnull
      查询书名不为空的图书。
    BookInfo.objects.filter(btitle__isnull=False)
    
    • 比较查询:
      语法类似,不再列举
      • gt 大于
      • gte 大于等于
      • lt 小于
      • lte 小于等于

    其余还有些过滤查询查询也很简单,不再记录。

3. 聚合函数
聚合函数包括:Avg 平均,Count 数量,Max 最大,Min 最小,Sum 求和,被定义在django.db.models中。

count查询图书总数:

BookInfo.objects.count()

order_by排序:

BookInfo.objects.all().order_by('bread')  # 升序
BookInfo.objects.all().order_by('-bread')  # 降序
4. 关联查询

最重要且最容易混淆的部分是关联查询。

  • 一到多(注意外键属性是否设置了related_name)
    (从不包含外键的表查询到包含外键的表)
    一对应的模型类对象.多对应的模型类名小写_set
b = BookInfo.objects.get(id=1)
b.heroinfo_set.all()

若外键中定义了ralated_name属性,
如当外键定义如下:

hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书', ralated_name = "book")  # 外键

则查询多到一时的语句为:

b = BookInfo.objects.get(id=1)
b.book.all()

使用定义的ralated_name名替换模型类名小写_set,这样的写法要简单方便得多。

  • 多到一
    (从包含外键的表查询到外键映射的表)
    多对应的模型类对象.多对应的模型类中的关系类属性名
h = HeroInfo.objects.get(id=1)
h.hbook
  • 访问一对应的模型类关联对象的id:
    (从包含外键的表查询到外键映射的表的id属性)
    多对应的模型类对象.关联类属性_id
h = HeroInfo.objects.get(id=1)
h.hbook_id

5. 关联过滤查询

查询方法:关联模型类名小写__属性名__条件运算符=值

例:

# 查询图书,要求图书英雄为"孙悟空"
BookInfo.objects.filter(heroinfo__hname='孙悟空')
# 查询图书,要求图书中英雄的描述包含"八"
BookInfo.objects.filter(heroinfo__hcomment__contains='八')
# 查询英雄, 要求所属书名为"天龙八部"
HeroInfo.objects.filter(hbook__btitle='天龙八部')
# 查询英雄,要求所属图书阅读量大于30
HeroInfo.objects.filter(hbook__bread__gt=30)

理解用法为,最终要查询的是什么,那就把它写在前面,其关联的表在查询条件以小写表示,过滤条件用双下划线连接。

猜你喜欢

转载自blog.csdn.net/weixin_34204057/article/details/90786462