Django读作jango,d不发音!不发音!不发音!!!(怎么就改不了了呢)
什么是ORM
即Object-Relationl Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和SQL语句和cursor打交道,只要像平时操作对象一样操作它就可以了 。
本质上ORM还是会被转化成SQL语句去执行。只不过是为了适应Python等一众面相数据而非记录的语言(或者说除了数据库的大多数语言),做了一层的适应性封装罢了……
Django ORM入门
建表:
- 首先要继承
model.Model
类,然后定义各字段类型和表格属性 - 字段类型:
AutoField
:自增数字字段,常用作主键(系统自动管理)CharField(max_length=20)
:字符串IntegerField
:整数DateTimeField
:时间类型,包含年月日时分秒,附带时区管理ForeignKey
:外键
- 主键:
- 使用
primary_key=True
定义主键,使用class Meta
定义复合主键 - 使用复合主键或没有主键的表格会自动添加自增id作为主键
- 使用
- 外键:
- 指明是何表的主键即可
on_delete
:外键对应记录被删除后的操作,有级联删除和设空的选项等
- 其他:
- ORM不会破坏SQL的参照完整性:外键值域 = 对应表主键值域 + 空
- 修改表格信息后记得
makemigrations
和migrate
- 表格修改意味着解决冲突(如表有数据时增加非空字段须指明
default
值等) - 所以表格设计尽可能还是一遍设计对比较好
1 | class jsTable(models.Model): # 借书信息 |
2 | dzid = models.ForeignKey(dzTable, on_delete=models.CASCADE) # 读者ID |
3 | tsid = models.ForeignKey(tsTable, on_delete=models.CASCADE) # 图书ID |
4 | jysj = models.DateTimeField() # 借阅时间 |
5 | yhsj = models.DateTimeField() # 应还时间 |
6 | ghsj = models.DateTimeField(blank=True, null=True) # 归还时间(空表示未归还) |
7 | |
8 | class Meta: |
9 | unique_together = ("dzid", "tsid", "jysj") |
查询:
Django ORM最大优点就是结合了SQL的一次一集合的操纵方式和Python的一次一记录方式。
- 表格对象
表格.objects
返回一张表- 使用
filter
返回筛选后的行子集表表格.objects.filter(外键=记录, 属性=属性值)
- 注意外键需要传记录,也可以使用
外键_id=外键值
转化为值查询 表格.objects.filter(属性__gt=属性值)
表示greater,类似还有__gte
、__lt
、__lte
等表格.objects.filter(属性__contains=字符串)
用于字符串,类似还有__startswith
等
- 使用
extra
进行SQL原生语句筛选yyTable.objects.extra(where=["""datediff(curdate(), yysj) > 10"""])
- Django ORM的执行策略是懒惰的,
表格.objects.filter().filter()
只执行一次查表行为 - 同理,暂存筛选后的表格并二次筛选也不会影响到查询性能(听上去有点像视图)
- 记录对象
- 对表格进行下标访问或
for elem in 表格
都能拿到记录 表格.objects.get(属性=属性值)
允许返回唯一的记录(查询结果为0个或多个时抛出异常)- 记录中的外键非空时,仍然是记录(即对应主表的对应记录)
- 如
预约记录.读者号.email
可以方便的获得预约记录的email信息
- 对表格进行下标访问或
- 数据对象
- 记录中非外键的值是数据
外键_id
可以取得外键的值,外键.属性
同样可以获得属性值
1 | result = jsTable.objects.filter(dzid_id=dzid, tsid_id=tsid, ghsj=None) # 查未还的借书记录 |
2 | if not result.exists(): |
3 | context['msg'] = "该读者未借阅该图书!" |
4 | return render(request, 'gly_hs.html', context=context) |
5 | result = result[0] |
6 | if timezone.now() - result.yhsj > timezone.timedelta(days=0): # 逾期未还 |
7 | context['msg'] = "图书逾期归还,应该缴纳费用" + \ |
8 | str((result.yhsj - timezone.now()).days) + "元" |
9 | else: # 期限内归还 |
10 | context['msg'] = "图书期限内归还" |
增删改:
- 使用
表格.delete()
、记录.delete()
删除对应记录 - 使用
记录.属性=新数据
修改记录,并使用记录.save()
保存修改 - 使用表格的构造函数构造记录,并使用
记录.save()
保存修改
1 | item = tsTable( |
2 | isbn_id=isbn, |
3 | cfwz='图书流通室', |
4 | zt='已预约', |
5 | jbr_id=request.session.get('id') |
6 | ) |
7 | item.save() |