前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Django 使用 ORM 操作数据库详解

Django 使用 ORM 操作数据库详解

作者头像
白墨石
发布2021-01-12 10:09:30
发布2021-01-12 10:09:30
81400
代码可运行
举报
文章被收录于专栏:生信情报站生信情报站
运行总次数:0
代码可运行

ORM 是个啥?

在python中的一个默认的编写规范是一切皆对象,这样做使得代码简洁,结构清晰,便于维护和重用代码,同时极大的提升开发效率。

同样在操作数据库时,一般我们用SQL语句来实现操作,但是放在Python中是一串冗长的字符串,不利于调试和修改,更不符合上面提到的规范。

所以,有大佬就提出ORM来替代原生的SQL语句,说白了ORM 就是要给缩写,代表着 对象-关系-映射

简写

全称

中文

O

Object

对象

R

Relational

关系

M

Mapping

映射

有了ORM,我们来看它与实际的数据库是怎么联系起来的:

数据库

ORM

数据库的表(table )

类(class)

记录,行数据(record)

对象(object)

字段(field)

对象的属性(attribute)

ORM相对原始SQL的优劣势

  • 优势
    • 专注业务逻辑开发,提升开发效率
    • 易于更新维护,重用代码
    • 会自动完成比如数据消毒,预处理,事务等功能
    • 不用编写复杂的SQL语句
  • 劣势
    • 牺牲执行效率,增加查询时间
    • 无法操作底层数据库,无法实现某些复杂操作
    • 遗忘SQL语句编写

怎么选择原生SQL和ORM

  • 对于复杂的SQL语句或数据库层面,推荐使用原始SQL
  • 对于要处理复杂的业务逻辑,加快开发,推荐使用ORM
  • ORM 相对 原始SQL在一般的业务中,损耗其实并不高,可以忽略不计

开发前准备

新建项目

配置数据库

配置模型

字段类型和参数

常用字段

代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Baimoc
# @Email   : baimoc@163.com
# @Time    : 2020/7/24 9:45

from django.db import models


class Field(models.Model):
    # 自增字段
    Auto = models.AutoField()
    # 自增字段,最大值可拓展到更大
    BigAuto = models.BigAutoField()

    # 二进制数据
    Binary = models.BinaryField()

    # 布尔型
    Boolean = models.BooleanField()
    NullBoolean = models.NullBooleanField() # 允许为空的布尔型

    # 整型
    PositiveSmallInterger = models.PositiveSmallIntegerField()  # 长度为 5字节正整数
    SmallIntegerField = models.SmallIntegerField()   # 长度为 6字节整数
    PositiveIntegerField = models.PositiveIntegerField()   # 长度为 10字节正整数
    IntegerField = models.IntegerField()   # 长度为 11字节正整数
    BigIntegerField = models.BigIntegerField()   # 长度为 20字节正整数

    # 字符串类型
    Char = models.CharField()  # varchar
    Text = models.TextField()  # longtext

    # 时间日期类型
    Date = models.DateField()  # 年月日
    DateTime = models.DateTimeField()  # 年月日时分秒
    Duration = models.DurationField()  # int,Python timedelta实现

    # 浮点型
    Float = models.FloatField()
    Decimal = models.DecimalField()  # 需要指定整数或小数有多少位

    # 高级字段
    Email = models.EmailField()
    Image = models.ImageField()
    File = models.FileField()
    FilePath = models.FilePathField()
    URL = models.URLField()
    UUID = models.UUIDField()

关系型字段

一对一(OneToOneField)

多对一(ForeignKey)

多对多(ManyToManyField)

代码语言:javascript
代码运行次数:0
运行
复制
class A(models.Model):
    one2one = models.OneToOneField(Field)


class B(models.Model):
    one2one = models.ForeignKey(A)


class C(models.Model):
    one2one = models.ManyToManyField(B)

