0%

Django orm入门

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的参照完整性:外键值域 = 对应表主键值域 + 空
    • 修改表格信息后记得makemigrationsmigrate
    • 表格修改意味着解决冲突(如表有数据时增加非空字段须指明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()