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)

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容