orm语句的特点:惰性查询
如果仅仅只是书写了orm语句,在后面没有用到该语句所查询出来的参数,那么orm会自动识别,并不执行
举例:
res = models.Book.objects.all() # 单单执行此语句Django并不会使用数据库,减轻数据库压力
res = models.Book.objects.all() print(res) # 只有用到数据了才会走数据库
接下来尝试获取数据表中所有书的名字。
res = models.Book.objects.values('name') print(res) # 拿到列表套字典的形式,对象 for i in res: print(i.get('name')) # 通过for循环字典取值方式拿到书籍名字
那么如何实现获取到的是一个数据对象,再通过title就能够拿到书名,并且没有其他字段。
res1 = models.Book.objects.only('name') # 对象只有name属性 for b in res1: print(b.name) # 如果(.)only括号内有的字段则不走数据库 print(b.title) # 如果(.)only括号内没有的字段则需要反复前往数据库查询数据,再一个一个返回,而all()不需要
结论:因为all()拿到的是所有的数据对象,而only()只拿到括号内指定的数据对象。
res = models.Book.objects.defer('name') # 对象除了没有name属性之外其他的都有 for i in res: print(i.price)
结论:defer与only刚好相反,defer括号内放的字段不再查询出来的对象中,查询该字段需要重新走数据库。如果查询的是非括号内的字段,则不走数据库。
举例:查询每本书的的出版社名字
res = models.Book;.objects.all() for i in res: print(i.publish.name) # 使用all方法查询的时候,每一个对象都会去数据库查询数据
res = models.Book.objects.select_related() for i in res: print(i.publish.name) # 只走了一次数据库, 使用INNER JOIN内连接操作
总结:select_related 内部直接先将book与publish连接,然后一次性将大表里面的所有数据全部封装给查询出来的对象。select_related括号内只能放外键字段并且是一对多,一对一。
# 跟跨表操作有关 res = models.Book.objects.prefetch_related('publish') # 子查询 for i in res: print(i.publish.name) """ prefetch_related该方法内部其实就是子查询 将子查询查询出来的所有结果也给你封装到对象中 给你的感觉好像也是一次性搞定的 """
结论:prefetch_related该方法内部其实就是子查询,将子查询出来的所有结果封装到对象中。
总结:select_related与prefetch_related,select_related是连表操作,prefetch_related是子查询,各有优点与缺点,如果表很大的时候,使用select_related连表耗时会耗费很长时间,而select_related子查询虽然查询两次,但是操作两个表的时间非常短效率就会胜于联表查询prefetch_related
针对信息来源可概括全部场景。比如:性别,学历,工作经验,信息来源... 这种情况该如何存储?
只要是某个字段的可能性是可以列举完全的,一般情况下都会采用choices参数
字段创建的数据类型根据想要指定字段中一个元祖元素是什么类型。该gender字段存的还是数字,但是如果存的数字在上面元祖列举的范围之内,那么可以获取到数字对应的真正的内容。
举例:
# 如果gender字段存的数字不再上述元祖列举的范围内容 # 如果在,如何获取对应的中文信息?
创建表:
class Client(models.Model): username = models.CharField(max_length=32) age = models.IntegerField() # 性别 gender_choices = { (1, '男'), (2, '女'), (3, '其他'), } """ 字段创建的数据类型根据想要指定字段中一个元祖元素是什么类型。 该gender字段存的还是数字,但是如果存的数字在上面元祖列举的范围之内 那么可以获取到数字对应的真正的内容 """ gender = models.IntegerField(choices=gender_choices)
创建数据,tests.py:
from django.test import TestCase # Create your tests here. import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day06.settings") import django django.setup() from app01 import models models.Client.objects.create(username='junjie',age=18,gender=1) models.Client.objects.create(username='nn',age=1,gender=2) models.Client.objects.create(username='jason',age=58,gender=3) models.Client.objects.create(username='tom',age=99,gender=4)
可以看到,数据的创建是没有问题,没有创建的数字也能存。
那么取?
# 取 user_obj = models.Client.objects.filter(pk=1).first() print(user_obj.gender) # 输出:1
此时输出不应该是pk=1所对应的真正性别,怎么获取的数据是1?
只要是choices参数的字段,如果想要获取对应信息,固定写法get_字段名_display()
user_obj = models.Client.objects.filter(pk=1).first() print(user_obj.get_gender_display()) # 输出:男
那么还有一个用户名为tom
没有书写固定关系,他返回的会是什么?
user_obj = models.Client.objects.filter(pk=4).first() print(user_obj.get_gender_display()) # 输出:4
如果没有对应关系,字段是什么还是展示什么。
字符串格式也是如此:
先创建字段:
score_choices = ( ('A','优秀'), ('B','及格'), ('C','不及格'), ) # 在已创建的表中添加新的字段,需要设置null=True 表示该字段为空,也可以设置默认值 score = models.CharField(max_length=32,choices=score_choices,null=True)
添加数据:
models.Client.objects.filter(pk=1).update(score='A')
获取数据:
res = models.Client.objects.filter(pk=1).first() print(res.get_score_display()) # 输出:优秀
MTV: Django号称是MTV模型,本质也是MVC模型
M: models
T: templates
V: views
MVC
M: models
V: views
C: controller(控制器)
利用orm自动创建第三张关系表
class Book(models.Model): name = models.CharField(max_length=32) authors = models.ManyToManyField('Author') class Author(models.Model): name = models.CharField(max_length=32)
class Book(models.Model): name = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) class Book2Author(models.Model): authors_id = models.ForeignKey(to='Author') books_id = models.ForeignKey(to='Book')
through_fields 字段先后顺序,判断的本质: 通过第三张表查询对应的表,需要用到那个字段酒吧哪个字段放前面,当前表是谁,就把对应的关联字放在前面。
半自动:可以使用orm正反向查询,但是没办法使用add,remove,clear,set 方法
class Book(models.Model): name = models.CharField(max_length=32) authors = models.ManyToManyField(to='Author', # 声明指定表为第三张关系表 through='Book2Author', # 声明在第三张关系表中的字段表示关系 through_fields=('Book','Author') ) class Author(models.Model): name = models.CharField(max_length=32) class Book2Author(models.Model): authors = models.ForeignKey(to='Author') books = models.ForeignKey(to='Book') ...
总结:全自动和半自动需要掌握,为了拓展性更高一般都采用半自动