Django之ORM(二)
必知必会13条
准备数据
from django.db import models # Create your models here. class MyCharField(models.Field): """ 自定义的char类型的字段类 """ def __init__(self, max_length, *args, **kwargs): self.max_length = max_length super(MyCharField, self).__init__(max_length=max_length, *args, **kwargs) def db_type(self, connection): """ 限定生成数据库表的字段类型为char,长度为max_length指定的值 """ return 'char(%s)' % self.max_length class Person(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32, db_column='myname', verbose_name='姓名') age = models.IntegerField(null=True, blank=True) birth = models.DateTimeField(auto_now=True) phone = MyCharField(max_length=11) sex = models.IntegerField(choices=((1, '男'), (2, '女'))) class Meta: # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名 db_table = "person" # 在admin中的显示, 一般直接加verbose_name_plural verbose_name = '个人信息' # 显示 个人信息s verbose_name_plural = '所有用户信息' # 显示所有用户信息 # 联合索引 index_together = [('name', 'age')] # 联合唯一索引 # unique_together = (("name", "age")) # 排序 # ordering = ('age', ) def __str__(self): return 'Person <{}:{}>'.format(self.id, self.name)
<1> all():
--->> 查询所有结果 --->> 对象列表
ret = models.Person.objects.all() print(ret)
输出结果
<QuerySet [<Person: Person <1:魏新雨咋软>>, <Person: Person <2:陈骏啊, 萨宁啊>>]>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.001) SELECT `person`.`id`, `person`.`myname`, `person`.`age`, `person`.`birth`, `person`.`phone`, `person`.`sex` FROM `person` LIMIT 21; args=()
**<2> filter(**kwargs): **
--->> 查询出所有满足条件的对象 ---->> 对象列表
ret = models.Person.objects.filter(sex=1) print(ret)
输出结果
<QuerySet [<Person: Person <1:魏新雨咋软>>, <Person: Person <2:陈骏啊, 萨宁啊>>]>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.001) SELECT `person`.`id`, `person`.`myname`, `person`.`age`, `person`.`birth`, `person`.`phone`, `person`.`sex` FROM `person` LIMIT 21; args=()
**<3> get(**kwargs): **
返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误
ret = models.Person.objects.get(id=1) print(ret)
输出结果
Person <1:魏新雨咋软>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.000) SELECT VERSION(); args=None (0.001) SELECT `person`.`id`, `person`.`myname`, `person`.`age`, `person`.`birth`, `person`.`phone`, `person`.`sex` FROM `person` WHERE `person`.`id` = 1; args=(1,)
**<4> exclude(**kwargs): **
--->> 查询出所有不满足条件的对象 ------>> 对象列表
ret = models.Person.objects.exclude(id=1) print(ret)
输出结果
<QuerySet [<Person: Person <2:陈骏啊, 萨宁啊>>]>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.000) SELECT VERSION(); args=None (0.000) SELECT `person`.`id`, `person`.`myname`, `person`.`age`, `person`.`birth`, `person`.`phone`, `person`.`sex` FROM `person` WHERE NOT (`person`.`id` = 1) LIMIT 21; args=(1,)
<5> values(*field):
---->> 取具体的数据 ------> 对象列表 ---->>> 元素 {字段: 值}
ret = models.Person.objects.all().values('id', 'name') for i in ret: print(i, type(i))
输出结果
{'id': 2, 'name': '陈骏啊, 萨宁啊'} <class 'dict'> {'id': 1, 'name': '魏新雨咋软'} <class 'dict'>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.000) SELECT `person`.`id`, `person`.`myname` FROM `person`; args=()
<6> values_list(*field):
---->> 取具体的数据 ------> 对象列表 ---->>> 元素 (字段, 值)
ret = models.Person.objects.all().values_list('id', 'name') for i in ret: print(i, type(i))
输出结果
(2, '陈骏啊, 萨宁啊') <class 'tuple'> (1, '魏新雨咋软') <class 'tuple'>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.000) SELECT `person`.`id`, `person`.`myname` FROM `person`; args=()
<7> order_by(*field):
可以指定多个字段 (默认升序, 在字段前加 - 降序)
ret = models.Person.objects.all().order_by('-age') print(ret)
输出结果
<QuerySet [<Person: Person <1:魏新雨咋软>>, <Person: Person <2:陈骏啊, 萨宁啊>>]>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.001) SELECT `person`.`id`, `person`.`myname`, `person`.`age`, `person`.`birth`, `person`.`phone`, `person`.`sex` FROM `person` ORDER BY `person`.`age` DESC LIMIT 21; args=()
<8> reverse():
对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)
ret = models.Person.objects.all().order_by('age').reverse() print(ret)
输出结果
<QuerySet [<Person: Person <1:魏新雨咋软>>, <Person: Person <2:陈骏啊, 萨宁啊>>]>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.001) SELECT `person`.`id`, `person`.`myname`, `person`.`age`, `person`.`birth`, `person`.`phone`, `person`.`sex` FROM `person` ORDER BY `person`.`age` DESC LIMIT 21; args=()
<9> distinct():
从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重)
<10> count():
返回数据库中匹配查询(QuerySet)的对象数量
ret = models.Person.objects.all().count() print(ret)
输出结果
2
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.000) SELECT COUNT(*) AS `__count` FROM `person`; args=()
<11> first(): 返回第一条记录
ret = models.Person.objects.first() print(ret)
输出结果
Person <1:魏新雨咋软>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.001) SELECT `person`.`id`, `person`.`myname`, `person`.`age`, `person`.`birth`, `person`.`phone`, `person`.`sex` FROM `person` ORDER BY `person`.`id` ASC LIMIT 1; args=()
<12> last(): 返回最后一条记录
ret = models.Person.objects.last() print(ret)
输出结果
Person <2:陈骏啊, 萨宁啊>
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.001) SELECT `person`.`id`, `person`.`myname`, `person`.`age`, `person`.`birth`, `person`.`phone`, `person`.`sex` FROM `person` ORDER BY `person`.`id` DESC LIMIT 1; args=()
<13> exists():
如果QuerySet包含数据,就返回True,否则返回False
ret = models.Person.objects.filter(id=100).exists() print(ret)
输出结果
False
SQL语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None (0.000) SELECT VERSION(); args=None (0.000) SELECT (1) AS `a` FROM `person` WHERE `person`.`id` = 100 LIMIT 1; args=(100,)
单表查询之神奇的双下划线
ret = models.Person.objects.filter(id__gt=1) # greater than 大于 ret = models.Person.objects.filter(id__lt=4) # less than 小于 ret = models.Person.objects.filter(id__gte=1) # greater than equal 大于等于 ret = models.Person.objects.filter(id__lte=4) # greater than equal 小于等于 ret = models.Person.objects.filter(id__in=[1,3]) # 获取id是1 和 id是3的数据 ret = models.Person.objects.filter(id__range=[1,3]) # 获取id是1 和 id是3的数据 ret = models.Person.objects.filter(id__in=[1,3]) # 获取id是1 和 id是3的数据 ret = models.Person.objects.filter(id__gte=1, id__lt=3) # 获取id大于1小于3的数据 ret = models.Person.objects.filter(id__range=[1,3]) # 获取id在1到3之间的数据 ret = models.Person.objects.filter(name__contains='新') # 获取name字段中包含新的数据 ret = models.Person.objects.filter(name__icontains='sb') # 获取name字段中包含sb的数据, 忽略大小写 ret = models.Person.objects.filter(name__startswith='l') # 获取name字段中以小写l开头的数据 ret = models.Person.objects.filter(name__istartswith='l') # 获取name字段中以l开头的数据, 忽略大小写
ForeignKey操作
准备表格
from django.db import models # 出版社表 class Press(models.Model): id = models.AutoField(primary_key=True) # id主键 name = models.CharField(max_length=32) # 出版社名称 def __str__(self): return '<这是一个出版社对象,它的名字是:{}>'.format(self.name) # 书 class Book(models.Model): id = models.AutoField(primary_key=True) # 自增id主键 title = models.CharField(max_length=30) # 书名 price = models.IntegerField(null=True) # Django 1.11 默认就是级联删除, Django 2.0之后必须指定on_delete # to=关联的表名 press = models.ForeignKey(to='Press', on_delete=models.CASCADE) # 作者 class Author(models.Model): id = models.AutoField(primary_key=True) # 自增id主键 name = models.CharField(max_length=32) # 作者名字 books = models.ManyToManyField(to='Book') # 只是ORM层面建立的一个多对多关系,不是作者表的一个字段 def __str__(self): return self.name
正向查找
对象查找(跨表)
语法:
对象.关联字段.字段
示例:
book_obj = models.Book.objects.first() # 第一本书对象 print(book_obj.press) # 得到这本书关联的出版社对象 print(book_obj.press.name) # 得到出版社对象的名称
字段查找(跨表)
语法:**关联字段__字段**
示例:
print(models.Book.objects.values_list('press__book__title'))
反向操作
对象查找
语法:
obj.表名_set
示例:
press_obj = models.Press.objects.get(id=1) # 找到第一个出版社对象 books = press_obj.book_set.all() # 找到第一个出版社出版的所有书 title = books.values_list("title") # 找到第一个出版社出版的所有书的书名
字段查找
语法:
**表名__字段**
示例:
title = models.Press.objects.values_list('book__title').filter(id=1)
ManyToManyField
class RelatedManager
"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。
它存在于下面两种情况:
- 外键关系的反向查询
- 多对多关联关系
简单来说就是当 点后面的对象 可能存在多个的时候就可以使用以下的方法。
方法
create()
创建一个新的对象,保存对象,并将它添加到关联对象集之中,返回新创建的对象
models.Author.objects.first().books.create(title='偷塔秘籍', press_id=1)
SQL语句
(0.000) SELECT `app01_author`.`id`, `app01_author`.`name` FROM `app01_author` ORDER BY `app01_author`.`id` ASC LIMIT 1; args=() (0.000) INSERT INTO `app01_book` (`title`, `price`, `press_id`) VALUES ('偷塔秘籍', NULL, 1); args=['偷塔秘籍', None, 1] (0.001) SELECT `app01_author_books`.`book_id` FROM `app01_author_books` WHERE (`app01_author_books`.`author_id` = 1 AND `app01_author_books`.`book_id` IN (6)); args=(1, 6) (0.000) INSERT INTO `app01_author_books` (`author_id`, `book_id`) VALUES (1, 6); args=(1, 6)
add()
把指定的model对象添加到关联对象集中。
添加对象
添加id
set()
更新某个对象在第三张表中的关联对象。不同于上面的add是添加,set相当于重置
set可以理解为SQL语句中的in, 所以参数传的是列表
author_obj = models.Author.objects.first() author_obj.books.set([1, 2])
SQL语句
(0.000) SELECT `app01_author`.`id`, `app01_author`.`name` FROM `app01_author` ORDER BY `app01_author`.`id` ASC LIMIT 1; args=() (0.001) SELECT `app01_book`.`id` FROM `app01_book` INNER JOIN `app01_author_books` ON (`app01_book`.`id` = `app01_author_books`.`book_id`) WHERE `app01_author_books`.`author_id` = 1; args=(1,) (0.001) DELETE FROM `app01_author_books` WHERE (`app01_author_books`.`author_id` = 1 AND `app01_author_books`.`book_id` IN (6)); args=(1, 6) (0.001) SELECT `app01_author_books`.`book_id` FROM `app01_author_books` WHERE (`app01_author_books`.`author_id` = 1 AND `app01_author_books`.`book_id` IN (1, 2)); args=(1, 1, 2) (0.005) INSERT INTO `app01_author_books` (`author_id`, `book_id`) VALUES (1, 1), (1, 2); args=(1, 1, 1, 2)