在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
- 直接通过创建模型类对象,执行save()方法保存到数据库中。
>>> from datetime import date
>>> book = BookInfo(
btitle='西游记',
bput_date=date(1988,1,1),
bread=10,
bcomment=10
)
>>> book.save()
- 通过模型类.objects.create()保存。
>>> HeroInfo.objects.create(
hname='沙悟净',
hgender=0,
hbook=book
)
<HeroInfo: 沙悟净>
- 删:delete
- 采用get获取的对象.delete()
hero = HeroInfo.objects.get(id=13)
hero.delete()
- 采用filter获取的对象.delete()
HeroInfo.objects.filter(id=14).delete()
- 改:save、update
- 对模型类对象属性重新赋值并保存
hero = HeroInfo.objects.get(hname='猪八戒')
hero.hname = '猪悟能'
hero.save()
- 更新模型类对象属性,会返回受影响的行数
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 小于等于
其余还有些过滤查询查询也很简单,不再记录。
-
get
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)
理解用法为,最终要查询的是什么,那就把它写在前面,其关联的表在查询条件以小写表示,过滤条件用双下划线连接。