文章目录
Django的对象关系映射系统(Object-Relational Mapper, ORM)提供了丰富的数据查询接口, 无需使用原生SQL语句即可通过对模型的简单操作实现对数据库里的数据进行 增删改查。查询得到的结果叫 查询集(QuerySet), 所以这个接口被称为QuerySet API
Article模型如下所示:
from django.db import models
class Article(models.Model):
title = models.CharField('标题', max_length=200, unique=True)
body = models.TextField('正文')
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
1. 增
1. 方法1:save()
from .models import Article
article = Article(title="My first article", body="My first article body")
article.save()
- 该方法如果不主动save(), 创建的对象实例只会存于内存之中,不会保存到数据库中,create方法弥补了该缺点
2. 方法2:create()
article = Article.objects.create(title="My first article", body="My first article body")
- 为了避免重复创建数据表中已存在的条目,Django还提供了get_or_create()。它会返回查询到的或新建的模型对象实例,还会返回这个对象实例是否是刚刚创建的
obj, created = Article.objects.get_or_create(title="My first article", body="My first article body")
- 对Django自带auth模块中的User模型操作,比如创建新的用户时,使用用create_user()。该方法会将密码自动加Hash存储到数据库中
from django.contrib.auth.models import User
user = User.objects.create_user(username='john, email='john@gmail.com',password='somepwd')
3. 方法3:bulk_create()
- 向数据库中插入多条数据时,每使用save或create方法保存一条就会执行一次SQL。而**bulk_create()**可以一次SQL添加多条数据,效率要高很多
# 内存生成多个对象实例
articles = [Article(title="title1", body="body1"), Article(title="title2", body="body2"), Article(title="title3", body="body3")]
# 执行一次SQL插入数据
Article.objects.bulk_create(articles)
2. 删
# 1. 删除一条数据
Article.objects.get(pk=5).delete()
# 2. 删除多条数据
Article.objects.filter(title__icontains="python").delete()
# 3. 删除全部数据
Article.objects.all().delete()
3. 改
1. 方法1:save()
article = Article.objects.get(id=1)
article.title = "New article title"
article.save()
2. 方法2:update()
# 1. 更新单条数据
article = Article.objects.get(id=1).update(title='new title')
# 2. 更新多条数据
article = Article.objects.filter(title__icontains='python').update(title='Django')
3. 方法3:bulk_update()
# 一次性更新多条数据
articles = [Article.objects.get(id=1), Article.objects.get(id=2)]
articles [0].title = "new title 1"
articles [1].title = "new title 2"
Article.objects.bulk_update(articles, ["title"])
4. 查
1. 查询所有数据
# QuerySet类型,实例对象列表,方法:all()
Article.objects.all()
# 字典列表
Article.objects.all().values()
# 只获取title-字典形式
Article.objects.all().values('title')
# 只获取title列表- 元组形式,只有value,没有key
Article.objects.all().values_list('title')
# 只获取title列表,只有value
Article.objects.all().values_list('title', flat=True)
2. 查询一条数据
# id 不存在会报错,方法:get()
article = Article.objects.get(id=11)
# id 不存在不会报错,方法:filter()
article = Article.objects.filter(id=1).first()
# 更好的方法,方法:get_object_or_404()
from django.shortcuts import get_object_or_404
article = get_object_or_404(Article, pk=1)
3. 查询多条数据
1. 按大于、小于及不等于查询
# gte:大于等于,lte:小于等于
articles = Article.objects.filter(id__gte=2).filter(id__lte=11)
# 不等于
articles = Article.objects.exclude(id=10)
2. 按范围查询
# 按范围查询,in或者range
articles = Article.objects.filter(id__range=[2, 11])
articles = Article.objects.filter(id__in=[3, 6,9])
3. 字符串模糊查询
#标题包含python,若忽略大小写使用 icontains
articles = Article.objects.filter(title__contains='python')
#标题以python开头,若忽略大小写使用 istartswith
articles = Article.objects.filter(title__startswith='python')
#标题是python结尾的,若忽略大小写使用 iendswith
articles = Article.objects.filter(title__endswith='python')
4. 按日期时间查询
# 查询2021年发表的文章
Article.objects.filter(created__year=2021)
# 查询2021年3月19日发表的文章
import datetime
Article.objects.filter(created__date=datetime.date(2021,3,19))
# 查询2021年1月1日以后发表的文章
Article.objects.filter(created__gt=datetime.date(2021, 1, 1))
# 与当前时间相比,查询即将发表的文章
from django.utils import timezone
Article.objects.filter(created__gt=timezone.now())
# 按绝对时间范围查询,查询2021年1月1日到6月30日发表文章
article = Aritlce.objects.filter(created__gte=datetime.date(2021, 1, 1),
pub_date__lte=datetime.date(2021, 6, 30))
# 按相对时间范围查询,用range查询3月1日以后30天内发表文章
startdate = datetime.date(2021, 3, 1)
enddate = startdate + datetime.timedelta(days=30)
Article.objects.filter(pub_date__range=[startdate, enddate])
4. 切片、排序、去重
# 切片
articles = Article.objects.filter(created__year=2021)[:5]
# 排序:created正序,-表示逆序
articles = Article.objects.all().order_by('-created')
# 去重
Article.objects.filter(title__icontains='python').distinct()
5. 高级Q和F方法
- Q方法
执行or逻辑的条件查询,可以使用Q方法,它可以连接多个查询条件,Q对象前面加 ~ 可以表示否定
from django.models import Q
# 查询标题含有python或Django的文章
article = Article.objects.filter(Q(title__icontains='python')|Q(title__icontains='django'))
# 查询标题含有python,不含有Django的文章
article = Article.objects.filter(Q(title__icontains='python')|~Q(title__icontains='django'))
- F方法
基于自身字段值来过滤一组对象,还支持加、减、乘、除、取模和幂运算等算术操作
from django.db.models import F
Article.objects.filter(n_commnets__gt=F('n_pingbacks'))
Article.objects.filter(n_comments__gt=F('n_pingbacks') * 2)