字段参数

  • 所有字段都具有的参数
    • db_column:修改字段名
    • primary_key:主键
    • verbose_name:字段别名,备注
    • unique:值是否唯一
    • null:数据空中的值,是否允许为空
    • blank:前端表单提交时,是否可以为空,一般null=True,blank=True
    • db_index:是否建立字段索引
    • help_text:显示帮助
    • editable:后台是否可以编辑
  • 个别字段才有的参数
    • CharField
      • max_length:最大长度值
    • DateField
      • unique_for_date:该日期的值是否唯一
      • unique_for_month:该月份的值是否唯一
      • auto_now=True:更新数据时间
      • auto_now_add=True:插入数据时间
    • DecimalField
      • max_digits:多少位数
      • decimal_places:多少位小数,例子(max_digits=4,decimal_places=2),可以存储11.11,32.55
  • 关系型字段的参数
    • related_name:用于外键关联的反向查询,父表查子表
    • on_delete:当外键被删除时,要进行什么操作

自关联

例子:省市县的存储

代码语言:javascript
代码运行次数:0
运行
复制
class AddressInfo(models.Model):
    address = models.CharField(max_length=200, null=True, blank=True, verbose_name="地址")
    pid = models.ForeignKey('self', null=True, blank=True, verbose_name='自关联', on_delete=models.CASCADE)  # 写法一
    # pid = models.ForeignKey('AddressInfo', null=True, blank=True, verbose_name='自关联')  # 写法二

    def __str__(self):
        return self.address

元数据

代码语言:javascript
代码运行次数:0
运行
复制
class AddressInfo(models.Model):
    address = models.CharField(max_length=200, null=True, blank=True, verbose_name="地址")
    pid = models.ForeignKey('self', null=True, blank=True, verbose_name='自关联', on_delete=models.CASCADE)  # 写法一
    # pid = models.ForeignKey('AddressInfo', null=True, blank=True, verbose_name='自关联')  # 写法二
    note = models.CharField(max_length=200, null=True, blank=True, verbose_name="说明")

    def __str__(self):
        return self.address

    class Meta:
        # 定义数据表名
        db_table='address'
        # 按照哪个字段排序
        # ordering=('pid',)
        # 表别名
        verbose_name='地址信息'
        # 表别名复数,用于英文显示
        verbose_name_plural=verbose_name
        # 设置基类,不生成数据表,作为其他表的基类
        # abstract=False
        # 设置表权限
        # permissions=(('定义好的权限', '权限说明'),)
        # 是否按照Django既定的规则来管理模型类
        # managed=False
        # 联合唯一键
        # unique_together=('address', 'note')  # 另一种写法 ((),())
        # 定义模型类属于哪个应用
        # app_label='myapp1

实例

建表

代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Baimoc
# @Email   : baimoc@163.com
# @Time    : 2020/7/24 9:45

from django.db import models


class Teacher(models.Model):
    """讲师信息表"""
    nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name="昵称")
    introduction = models.TextField(default="这位同学很懒,木有签名", verbose_name="简洁")
    fans = models.PositiveIntegerField(default="0", verbose_name="粉丝数")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "讲师信息表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.nickname


class Course(models.Model):
    """课程信息表"""
    title = models.CharField(max_length=100, primary_key=True, db_index=True, verbose_name="课程名")
    # 老师和课程为多对一关系,使用 ForeignKey 来实现
    teacher = models.ForeignKey(Teacher, null=True, on_delete=models.CASCADE, verbose_name="课程讲师")
    type = models.CharField(choices=((1, "实战课"), (2, "免费课"), (0, "其他")), max_length=1, default=0, verbose_name="课程类")
    price = models.PositiveSmallIntegerField(verbose_name="价格")
    volume = models.BigIntegerField(verbose_name="销量")
    online = models.DateField(verbose_name="上线时间")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "课程信息表"
        verbose_name_plural = verbose_name

    def __str__(self):
        # 返回type的描述信息
        return f"{self.get_type_display(), self.title}"


class Student(models.Model):
    """学生信息表"""
    nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name="昵称")
    # 课程与学生是多对多关系
    course = models.ManyToManyField(Course, verbose_name="课程")
    age = models.PositiveSmallIntegerField(verbose_name="年龄")
    gender = models.CharField(choices=((1, "男"), (2, "女"), (0, "保密")), max_length=1, default=0, verbose_name="性别")
    study_time = models.PositiveIntegerField(default="0", verbose_name="学习时长(h)")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "学生信息表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.nickname


