字段类型
Django 有丰富了字段类型, 为降低学习成本, 同时也为了维护方便, 尽量使用和数据库一致的数据类型.
数字类
IntegerField
BigIntField
FloatField
DecimalField
字符类
CharField
# 在MySQL中对应的就是varchar, 所以必须指定长度
name = models.CharField(max_length=200)TextField
遇到大的文件或图片时, 将其存放在静态资源服务器, 然后使用URI或者URL存储会更合理.
常用类
BooleanField
DateField
DateTimeField
AutoField
没有指定主键时, 当前模型会自动将一个自增id的
IntegerField
做为主键.ImageField
用来做特殊约束和校验的字段, 会校验传入数据是否图片.EmailField
用来做特殊约束和校验的字段, 会校验传入数据是否邮箱地址.
UUIDField
一般来说,uuid
会用作当前数据表的主键.
字段选项/约束
primary_key
如果为True
, 将当前字段设置为主键, 默认为False
.null
如果为
True
,Django
将在数据库中存储空值为NULL
, 默认为False
.blank
代表空白字符""
, 如果是True
, 当前字段允许为空, 默认为False
null
是数据库上的设置,blank
是字段验证上的设置.blank
设置的字段不可以为NULL
.unique
唯一约束设置, 默认为False
default
设置字段默认值时间类型
auto_now
每次保存时更新字段时间为现在, 只有调用Model.seve()
时才会生效.update_time = models.DateTimeField(auto_now=True)
auto_now_add
第一次创建对象时设置时间.create_time = models.DateTimeField(auto_now_add=True)
测试一下
创建应用
python manage.py startapp myblog |
添加模板
class Person(models.Model): |
更新同步
python manage.py makemigrations |
进入shell, 创建保存一条数据
python manage.py shell |
>> from myblog.models import Person |
回头看看数据库
数据表重构
方法一
执行
python manage.py migrate
同步失败时
- 更改
migrations
中的文件解决问题- 通过调试确认是哪个字段发生错误
方法二
数据结构发生改变时
- 删除
migrations
文件然后推倒重来django
会在数据表django_migrations
中创建同步记录, 需要删除对应的同步记录- 删除已经创建记录的表
Meta内嵌类
通过一个内嵌类Meta来定义元数据.
元数据又被称为中介数据, 用来描述数据的数据, 既“所有不是字段的东西”.
使用方法
from django.db import models |
字段选项
abstract
将当前模型类转换为抽象类, 进行migrate
的时候会被忽略, 也就不会对实体表进行修改.app_label
指定当前model
从属于哪个已经注册的应用.
一般为应用只编写视图层来处理业务逻辑. 模型层统一由一个models
模块来管理
比如博客的个人信息models
, 很多应用都会使用到, 这时就要使用app_label
来区分所属应用了.db_table
自定义表名, 不指定默认为应用名_模型名
, 一般在以下情况使用.- 目标表已经存在时
- 没有管理表的权限. 需要dba建表再开发时
- 规范数据库的表名命名时
managed
默认为True
, 为False
将不会针对当前模型创建和删除数据库表, 也就是会忽略该模型. 一般会在公司有DBA时使用.ordering
设置排序字段, 默认规则为升序.默认升序
ordering = 'order_date'
-
号表示降序ordering = ['-order_date']
ordering = ['-pub_date', 'author']?
号表示随机ordering = ['?field_name']
get_latest_by
设置获取最后一条记录的排序规则, 和模型的实例方法latest()
相关联# 升序排序 order_date 字段
get_latest_by = 'order_date'
# 降序排序 priority, 后升序排序 order_date
get_latest_by = ['-priority', 'order_date']indexes
设置索引, 同样的, 在由DBA的情况下不需要用到.class Meta:
indexes = [
models.Index(fields=['last_name', 'first_name']),
models.Index(fields=['first_name'], name='first_name_idx'),
]constraints
自定义约束class Meta:
constraints = [
# 创建一个检查约束
# 确保年龄等于18
models.CheckConstraint(check=models.Q(age__gte=18), name='age_gte_18'),
# 创建一个唯一约束
# 确保每个房间在每个日期只能被预订一次
UniqueConstraint(field=['room', 'date'], name='unique_booking')
]unique_together
多字段唯一性约束(未来可能被弃用, 了解下就行)# 一组字段名,合起来必须是唯一的
unique_together = ['driver', 'restaurant']
模型继承
直接继承
from django.db import models |
多重继承
默认情况下,Django 给每个模型一个自动递增的主键.
如果当前模型对象没有指定主键, 那么两张表主键会产生冲突, 为了解决多重继承产生的id冲突, 需要覆盖主键字段.
from django.db import models |
实例方法
save()
将对象保存到数据库(或进行更新操作)只会进行数据库操作, 并不会进行字段验证.
clean_fields()
验证模型上所有字段, 调用save()
方法时不会被自动调用.clean()
自定义模型验证的方法.validate_unique()
验证模型上所有唯一约束, 和unique_together
属性搭配使用.full_clean()
依次调用 Model.clean_fields()、 Model.clean() 和 Model.validate_unique()
latest()
获取最后一条记录, 根据get_latest_by
属性进行获取.refresh_from_db()
从数据库里刷新当前记录, 适用于数据库数据发生变动时.__str__()
用来自定义模型输出.
django.setup()
用来独立运行Django中的应用, 类似于第三方库的使用.
比如,编写一个脚本, 然后进行一些ORM操作, 同时也方便我们进行调试.
这里创建一个测试文件test.py
, 使用它来进行调试学习.
import os |
QuerySet API
QuerySet
本身被构造,过滤,切片,或者复制赋值等操作,是无需访问数据库的。
只有在你需要从数据库取出数据或者向数据库存入数据时才需要访问数据库.
下面用CRUD给这些方法进行分类
Create
save()
Retrieve
all()
获取表中所有记录.Model.objects.all()
get()
通过指定条件, 获取一条数据, 如果有多条或不存在, 则会报错.# SELECT ... WHERE id = 22;
Model.objects.get(id=22)filter()
匹配满足条件的记录, 类似于SQL
中的WHERE
语句.# SELECT ... WHERE name = name_0;
Model.objects.filter(name="name_0")Django
使用__
来作为过滤条件标识符, 后面接上关键字来进行查询.条件查询
- gt --- >
- get -- >=
- lt --- <
- lte -- <
# SELECT ... WHERE id > 22;
Model.objects.filter(id__gt=22)
# SELECT ... WHERE id <= 22;
Model.objects.filter(id__lte=22)模糊查询
- startswith --- 匹配开头
- endswith ----- 匹配结尾
- icontains ---- 匹配内容
# SELECT ... WHERE name LIKE 'Lennon%';
Model.objects.filter(name__startswith='Lennon')
# SELECT ... WHERE name LIKE '%Lennon%';
Model.objects.filter(name__startswith='%Lennon%')exclude()
匹配不匹配对象, 与filter()
逻辑相反.latest()
返回最后一条数据.
order_by()
设置排序, 可以覆盖
ordering
选项# 这里需要注意, 排序并不涉及数据库操作, 是在本地进行的
Model.objects.all().order_by("name", "id")
Update
save()
Delete
delete()
# 删除id大于
Model.objects.filter(id>=22).delete()
高级
原始SQL
遇到复杂的场景, 使用
raw()
来执行SQL
语句.
# Reader._meta.db_table -- 记录所在表名 |
多个数据库
修改mysite/settings.py
添加数据库配置.
DATABASES = { |
使用 using
参数指定数据库.
person.save(using='person') |
事务
使用transaction.atomic()
控制数据库事务
基于HTTP请求的事务
- 在
settings
中要设置ATOMIC_REQUESTS
为True
from django.db import transaction
def viewfunc(request):
# 在事务中执行的代码
...- 在
基于视图具体逻辑的事务
from django.db import transaction
def viewfunc(request):
...
with transaction.atomic():
# 在事务中执行的代码
...
注意,只有视图被限制在事务中执行。中间件在事务之外运行,同理,渲染模板响应也是在事务之外运行的。
参考文档📕
模型 | Django 文档 | Django (djangoproject.com)
模型字段参考 | Django 文档 | Django (djangoproject.com)
模型 Meta 选项 | Django 文档 | Django (djangoproject.com)
约束参考 | Django 文档 | Django (djangoproject.com)
Django 配置 | Django 文档 | Django (djangoproject.com)