Django知识点:ORM操作
程序员文章站
2022-05-31 20:46:28
...
字段类型
CharFiled | 字符串类型,需要指定长度 |
---|---|
IntegerField | 整型 |
FloatField | 浮点型 |
DateField | 日期,年月日 |
DateTimeField | 年月日时分秒 |
BooleanField | 布尔 |
TextField | 文本 |
EmailField | 邮箱 |
DecimalField | 浮点,指定小数点位数decimal_places,和长度max_digits |
ForeignKey | 外键 |
ImageField | 图片类型,需要依赖 pillow,能够完成图片的上传 |
ImageField 字段使用:
在settings 中增加配置,决定图片上传的路径
MEDIA_URL = 'media'
MEDIA_ROOT = os.path.join(BASE_DIR,'static')
单表操作
已有数据模型
class User(models.Model):
# id = models.AutoField(primary_key=True) # 主键
name = models.CharField(max_length=32, verbose_name="姓名") # 名字,字符串
age = models.IntegerField(verbose_name="年龄") # 年龄 int
gender = models.CharField(max_length=4, verbose_name="性别") # 性别 int
方法 | 注释,语法 | 返回值 |
---|---|---|
save | 先实例化对象user,user.属性 = 值… user.save()添加数据 | – |
create | 先定义一个操作字典,包含属性和对应的值,调用create方法添加数据 | – |
all | 查询所有数据,可以通过下标获取对象,然后在(.属性)获取对象属性的值 | queryset 列表对象 |
get | 获取符合条件的数据,有且只有一条,否在报错,通常配合id 使用 | 对象 |
filter | 类似sql中的where,过滤的作用,返回所有符合条件的数据 | queryset |
first | 操作的是queryset ,返回第一条数据 | 对象 |
exclude | 返回不符合条件的数据 | queryset |
order_by | 对拿到的数据排序,默认顺序是正序,order_by(’-id’)是对id逆序,操作的是queryset | queryset |
values | 返回的是一个类 queryset 里面的数据字典类型 | queryset类字典类型 |
exists | 判断数据是否存在 | 布尔值 |
count | 统计符合条件的数据条数 | 数字 |
切片 [ ] | 对拿到的数据二次操作 | queryset列表对象 |
update | 是queryset 的一个方法,如果是对象不能使用update | – |
delete | 删除数据,是queryset的一个方法,对象不能使用delete | – |
双下划线语法:一般配合filter 使用
id__lt | 小于 |
---|---|
id__gt | 大于 |
id__gte | 大于等于 |
id__in=[1,2,3] | id 在列表里的取值 |
contains | 包含指定字符,大小写敏感 |
icontsins | 包含指定字符,大小写不敏感 |
startswith | 指定字符开头,大小写敏感 |
endswith | 指定字符结尾,大小写敏感 |
iendswith | 指定字符结尾,大小写不敏感 |
id__range(1,3) | 在指定的范围,是一个前闭合,后闭合的区间,包含头和尾 |
增加数据
- save 方法
- 方法1:先实例化对象user,在实例化的时候添加对象的属性,之后再用user对象调用save方法实现添加数据
def adduser(request):
user = User(name='Ian',age=11,gender='nan')
user.save()
- 方法2:实例化对象user,一个一个的对象添加属性,之后再调用save方法实现添加数据
def adduser(request):
user.User()
user.name = 'ian'
user.age = 12
user.gender = 'nv'
user.save()
- create 方法
- create是一个方法
def adduser(request):
# 方式1
User.objects.create(name='Damon',age='13',gender='nan')
# 方式2
params = dict(name='Alaric',age=14,gender='nan')
User.objects.create(**params)
ps:** 出现在形参中,是关键字参数
** 出现在实参中是解包 的意思
在这里的意思是:传入的params 是一个字典参数,将这个字典的键值对拆解出来,把拆解出来的参数当参数用
给表再添加几条数据
def adduser(request):
user = User(name='Nina',age=15,gender='nv')
user.save()
User.objects.create(name='aaa',age=16,gender='nan')
User.objects.create(name='aaa',age=26,gender='nv')
User.objects.create(name='aaa',age=36,gender='nan')
User.objects.create(name='bbb',age=17,gender='nv')
params = dict(name='ccc',age=18,gender='nv')
User.objects.create(**params)
查询方法
- all 方法
- 查询所有的数据
- 返回值:queryset 类列表对象
- 要获取某一条数据用下标,或者遍历获取每一个
- 获取某个对象的属性通过 “.属性”
def getuser(request):
data = User.objects.all()
# 打印的是全部数据,是一个类列表对象
print(data)
# 打印的是这个列表对象中下标为0的数据
print(data[0])
# 打印的是列表对象中下标为0的数据的name属性的值
print(data[0].name)
# for循环可以遍历获取每一条数据
for i in data:
print(i) # i是个对象
print(i[0].name)
- get 方法
- 返回符合条件的数据,且返回结果有且只有一条数据,否则报错
- 返回值:对象
- get 通常用 id 作为条件
def getuser(request):
# 拿到id为1的数据
data = User.objects.get(id=1)
print(data)
# 拿到name为Alaric的数据
data = User.objects.get(name='Alaric')
print(data)
- filter 方法
- 类似于sql中where,过滤的作用
- 返回值:queryset
def getuser(request):
data = User.objects.filter(name='Ian')
# 打印name为Ian的数据
print(data)
# filter拿到的是一个类列表对象,可以用for遍历
for i in data:
print(i.id)
# 当有多个条件的时候,条件之间是and关系,需要同时满足
data = User.objects.filter(name='Ian',age=11)
print(data)
- first 方法
- 返回第一条数据
- 返回值:对象
def getuser(request):
# 通过filter获取的name为aaa的有三条数据,first获取第一条数据
data = User.objects.filter(name='aaa').first()
print(data)
- last 方法
- 返回最后一条数据
- 返回值:对象
def getuser(request):
# 通过filter获取的name为aaa的有三条数据,last获取第一条数据
data = User.objects.filter(name='aaa').last()
print(data)
- exclude 方法
- 返回不符合条件的数据(不包含条件属性的其他所有数据)
- 返回值:queryset
def getuesr(request):
# 查询所有gender为nan的所有数据(查询所有不是nv的数据)
data = User.objects.exclude(gender='nv')
print(data)
- order_by
- 排序
- 返回值:queryset
def getuser(request):
# 升序
data = User.objects.order_by('id','age')
print(data)
# 逆序
data = User.objects.order_by('-id')
print(data)
- reverse 方法
- 对查询的结果反向排序,多个排序条件的话,前面的先排序
- 返回值:queryest
data = User.objects.all().order_by('id').reverse()
print(data)
- values 方法
- 返回一个类 queryset 里面的数据字典类型
- 可以根据key(类属性)拿到对应的值
data = User.objects.all().values() # 得到一个queryset类字典类型
data = User.objects.all().values('name','age') # 根据属性关键字,拿到对应的属性的值
print(data)
- exists 方法
- 判断这条数据是否在数据库存在
- 返回值:布尔值 True,存在 False,不存在
flag = User.objects.filter(name='Ian').exists()
print(flag)
- count 方法
- 统计符合条件的数据条数
- 返回值:数字
num = User.objects.filter(name='damon').count()
print(num)
- 切片 [ ]
- 对拿到的数据进行二次处理
- 返回值:是对queryset 对象进行处理,所以拿到的是对象
data = User.objects.all()[1:3]
print(data)
修改数据
- save 方法
- 需要先查询数据,拿到数据实例对象
- 然后在修改实例对象的属性的值
- save 方法保存数据
user = User.objects.filter(id=2).first()
user.age = 222
user.save()
- update 方法
- 是 queryset 的方法,操作的不能是对象
User.objects.filter(id=4).update(age=555)
User.objects.filter(name='aaa').update(age=44)
删除数据
- delete 方法
- 是queryset 的方法,操作的不能是对象
User.objects.filter(id=6).delete()
User.objects.filter(name='aaa').delete()
一对多操作
已有模型
添加数据
Publish.objects.create(name='北京出版社',address='北京')
Publish.objects.create(name='河南出版社',address='河南')
Publish.objects.create(name='山东出版社',address='山东')
# 第一种
Book.objects.create(name='python基础',publish_id=1)
# 第二种
publish = Publish.objects.get(name='北京出版社')
Book.objects.create(name='python开发',publish_id=publish.id)
# 第三种
publish = Publish.objects.get(name='河南出版社')
Book.objects.create(name='pythonWeb',publish=publish)
# 第四种
Book.objects.create(name='pythonWeb',publish=Publish.objects.get(name='山东出版社'))
# 正向:从外键所在的表到关联表的操作叫正向操作
book = Book()
book.name = 'py数据分析'
book.publish = Publish.objects.get(name='河南出版社')
book.save()
# 反向:从关联表到外键所在的表的操作
publish = Publish.objects.filter(name='山东出版社').first()
publish.book_set.create(name='py爬虫')
# 在创建出版社的时候,直接在后面添加该出版社的书籍
publish = Publish.objects.create(name='河南出版社')
publish.book_set.create(name='py技术')
查询
# 查询北京出版社的书籍
pub = Publish.objects.get(name='北京出版社')
book = Book.objects.filter(publish_id=pub.id).values('name')
book1 = Book.objects.filter(publish=pub).values('name')
print(book,book1)
# 查询python基础的出版社的名字
book = Book.objects.get(name='python基础')
pname = Publish.objects.get(id=book.publish_id)
print(pname.name)
# 正向查询 book->publish
# 查 python基础的出版社信息
book = Book.objects.get(name='python基础')
pub_name = book.publish.name # book.publish得到的是一个出版社对象
print(pub_name)
pub_id = book.publish_id # 直接拿book的publish_id就是对应出版社的id
print(pub_id)
# 反向查询:pub-》book
# 查北京出版社的书籍
pub = Publish.objects.get(name='北京出版社')
b_name = pub.book_set.all().values('name')
print(b_name)
修改数据
# 1.save 将python基础的出版社修改为河南出版社
book = Book.objects.get(name='python基础')
pub = Publish.objects.get(name='河南出版社',address='河南')
book.publish = pub
book.save()
# 2.update
pub = Publish.objects.get(name='北京出版社')
Book.objects.filter(name='py爬虫').update(publish = pub)
删除数据
- 需要先删除外键所在的表,针对现有的表,只能删除书的数据,出版社的不能删
# 删除“python基础”
Book.objects.get(name='python基础').delete()
# 删除关联表 删除py爬虫的对应的出版社信息
book = Book.objects.get(name='py爬虫')
book.delete()
# 删除“py技术”
book = Book.objects.get(name='py技术') # 实例化py技术这本书
Publish.objects.filter(id = book.publish_id).delete() # Publish调用delete 方法删除
多对多操作
已有模板
添加数据
# 增加老师
Teacher.objects.create(name='老张',gender=1)
Teacher.objects.create(name='老王',gender=1)
Teacher.objects.create(name='老李',gender=1)
Teacher.objects.create(name='丽丽',gender=0)
# 增加学生
Student.objects.create(name='张一',age=21,gender=1)
Student.objects.create(name='张二',age=22,gender=1)
# 正向添加:王一想上老王的课
teacher = Teacher.objects.get(name='老王') # 先实例化老师对象
teacher.student.create(name='王一',age=23,gender=1) # 老师.学生.create方法
# 正向添加:小三和小四想上女老师的课
teacher = Teacher.objects.get(gender=0) # 实例化老师对象
student1 = Student.objects.create(name='小三',age=31,gender=1) # 实例化多个学生对象
student2 = Student.objects.create(name='小四',age=22,gender=0)
teacher.student.add(student1,student2) # 老师.学生.add方法(学生1,学生2)
# 反向添加:小五想上老李的课
student = Student.objects.create(name='小五',age=25,gender=1) # 实例化学生对象
teacher = Teacher.objects.filter(name='老李').first() # 实例化老师对象
student.teacher_set.add(teacher) # 学生.老师_set.add方法(老师)
查询数据
# 正向查询:老张的学生都有谁
teacher = Teacher.objects.filter(name='老张').first() # 实例化老师对象
student = teacher.student.all().values('name') # 老师.学生.all().values()
print(student)
# 反向查询:丽丽的学生都有谁
student = Student.objects.filter(name='小三').first() # 实例化学生对象
teacher = student.teacher_set.all().values('name') # 学生.老师_set.all().values(属性关键字)
print(teacher)
修改数据
- 正向修改数据的时候用 set()方法
- 反向修改数据的时候使用 _set()方法
- 括号里面可以放多个对象,也可以是 [ id1 , id2 , id3 ]
# 正向
# 把学生id为3,4,5的学生老师都换成丽丽
teacher = Teacher.objects.get(name='丽丽') # 实例化老师对象
teacher.student.set([3,4,5]) #
# 反向
# 给小三选上老师id为1,2,3,4的课
student = Student.objects.get(name='小三')
student.teacher_set.set([1,2,3,4])
删除数据
- remove 删除关系
- remove() 可以加id,也可以加对象
- clear 清空所有的关系
- delete 删除数据之后,对应的关系表里的关系也没有了
# 正向:解除小四和丽丽的关系
# 正向删除的时候,直接调用remove方法
teacher = Teacher.objects.get(name='丽丽')
student = Student.objects.get(name='小四')
teacher.student.remove(student)
# 反向:解除丽丽和小三的关系
# 反向删除的时候,加个_set 再用remove 方法
teacher = Teacher.objects.get(name='丽丽')
student = Student.objects.get(name='小三')
student.teacher_set.remove(teacher)
# clear 清空
# 反向:删除张一和所有老师的关系
Student.objects.get(name='张一').teacher_set.clear()
# 正向:删除老张和所有学生的关系
teacher = Teacher.objects.get(name='老张')
teacher.student.clear()
# delete 删除数据
Student.objects.filter(name='王一').delete()
双下划线语法" __ "
# 取id 小于3的数据
data = User.objects.filter(id__lt=3).values('name')
# 取id 大于3 的数据
data = User.objects.filter(id__gt=3).values('name')
# 取id 大于等于3 的数据
data = User.objects.filter(id__gte=3).values('name')
# 取id 为1,2,3的数据
data = User.objects.filter(id__in=[1,2,3]).values('name')
# 取包含指定字符的数据,大小写敏感
data = User.objects.filter(name__contains='I').values('name')
# 取包含指定字符的数据,大小写不敏感
data = User.objects.filter(name__icontains='I').values('name')
# 指定字符开头的数据,大小写敏感
data = User.objects.filter(name__startswith='I').values('name')
# 指定字符开头的数据,大小写不敏感
data = User.objects.filter(name__istartswith='I').values('name')
# 指定字符结束的数据,大小写敏感
data = User.objects.filter(name__endswith='I').values('name')
# 取id 范围在(1,3)的数据,是个前闭合后闭合的范围区间
data = User.objects.filter(id__range=(1,3)).values('name')
聚合函数
- 先导包:from django.db.models import Sum,Avg,Count,Max,Min,F,Q
# 返回值是个字典:默认key的格式(参数名_聚合函数名)
dict1 = Student.objects.all().aggregate(Count('id'), Count('name'), Avg('age'))
# print(dict1)
# 给聚合函数返回值的 key 改名字
dict2 = Student.objects.aggregate(name=Count('name'))
# print(dict2)
# 在使用聚合函数的前面加上要改的名字 新名字 = Count('name')
# F 对象,用来比较一个表中的两个字段的值的大小
data = Book.objects.filter(num__lt = F('sell_num')).all().values('name')
# print(data)
# Q 对象,处理条件查询中的and or not 关系
# and &;or |;not ~
## 查询 num 大于 10 sell_num 小于100 的书名
book= Book.objects.filter(num__gt=10,sell_num__lt =100).all().values()
## and
book = Book.objects.filter(Q(num__gt=10) & Q(sell_num__lt =100)).all().values("name")
# or
book = Book.objects.filter(Q(num__gt=10) | Q(sell_num__lt =100)).all().values("name")
# not
## 查找 num不大于 10 或者 sell_num 不小于 100 的书名
book = Book.objects.filter(~Q(num__gt=10) | ~Q(sell_num__lt =100)).all().values("name")
book = Book.objects.filter(~Q(num__gt=10)).all().values("name")
book = Book.objects.filter(~Q(num__gt=10) & Q(sell_num__lt =100)).all().values("name")
推荐阅读