class TeacherAssisant(models.Model):
    """助教信息表"""
    nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name="昵称")
    teacher = models.OneToOneField(Teacher, null=True, on_delete=models.SET_NULL, verbose_name="讲师")
    hobby = models.CharField(max_length=100, null=True, blank=True, verbose_name="爱好")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "助教信息表"
        db_table = "courses_assistant"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.nickname

更改数据库表

删除模型类的步骤

  • 删除表模型
  • 删除项目中migraions文件夹下模型类生成的对应文件
  • 删除数据库migraions表中的生成记录
  • 删除数据表

导入数据

1.命令行添加

数据库中的数据表

2. 脚本添加
代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Baimoc
# @Email   : baimoc@163.com
# @Time    : 2020/7/24 15:29
# @File    : orm_data

import os
import sys
import random
import django
from datetime import date

project_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(project_path)  # 将项目路径添加到系统搜寻路径当中
os.environ['DJANGO_SETTINGS_MODULE'] = 'orm_baimoc.settings'  # 设置项目的配置文件
django.setup()

from ormbaimoc.models import Teacher, Course, Student, TeacherAssisant

def import_data():
    """使用 Django ORM 导入数据"""
    # 讲师数据
    Teacher.objects.create(nickname="Jack", introduction="Python 工程师", fans=123)
    Teacher.objects.create(nickname="Allen", introduction="Java 工程师", fans=321)
    Teacher.objects.create(nickname="Henry", introduction="Golang 工程师", fans=888)

    # 课程数据
    Course.objects.bulk_create([Course(title=f"Python 系列教程{i}",
                                       teacher=Teacher.objects.get(nickname="Jack"),
                                       type=random.choice((0, 1, 2)),
                                       price=random.randint(200,300),
                                       volume=random.randint(100, 10000),
                                       online=date(2018, 10, 1))
                                for i in range(1, 5)])
    Course.objects.bulk_create([Course(title=f"Java 系列教程{i}",
                                       teacher=Teacher.objects.get(nickname="Allen"),
                                       type=random.choice((0, 1, 2)),
                                       price=random.randint(200,300),
                                       volume=random.randint(100, 10000),
                                       online=date(2018, 6, 6))
                                for i in range(1, 4)])
    Course.objects.bulk_create([Course(title=f"Golang 系列教程{i}",
                                       teacher=Teacher.objects.get(nickname="Henry"),
                                       type=random.choice((0, 1, 2)),
                                       price=random.randint(200,300),
                                       volume=random.randint(100, 10000),
                                       online=date(2020, 11, 1))
                                for i in range(1, 3)])

    # 学生数据
    Student.objects.update_or_create(nickname="赵同学", defaults={
        "age":random.randint(18, 58),
        "gender":random.choice((0, 1, 2)),
        "study_time":random.randint(9, 999),
    })
    Student.objects.update_or_create(nickname="吴同学", defaults={
        "age": random.randint(18, 58),
        "gender": random.choice((0, 1, 2)),
        "study_time": random.randint(9, 999),
    })
    Student.objects.update_or_create(nickname="郑同学", defaults={
        "age":random.randint(18, 58),
        "gender":random.choice((0, 1, 2)),
        "study_time":random.randint(9, 999),
    })
    Student.objects.update_or_create(nickname="王同学", defaults={
        "age": random.randint(18, 58),
        "gender": random.choice((0, 1, 2)),
        "study_time": random.randint(9, 999),
    })

    # 正向添加
    # 销量大于等于 1000 的课程
    Student.objects.get(nickname="赵同学").course.add(*Course.objects.filter(volume__gte=1000))
    # 销量大于 5000 的课程
    Student.objects.get(nickname="王同学").course.add(*Course.objects.filter(volume__gt=5000))

    # 反向添加
    # 学习实践大于等于 500 小时的同学
    Course.objects.get(title="Python 系列教程1").student_set.add(*Student.objects.filter(study_time__gte=500))
    # 学习实践小于等于 500 小时的同学
    Course.objects.get(title="Python 系列教程1").student_set.add(*Student.objects.filter(study_time__lte=500))

    # 助教数据 get_or_create
    TeacherAssisant.objects.get_or_create(nickname="助教1",
                                          defaults={"hobby":"慕课网学习", "teacher":Teacher.objects.get(nickname="Jack")})
    TeacherAssisant.objects.get_or_create(nickname="助教2",
                                          defaults={"hobby": "看电影", "teacher": Teacher.objects.get(nickname="Allen")})
    TeacherAssisant.objects.get_or_create(nickname="助教3",
                                          defaults={"hobby": "读书", "teacher": Teacher.objects.get(nickname="Henry")})
    return True


