Django ORM常用字段及参数
models中的常用字段
models中常用字段与数据库中的对应关系
models中常用字段 | 数据库对应字段 |
---|---|
AutoField(primary_key=True) | 主键字段 |
CharField(max_length=32) | varchar(32) |
IntegerField() | int |
BigIntergerField() | bigint |
DecimalField() | decimal |
EmailField() | varchar(254) |
DateField() | date |
DateTimeField() | datetime |
日期字段中有两个容易搞混掉的字段
- auto_now:每次编辑数据的时候都会自动更新该字段时间
- auto_now_add:创建数据的时候会把当前时间添加到数据库
常用字段拓展:
BooleanField(Field)
# 给该字段传布尔值,会对应成数字 0/1
# 通常用于两种值就可以表示属性的字段,比如
is_delete
is_status
is_vip
...
TextField(Field)
# 文本类型,用来存储大段文本
# varchar和char的最大值只有255,如果存文章的话就用到该字段
FileField(Field)
# 存的是字符串,路径保存在数据库,文件上传到指定目录,只存文件路径
upload_to = '指定文件路径'
# 给该字段传文件对象,文件会自动保存到upload_to指定的文件夹下,然后该字段存文件的路径
如何自定义一个char类型字段
from django.db.models import Field
class RealCharField(Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length # 拦截一个父类的方法,操作完后利用super调用父类的方法
super().__init__(max_length=max_length, *args, **kwargs)
def db_type(self, connection):
return 'char(%s)' % self.max_length
# 自定义一个类,添加我们自定义的RealCharField测试一下
class Movie(models.Model):
testField = RealCharField(max_length=64, null=True)
字段内的关键字参数
之前用过的很常见的比如:
- null:可以将该字段设置为空
- default:可以设置默认值
- unique:如果设置为unique=True则该字段在表中必须是唯一的
- db_index:如果db_index=True代表着此字段设置索引
ForeignKey外键关系:
- ForeignKey:表示外键关联关系,一般把该字段设置在"一对多"多的一方
- to:设置要关联的表
- to_field:设置要关联的表的字段
- on_delete:当删除关联表中的数据时,当前表与其关联的行的行为
- models.CASCADE:删除关联数据,与之关联也删除(级联删除)
- db_constraint:在数据库中创建外键约束,默认为True
Django终端打印SQL语句
在Django项目的settings.py文件中,在最后或任意位置复制粘贴如下代码:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
配置好之后,再执行任何对数据库进行操作的语句时,会自动将Django执行的sql语句打印到pycharm终端上
choice参数
当你的数据能够被你列举完全,就可以考虑使用该参数
比如:用户的性别(男/女)、婚否(已婚/未婚)、在职(在职/离职)
举个简单的例子
# 创建一个表
class UserInfo(models.Model):
username = models.CharField(max_length=32)
gender_choices = (
(1, '男'),
(2, '女'),
(3, '其他'),
)
gender = models.IntegerField(choices=gender_choices)
# 该字段还是存数字,并且可以存匹配关系之外的数字
user_obj = models.UserInfo.objects.get(pk=1)
print(user_obj.username, user_obj.gender) # 1
# 针对choice参数字段取值的时候 get_xxx_display()
print(user_obj.gender) # 1
print(user_obj.get_gender_display()) # 男
# 针对没有注释信息的数据 get_xxx_display()获取到的还是数字本身
数据库查询优化(面试问题)
only和defer
-
only:
res = models.Book.objects.only('title')
-
only作用:
括号内传字段,得到的结果是一个列表套数据对象,该对象内只含有括号内指定的字段属性,对象点该字段属性,是不会走数据库的,但是一旦点非括号内的字段,也能够拿到数据,但是是重新走的数据库查询 -
defer:
res = models.Book.objects.defer('title')
-
defer作用:defer与only相反
括号内传字段,得到的结果是一个列表套数据对象,该对象内没有括号内指定的字段属性对象点该字段属性,是重复走数据库,但是一旦点非括号内的字段,也能够拿到数据,但是就不走数据库查询了
select_related和prefetch_related
-
select_related:
res = models.Book.objects.select_related('publish')
-
select_related介绍和作用:
内部是链表操作,先将关系表全部链接起来,之后在一次性查询出来,封装到对象中,数据对象之后再获取任意表中的数据的时候都不需要再走数据库了,因为全部封装成了对象的属性
select_related括号内只能传外键字段,并且不能是多对多字段,只能是一对多或一对一字段可以传入多个外键字段
(外键字段1__外键字段2__外键字段3
) -
prefetch_related:
res = models.Book.objects.prefetch_related('publish')
-
prefetch_related介绍与作用:
内部是子查询,但是给我们的感觉是链表操作,内部通过子查询将外键关联表中的数据也全部封装到对象中,之后对象点当前表或者外键关联表中的字段也都不需要走数据库了
两者的区别(根据应用环境而定):
"""
select_related:
连表操作,好处在于只走一次SQL查询
耗时耗在连接表的操作
"""
"""
prefetch_related
子查询,走两次SQL查询
耗时耗在查询次数
"""
Django ORM如何开启事务操作
事务的四大特性(ACID)
简单介绍一下,具体查看MySQL了解知识篇中的事务详解
- 原子性:事务是一个不可分割的单位
- 一致性:与原子性绑定在一起的,事务的操作要么同时成功,要么同时失败
- 隔离性:事务与事务之间互不干扰
- 持久性:事务的操作提交(commit)之后,永久改变数据
提交之后,不可回滚(rollback)
MySQL中开始事务:start transaction
Django ORM开启事务:
from django.db import transaction
with transaction.atomic():
pass
# 在with代码块中执行的orm语句同属于一个事务,代码块运行结束事务随之结束
MTV与MVC模型(了解)
MTV
- M:models
- T:templates
- V:views
MVC
- M:models
- V:views
- C:controller(控制器,路由分发)
本质 :MTV本质上也是MVC