Django ORM入门

表结构如下

1
2
3
4
5
6
7
8
9
10
11
from django.db import models


class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
remarks = models.CharField(max_length=255, null=True)
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
db_table = 'persons'

基础操作

filterexclude用法一致

  • 插入

    1
    2
    3
    4
    5
    6
    7
    # 方式一
    Person.objects.create(name='张三', age=22)
    # 方式二
    person = Person(name='李四', age=23)
    person.save()
    # 方式三,查询匹配到更新,否则插入
    Person.objects.update_or_create(name='张三三', defaults={'age': 100})
  • 更新

    1
    Person.objects.filter(name='张三三').update(age=F('age') + 1, remarks='我是备注')
  • 删除

    1
    2
    3
    4
    5
    # 匹配删除
    Person.objects.filter(age=23).delete()
    # 单个删除
    person = Person.objects.get(id=1)
    person.delete()
  • 简单查询

    1
    2
    3
    4
    5
    6
    7
    8
    # 简单查询, 如果未匹配到或匹配到多条则报错
    Person.objects.get(id=1)
    # 查询第一条数据
    Person.objects.first()
    # 查询最后一条数据
    Person.objects.last()
    # 查询所有数据
    Person.objects.all()
  • 条件查询

    1
    2
    3
    4
    5
    # 根据指定字段匹配查询
    Person.objects.filter(name='10号').first()
    # 多条件匹配
    Person.objects.filter(age=30, name__contains='张') # 都满足条件
    Person.objects.filter(Q(age=22) | Q(name__contains='张')) # 满足任意一个
  • 大小比较

    1
    2
    3
    4
    5
    6
    7
    8
    # 大于 
    Person.objects.filter(age__gt=40)
    # 大于等于
    Person.objects.filter(age__gte=40)
    # 小于
    Person.objects.filter(age__lt=40)
    # 小于等于
    Person.objects.filter(age__lte=40)
  • 包含

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 年龄是23, 24, 25的
    Person.objects.filter(age__in=(23, 24, 25))
    # 名字包含字符串‘张’的
    Person.objects.filter(name__contains='张')
    # 名字以‘张’开头
    Person.objects.filter(name__startswith='张')
    # 名字以‘张’结尾
    Person.objects.filter(name__endswith='张')
    # 匹配时忽略大小写,icontains/istartswith/iendswith
    Person.objects.filter(name__istartswith='a')
  • 日期/时间

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 匹配年
    Person.objects.filter(created_at__year=2022)
    # 年/月/日/周
    __month
    __day
    __week_day
    __week
    __hour
    __minute
    __second
  • 其他

    1
    2
    3
    4
    # 过滤字段是否为NULL
    Person.objects.filter(remarks__isnull=True)
    # 正则匹配,iregex 忽略大小写
    Person.objects.filter(name__regex=r'[0-9]+')

关联查询

表结构信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django.db import models


class Class(models.Model):
name = models.CharField(max_length=30)
remarks = models.CharField(max_length=255, null=True)
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
db_table = 'classes'



class Person(models.Model):
cls = models.ForeignKey(Class, on_delete=models.PROTECT, null=True)
name = models.CharField(max_length=30)
age = models.IntegerField()
remarks = models.CharField(max_length=255, null=True)
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
db_table = 'persons'
  • 关联查询

    1
    2
    3
    4
    5
    6
    7
    # 通过人查询所属班级信息
    person = Person.objects.first()
    print(person.cls.name)
    # 查询班级下的学生
    cls = Class.objects.filter(name='一一班').first()
    cls.person_set.all() # 班级里的所有人
    cls.person_set.filter(age__in=(22, 23)) # 对属于版本的学生再匹配过滤
  • 关联匹配

    1
    2
    3
    4
    # 匹配属于一一班的学生
    Person.objects.filter(cls__name='一一班')
    # 匹配一年级的学生(班级名称一开头)
    Person.objects.filter(cls__name__startswith='一')
  • 查询优化

    1
    2
    3
    4
    # 关联查询避免访问学生的班级信息时再次查询班级表
    Person.objects.select_related('cls') # sql层面
    Person.objects.prefetch_related('cls')
    Person.objects.annotate(cls_name=F('cls__name')) # 仅关联指定字段查询
  • 其他