if __name__ == '__main__':
    if import_data():
        print("导入数据成功")

# 其他导入数据方法
# fixtures Django serialization 保存
# 数据库层面的导入数据

Model API

基本查询

代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Baimoc
# @Email   : baimoc@163.com
# @Time    : 2020/7/26 18:39
# @File    : view

from django.shortcuts import render
from django.views.generic import View
from django.http import JsonResponse
from .models import AddressInfo, Teacher, Course,Student,TeacherAssisant


class IndexView(View):
    """主页"""

    def get(self, request):
        # 查询全部
        teachers = Teacher.objects.all()
        print(teachers)

        # 获取一个值
        # 只能返回一条结果,多条会报错
        teachers2 = Teacher.objects.get(nickname='Jack')
        print(teachers2, type(teachers2))

        # 查询符合条件的多个值
        # 返回QuerySet,可以是多条结果
        teachers3 = Teacher.objects.filter(fans__gte=500)
        for teacher in teachers3:
            print(f"讲师姓名:{teacher.nickname} --> 粉丝数:{teacher.fans}")

        # 字段数据匹配
        teacher4 = Teacher.objects.filter(fans__in=[888])
        print(teacher4)

        # 结果切片
        print(Teacher.objects.all()[:2])
        # 排序
        teacher6 = Teacher.objects.all().order_by('.fans')
        for t in teacher6:
            print(t.fans)
        # 链式查询
        teacher7 = Teacher.objects.filter(fans__gte=100).order_by('nickname')
        print(teacher7)

        # 查询原生SQL
        print(Teacher.objects.filter(fans__gte=100).order_by('nickname').query)

        return render(request, "address.html")

返回新 QuerySet API

代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Baimoc
# @Email   : baimoc@163.com
# @Time    : 2020/7/26 18:39
# @File    : view
from datetime import date

from django.db.models import Sum, Avg, Max, Min
from django.shortcuts import render
from django.views.generic import View
from django.http import JsonResponse
from .models import AddressInfo, Teacher, Course,Student,TeacherAssisant, GroupConcat


