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}
                      
                      
                     
                    
                  
评论区