目录:
ORM基础
-
类 >>> 数据库的表
-
对象 >>> 数据库里面的一条条的表记录
-
对象点属性 >>> 表记录的某个字段对应的值
在视图中操作orm
增
1.create()
modeles.User.objects.create(kwargs)
create方法会返回当前所创建的数据对象(*****)
2.对象.save()
user_obj = models.User()
user_obj.username = 'jason'
user_obj.save()
删
queryset对象.delete()
改
1.update()
models.User.objects.filter(kwargs).update()
批量更新
2.对象.save()
user_obj = models.User(kwargs)
user_obj.username = 'jason'
user_obj.save()
效率较低
查
1.all() 查所有 不需要传参数
2.filter(kwargs) 结构是一个queryset对象 你可以把它看成一个列表里面是一个个的数据对象
bulk_create批量插入数据
# 一次性插入多条数据
data = ["".join([str(random.randint(65, 99)) for i in range(4)]) for j in range(100)]
obj_list = [models.A(name=i) for i in data]
models.A.objects.bulk_create(obj_list)
ORM常用字段和参数
官方文档:https://docs.djangoproject.com/zh-hans/2.1/ref/models/fields/#field-types
-
AutoField
int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。 -
IntegerField
一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,) -
CharField
字符类型,必须提供max_length参数, max_length表示字符长度。注意: 这里需要知道的是Django中的CharField对应的MySQL数据库中的varchar类型,没有设置对应char类型的字段
-
DateField
日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。 -
DateTimeField
日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。
字段参数
-
null
用于表示某个字段可以为空。 -
unique
如果设置为unique=True 则该字段在此表中必须是唯一的 。 -
db_index
如果db_index=True 则代表着为此字段设置索引。 -
default
为该字段设置默认值。
DateField中的参数:
- auto_now:每次操作该数据的时候 都会自动更新当前时间
- auto_now_add:数据第一次创建的时候 会将创建时间自动记录下来 后续的改动不会再自动更新该字段
13个必知ORM操作
返回QuerySet对象的方法有
all()
filter()
exclude()
order_by()
reverse()
distinct()
特殊的QuerySet
values() 返回一个可迭代的字典序列
values_list() 返回一个可迭代的元祖序列
返回具体对象的
get()
first()
last()
返回布尔值的方法有:
exists()
返回数字的方法有
count()
ORM关系字段
ForeignKey字段(一对多)
外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 '一对多’中’多’的一方。
ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。
字段参数
-
to
设置要关联的表 -
to_field
设置要关联的表的字段 -
on_delete
当删除关联表中的数据时,当前表与其关联的行的行为。 -
models.CASCADE
-
删除关联数据,与之关联也删除
-
db_constraint
是否在数据库中创建外键约束,默认为True。
示例
class MyModel(models.Model):
user = models.ForeignKey(
to="User",
to_field="id",
on_delete=models.CASCADE
)
OneToOneField
常用于拆表
通常一对一字段用来扩展已有字段。(通俗的说就是一个人的所有信息不是放在一张表里面的,简单的信息一张表,隐私的信息另一张表,之间通过一对一外键关联)
字段参数
-
to
设置要关联的表。 -
to_field
设置要关联的字段。 -
on_delete
当删除关联表中的数据时,当前表与其关联的行的行为。(参考外键的例子)
ManyToManyField
适用于两种情况:
- 外键关系的反向查询
- 多对多关联关系
models.py
authors = models.ManyToManyField(to='Author') # 默认关联的就是Author表的主键字段
多对多表关系的三种创建方式
1.全自动
authors = models.ManyToManyField(to='Author')
让django orm自动帮你创建第三张表
好处:不需要自己手动添加
坏处:表字段的扩展性极差 只会帮你建外键字段 其他额外字段一概无法创建
2.纯手动(了解)
class Book(models.Model):
name = ...
class Author(models.Model):
name = ...
class Book2Author(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
3.半自动(推荐)
class Book(models.Model):
name = ...
authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author'))
class Author(models.Model):
name = ...
books = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('author','book'))
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
create_time = ...
info = ...
ORM跨表查询
models.py示例:
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
# 出版社外键
publish = models.ForeignKey(to='Publish') # 默认关联的就是Publish表的主键字段
"""
一对多外键字段 在书写的时候 orm会自动加_id后缀
所以 你不要加_id了
"""
# 作者外键
authors = models.ManyToManyField(to='Author') # 默认关联的就是Author表的主键字段
"""多对多字段是虚拟字段 不会在表中展示出来
只是用来告诉django orm自动创建书籍和作者的第三张表
还可以跨表的查询的提供方便
"""
class Publish(models.Model):
name = models.CharField(max_length=32)
email = models.EmailField()
addr = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.CharField(max_length=32)
# 一对一
"""
一对一外键字段 在书写的时候 orm会自动加_id后缀
所以 你不要加_id了
"""
author_detail = models.OneToOneField(to='AuthorDetail')
class AuthorDetail(models.Model):
phone = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
ORM多表操作
# 外键字段的增删改查
# models.Book.objects.create(title='三国演义',price='123.23',publish_id=1)
# publish_obj = models.Publish.objects.filter(pk=2).first()
# models.Book.objects.create(title='西游记',price='122.23',publish=publish_obj)
# models.Book.objects.filter(pk=1).update(publish_id=2)
# publish_obj = models.Publish.objects.filter(pk=1).first()
# models.Book.objects.filter(pk=1).update(publish=publish_obj)
# book_obj = models.Book.objects.filter(pk=1).first()
# # book_obj.authors.add(1) # 在第三张表中 添加书籍和作者的关系
# # book_obj.authors.add(1,2) # 在第三张表中 添加书籍和作者的关系
# author_obj1 = models.Author.objects.filter(pk=1).first()
# author_obj2 = models.Author.objects.filter(pk=2).first()
# book_obj.authors.add(author_obj1,author_obj2)
"""
add即支持传数字 并且也支持传对象
两者都可以是多个
"""
# 改
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.set([2,]) # 修改
"""
set即支持传数字 并且也支持传对象
两者都可以是多个
但是需要注意的是 传入的格式必须是可迭代对象
"""
# 删
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.remove(2)
"""
remove即支持传数字 并且也支持传对象
两者都可以是多个
"""
# 清空
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.clear() # 清空当前数据所有的关联信息
"""
clear括号内不需要传任何参数
"""
基于对象的跨表查询
基于子查询
# 正向与反向的概念解释
正向查询按字段
反向查询按表名小写...
# 一对一
# 正向:author---关联字段在author表里--->authordetail 按字段
# 反向:authordetail---关联字段在author表里--->author 按表名小写
# 一对多
# 正向:book---关联字段在book表里--->publish 按字段
# 反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书
# 多对多
# 正向:book---关联字段在book表里--->author 按字段
# 反向:author---关联字段在book表里--->book 按表名小写_set.all() 因为一个作者对应着多个图书
示例:
"""基于对象的跨表查询相当于子查询"""
# 查询书籍id为1的出版社名称
# book_obj = models.Book.objects.filter(pk=1).first()
# print(book_obj.publish.name)
# 查询出版社是南方出版社出版过的书的名字
# publish_obj = models.Publish.objects.filter(name='南方出版社').first()
# # print(publish_obj.book_set) # app01.Book.None
# print(publish_obj.book_set.all())
# 查询作者是jason的手机号
# author_obj = models.Author.objects.filter(name='jason').first()
# print(author_obj.author_detail.phone)
# 查询手机号是110的作者姓名
# author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
# print(author_detail_obj.author.name)
# 查询书籍id为1 的作者姓名
# book_obj = models.Book.objects.filter(pk=1).first()
# # print(book_obj.authors) # app01.Author.None
# print(book_obj.authors.all()) # app01.Author.None
# 查询作者id为1的写过的书籍
# author_obj = models.Author.objects.filter(pk=1).first()
# print(author_obj.book_set) # app01.Book.None
# print(author_obj.book_set.all())
基于双下划线的查询
基于连表
# 价格 大于 小于 大于等于 小于等于
filter(price__gt='90')
filter(price__lt='90')
filter(price_gte='90')
filter(price_lte='90')
# 存在与某几个条件中
filter(price__in=['11','22','33'])
# 在某个范围内
filter(price__range=[50,90])
# 模糊查询
filter(title__contains='西')
filter(title__icontains='P')
# 以什么开头 以什么结尾
# 按年查询
filter(create_time__year='2017')
# 一对一
-连表查询
-一对一双下划线查询
-正向:按字段,跨表可以在filter,也可以在values中
-反向:按表名小写,跨表可以在filter,也可以在values中
# 查询jason作者的手机号 正向查询 跨表的话,按字段
ret=Author.objects.filter(name='jason').values('authordetail__phone')
# 以authordetail作为基表 反向查询,按表名小写 跨表的话,用表名小写
ret=AuthorDetail.objects.filter(author__name='jason').values('phone')
# 查询jason这个作者的性别和手机号
# 正向
ret=Author.objects.filter(name='jason').values('sex','authordetail__phone')
# 查询手机号是13888888的作者性别
ret=Author.objects.filter(authordetail__phone='13888888').values('sex')
ret=AuthorDetail.objects.filter(phone='13888888').values('author__sex')
"""
总结 其实你在查询的时候先把orm查询语句写出来,再看用到的条件是否在当前表内,在就直接获取,不在就按照正向按字段反向按表名来查即可
比如:
1.查询出版社为北方出版社的所有图书的名字和价格
res1 = Publish.objects.filter(name='').values('book__name','book__price')
res2 = Book.objects.filter(publish__name='').values('name','price')
2.查询北方出版社出版的价格大于19的书
res1 = Publish.objects.filter(name='',book__price__gt=19).values('book__name','book__price)
"""