class IndexView(View):
    """主页"""

    def get(self, request):
        # 查询全部
        teachers = Teacher.objects.all()
        print(teachers)

        # 获取一个值
        # 只能返回一条结果,多条会报错
        teachers2 = Teacher.objects.get(nickname='Jack')
        print(teachers2, type(teachers2))

        # 查询符合条件的多个值
        # 返回QuerySet,可以是多条结果
        teachers3 = Teacher.objects.filter(fans__gte=500)
        for teacher in teachers3:
            print(f"讲师姓名:{teacher.nickname} --> 粉丝数:{teacher.fans}")

        # 字段数据匹配
        teacher4 = Teacher.objects.filter(fans__in=[888])
        print(teacher4)

        # 结果切片
        print(Teacher.objects.all()[:2])
        # 排序
        teacher6 = Teacher.objects.all().order_by('.fans')
        for t in teacher6:
            print(t.fans)
        # 链式查询
        teacher7 = Teacher.objects.filter(fans__gte=100).order_by('nickname')
        print(teacher7)

        # 查询原生SQL
        print(Teacher.objects.filter(fans__gte=100).order_by('nickname').query)


        # 返回新 Query API
        # 排除
        print(Student.objects.all().exclude(nickname="王同学"))
        # 排序
        print(Student.objects.all().exclude(nickname="王同学").reverse())
        # 修改返回结果的字段名,将nickname改为name
        students = Student.objects.all().extra(select={"name":"nickname"})
        for student in students:
            print(student.name)

        # 获取字典或元组形式的 QuerySet
        print(TeacherAssisant.objects.values('nickname', 'hobby'))
        # < QuerySet[{'nickname': '助教1', 'hobby': '慕课网学习'}, {'nickname': '助教2', 'hobby': '看电影'}, {'nickname': '助教3', 'hobby': '读书'}] >

        print(TeacherAssisant.objects.values_list('nickname', 'hobby'))
        # <QuerySet [('助教1', '慕课网学习'), ('助教2', '看电影'), ('助教3', '读书')]>

        print(TeacherAssisant.objects.values_list('nickname', flat=True))
        # <QuerySet ['助教2', '助教3', '助教1']>

        # 根据日期获取查询集
        print(Course.objects.dates('created_at', 'day', order='DESC'))
        # <QuerySet [datetime.date(2020, 7, 26)]>

        print(Course.objects.datetimes('created_at', 'second', order='DESC'))
        # <QuerySet [datetime.datetime(2020, 7, 26, 9, 25, 21, tzinfo=<UTC>)]>

        # 并集:union、交集:inersection、差集:difference
        p_240 = Course.objects.filter(price__gte=240)
        p_260 = Course.objects.filter(price__lte=260)
        print(p_240.union(p_260))
        # 引擎不支持会报错
        # print(p_240.inersection(p_260))
        # print(p_240.difference(p_260))

        # 一对多、多对一查询优化:select_related
        # 一对多、多对多查询优化:prefetch_related
        courses = Course.objects.all()
        for c in courses:
            print(f"{c.title} -- {c.teacher.nickname} -- {c.teacher.fans}")
        # (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
        # (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
        # (0.000) SELECT `ormbaimoc_course`.`title`, `ormbaimoc_course`.`teacher_id`, `ormbaimoc_course`.`type`, `ormbaimoc_course`.`price`, `ormbaimoc_course`.`volume`, `ormbaimoc_course`.`online`, `ormbaimoc_course`.`created_at`, `ormbaimoc_course`.`updated_at` FROM `ormbaimoc_course`; args=()
        # (0.000) SELECT `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_teacher` WHERE `ormbaimoc_teacher`.`nickname` = 'Henry' LIMIT 21; args=('Henry',)
        # (0.000) SELECT `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_teacher` WHERE `ormbaimoc_teacher`.`nickname` = 'Henry' LIMIT 21; args=('Henry',)
        # (0.000) SELECT `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_teacher` WHERE `ormbaimoc_teacher`.`nickname` = 'Allen' LIMIT 21; args=('Allen',)
        # (0.000) SELECT `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_teacher` WHERE `ormbaimoc_teacher`.`nickname` = 'Allen' LIMIT 21; args=('Allen',)
        # (0.000) SELECT `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_teacher` WHERE `ormbaimoc_teacher`.`nickname` = 'Allen' LIMIT 21; args=('Allen',)
        # (0.000) SELECT `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_teacher` WHERE `ormbaimoc_teacher`.`nickname` = 'Jack' LIMIT 21; args=('Jack',)
        # (0.000) SELECT `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_teacher` WHERE `ormbaimoc_teacher`.`nickname` = 'Jack' LIMIT 21; args=('Jack',)
        # (0.000) SELECT `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_teacher` WHERE `ormbaimoc_teacher`.`nickname` = 'Jack' LIMIT 21; args=('Jack',)
        # (0.000) SELECT `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_teacher` WHERE `ormbaimoc_teacher`.`nickname` = 'Jack' LIMIT 21; args=('Jack',)

        courses = Course.objects.all().select_related('teacher')
        for c in courses:
            print(f"{c.title} -- {c.teacher.nickname} -- {c.teacher.fans}")
        # (0.016) (SELECT `ormbaimoc_course`.`title`, `ormbaimoc_course`.`teacher_id`, `ormbaimoc_course`.`type`, `ormbaimoc_course`.`price`, `ormbaimoc_course`.`volume`, `ormbaimoc_course`.`online`, `ormbaimoc_course`.`created_at`, `ormbaimoc_course`.`updated_at` FROM `ormbaimoc_course` WHERE `ormbaimoc_course`.`price` >= 240) UNION (SELECT `ormbaimoc_course`.`title`, `ormbaimoc_course`.`teacher_id`, `ormbaimoc_course`.`type`, `ormbaimoc_course`.`price`, `ormbaimoc_course`.`volume`, `ormbaimoc_course`.`online`, `ormbaimoc_course`.`created_at`, `ormbaimoc_course`.`updated_at` FROM `ormbaimoc_course` WHERE `ormbaimoc_course`.`price` <= 260) LIMIT 21; args=(240, 260)
        # (0.000) SELECT `ormbaimoc_course`.`title`, `ormbaimoc_course`.`teacher_id`, `ormbaimoc_course`.`type`, `ormbaimoc_course`.`price`, `ormbaimoc_course`.`volume`, `ormbaimoc_course`.`online`, `ormbaimoc_course`.`created_at`, `ormbaimoc_course`.`updated_at`, `ormbaimoc_teacher`.`nickname`, `ormbaimoc_teacher`.`introduction`, `ormbaimoc_teacher`.`fans`, `ormbaimoc_teacher`.`created_at`, `ormbaimoc_teacher`.`updated_at` FROM `ormbaimoc_course` LEFT OUTER JOIN `ormbaimoc_teacher` ON (`ormbaimoc_course`.`teacher_id` = `ormbaimoc_teacher`.`nickname`); args=()

        students = Student.objects.filter(age__lt=30).prefetch_related("course")
        for s in students:
            print(s.course.all())
        # (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
        # (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
        # (0.000) SELECT `ormbaimoc_student`.`nickname`, `ormbaimoc_student`.`age`, `ormbaimoc_student`.`gender`, `ormbaimoc_student`.`study_time`, `ormbaimoc_student`.`created_at`, `ormbaimoc_student`.`updated_at` FROM `ormbaimoc_student` WHERE `ormbaimoc_student`.`age` < 30 ORDER BY `ormbaimoc_student`.`age` ASC; args=(30,)

        # 反向查询:父表查询子表
        print(Teacher.objects.get(nickname="Jack").course_set.all())
        # print(Teacher.objects.get(nickname="Jack").teacher.all())

        # annotate(): 使用聚合计数,求和,平均等
        print(Course.objects.values('teacher').annotate(vol=Sum('volume')))
        print(Course.objects.values('teacher').annotate(vol=Avg('volume')))
        print(Course.objects.values('teacher').annotate(vol=Max('volume')))
        print(Course.objects.values('teacher').annotate(vol=Min('volume')))

        # raw(),执行原始SQL


        """不返回 Query API """
        # 获取对象 ---------------------------------
        # get()
        # get_or_create()
        # first()
        print(Course.objects.first())

        # last()
        print(Course.objects.last())

        # latest(), 注意需要设置 get_latest_by = 'created_at'
        print(Course.objects.latest())

        # earliest()
        print(Course.objects.earliest())

        # in_bulk(), 批量插入数据
        print(Course.objects.in_bulk(['Golang 系列教程1', 'Python 系列教程4']))

        # 更新对象 ---------------------------------
        # update()
        Course.objects.filter(title="Golang 系列教程1").update(price=6666)
        # update_or_create()
        Course.objects.filter(title="Java 系列教程5").update_or_create(title="Java 系列教程5", price=888, volume=55, online=date(2018, 6, 6))

        # 删除对象 ----------------------------------
        Course.objects.filter(title='Java 系列教程5').delete()

        # 其他操作 exists(),count(), aggregate(),判断是否存在,统计个数,聚合
        print(Course.objects.filter(title='test').exists())
        print(Course.objects.filter(title='Golang 系列教程1').exists())
        print(Course.objects.count())
        print(Course.objects.aggregate(Max('price'), Min('price'), Avg('price'), Sum('volume')))

参考

http://www.ruanyifeng.com/blog/2019/02/orm-tutorial.html

https://www.imooc.com/video/18466

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/07/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ORM 是个啥?
  • ORM相对原始SQL的优劣势
  • 怎么选择原生SQL和ORM
  • 开发前准备
  • 字段类型和参数
    • 常用字段
    • 关系型字段
    • 字段参数
    • 自关联
    • 元数据
    • 实例
    • 更改数据库表
    • Model API
    • 返回新 QuerySet API
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档