ORM
对象映射关系
:把我们定义的对象(类),,映射到数据库的表中,Django的ORM, 是为了跟SQL语句有同样的表达能力
- DateTimeField:
True
, Django会默认填充当前时间
- choices: 在admin中, 会提供一个下拉列表
数值型
字段 |
介绍 |
AutoField int(11) |
自增主键: id = models.AutoField(primary_key=True) |
BooleanField tinyint(1) |
布尔类型字段, 一般用来记录状态标记 |
DecimalField decimal |
指定精确到多少位数: 666.66 => max_digits=5, decimal_places=2 |
IntegerField int(11) |
同AutoFields一样, 但是不自增 |
PositiveIntegerField |
同IntegerField, 但是只包含正整数 |
SmallIntegerField smallint |
小整数时一般用到 |
字符型
字段 |
介绍 |
CharField varchar |
基础的varchar类型 |
URLField |
继承自CharField, 但是实现了对URL的特殊处理 |
UUIDField char(32) |
除了PostgreSQL中使用的时UUID类型, 其他都是固定长度char(32), 用来存放生成的唯一ID |
EmailField |
继承自CharField, 但是实现了对Email的特殊处理 |
FileField |
继承自CharField, 但是实现了对文件的特殊处理 |
TextField |
longtext 继承自FileField, 用来处理图片相关数据, 在展示上会有不同 |
日期类型
字段 |
介绍 |
DateField |
对应MySQL中的data |
DateTimeField |
对应MySQL中的datatime |
TimeField |
对应MySQL中的data |
关系类型
用来关联两张表
多对多会创建一个中间表,来进行多对多的关联
字段 |
介绍 |
ForeignKey |
|
OneToOneField |
|
ManyToManyField |
|
参数
字段 |
介绍 |
null |
用于设定在数据库层面是否允许为空 |
blank |
针对业务层面, 该值是否允许为空 |
choices |
配置之后,在admin页面可以看到对应的可选项展示 |
db_column |
指定Model中的某个字段对应数据库中的哪个字段 |
db_index |
配置索引,作为查询条件的字段 |
default |
默认值配置 |
editable |
是否可编辑, 默认True。如果不想这个字段展示到页面上可以设置False |
error_messages |
用来自定义字段值校验失败时的异常显示key(null、blank、invalid、incalid_choice、unique、unique_for_date) |
help_text |
字段提示语,在页面对应字段的下方展示此配置 |
primary_key |
主键,配置后,在页面对字段的下方会展示此配置 |
unique_for_date |
针对date的联合约束,不是数据库层面的约束 |
unique_for_month |
针对月份的联合约束 |
unique_for_year |
针对年份的联合约束 |
verbose_name |
字段对应的展示文案 |
validators |
自定义校验逻辑, 同form 类似 |
QuerySet
本质是一个懒加载
的对象
可以使用链式调用
: posts = Post.objects.filter(status=1).filter(category_id=2)
posts = Post.objects.all() # 返回一个QuerySet对象,赋值给posts
available_posts = posts.filter(status=1) # 继续返回一个QuerySet对象,并赋值给available_posts
print(available_posts) # 此时根据上面的两个条件执行数据库查询操作,对应:select × from blog_post where status = 1;
支持链式调用的接口
接口 |
介绍 |
all |
查询所有数据 |
filter |
根据条件过滤数据 |
exclude |
同filter, 只是相反的逻辑 |
reverse |
把QuerySet中的结果倒叙排列 |
distinct |
用来进行去重查询 |
none |
返回空的QuerySet |
不支持链式调用
接口 |
介绍 |
get |
条件查询,存在返回实例,不存则抛出DoesNotExist异常 |
create |
直接常见一个Model对象 |
get_or_create |
根据条件查找,没有,就使用create创建 |
update_or_create |
同get_or_create, 只是用来更新操作 |
count |
返回QuerySet有多少条数据 |
latest |
返回最新的一条记录,但是需要在Meta中定义:get_latest_by = <用来排序的字段> |
earliest |
同上,返回最早的一条数据 |
first |
从当前QuerySet中获取第一条数据 |
last |
从当前QuerySet中获取最后一条数据 |
exists |
返回True或False |
blank_create |
同create,批量创建记录 |
in_blank |
批量查询,接收两个参数:id_list, filed_name |
update |
根据条件批量更新记录:Post.object.filter(owner_name=“asd”).update(title=“更新") |
delete |
同update,根据条件批量删除数据,update和delete都会触发Django的signal |
values |
当我们明确知道只需要返回某个字段的值:title_list = Post.obnjects.filter(id=1).values(“title”),返回包含dict的QuerySet |
values_list |
同values, 但直接返回的是包含tuple 的QuerySet |
title_list = Post.objects.filter(category_id=1).values_list("title", flat=True)
for title in title_list:
print(title)
进阶接口
- defer:把不需要展示的数据做延迟加载, 比如获取文章除正文外的其他字段:
posts = Post.objects.all().defer('content')
, 这样拿到的记录中就不会包含content中的内容
posts = Post.objects.all().defer('content')
for post in posts: # 此时会执行数据库查询
print("post.content") # 此时会执行数据查询, 获取到content
- only: 和defer刚好相反, 如果想只获取title中的值,可以使用only
- select_related: 可以用来处理
一对多
的关系
posts = Post.objects.all()
for post in posts: # 产生数据库查询
print(post.owner) # 产生额外的数据库查询
posts = Post.objects.all().select_related('category')
for post in posts: # 产生数据库查询, category数据也会一次性查询出来
print(post.category)
- prefetch_related: 针对
多对多
的数据:
posts = Post.objects.all().prefetch_related('tag')
for post in posts: # 产生两条查询语句, 分别查询post 和 tag
print('post.tag.all()')
常用的字段查询
字段 |
介绍 |
contains |
包含, 用来进行相似查询 |
icontains |
同contains, 只是忽略大小写 |
exact |
精确匹配 |
iexact |
同 exact, 只是忽略大小写 |
in |
指定某个集合: Post.objects.filter(id__in=[1,2])==> |
gt |
> |
gte |
>= |
lt |
< |
lte |
=< |
startswith |
以某个字符串开头, |
istartswith |
同, startswith, 只是忽略带小写 |
endswith |
以某个字符串结尾, |
iendswith |
同endswith, 只是忽略大小写 |
rang |
范围查询, 多用于时间范围, :created_time_range=(“开始时间”, “结束时间”) |
##进阶查询
F
: 执行数据库层面的计算, 从而避免出现竞争状态
post = Post.objects.get(id=1)
post.pv = post.pv + 1
post.save()
from django.db.models import F
post = Post.objects.get(id=1)
post.pv = F('pv') + 1
post.save()
Q
: 或
的关系: select * from tables where id=1 or id =10;
from django.db.models import Q
post = Post.objects.filter(Q(id=1) | Q(id=10))
post = Post.objects.filter(Q(id=1) & Q(id=10))
想得到某个分类下有多少篇文章
category = Category.objects.get(id=1)
posts_count = catecory.posts_count.count()
通过category.post_count访问, 把结果放到category
from django.db.models import Q
# 这相当于是给category动态增加了属性posts_count, (源于Count("post"))
catefories = Category.objects.annotate(post_count = Count("post"))
print(categoies[0].posts_count)
Sum
: 同Count类似,aggregate
, 只是他是用来做合计的, 比如计算所有文章加起来的访问量是多少:
from django.db.models import Sum
post.objects.aggregate(all_pv=Sum("pv")) # 输出结果: {"all_pv": 487}
评论区