##基础数据准备
#数据模板准备
图书表、出版社、作者表、作者详情表、
#表之间的关系
图书表 和 出版社 一对多
图书表 和 作者表 多对多
作者表 和 作者详情表 一对一 (这里专门把作者表拆成两张表来练习orm操作)
#细节
1、多对多字段建在查询频率比较高的那张表中
2、多对多的字段只是一个虚拟字段、在数据库中不显示
# 告诉django orm自动帮你创建第三张表
# 查询的时候 可以借助该字段跨表
#要执行两条数据迁移命令:
python3 manage.py makemigrations
python3 manage.py migrate
fromdjango.dbimportmodels#Createyourmodelshere.fromdjango.confimportsettingsfromdjango.dbimportmodels#Createyourmodelshere.#图书表classBook(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')#多对多字段建在查询频率比较高的那张表中authors=models.ManyToManyField(to='Author')#authors只是一个虚拟字段#告诉djangoorm自动帮你创建第三张表#查询的时候可以借助该字段跨表def__str__(self):returnself.title#必须返回一个字符串类型否则直接报错#出版社classPublish(models.Model):name=models.CharField(max_length=32)addr=models.CharField(max_length=32)email=models.EmailField()def__str__(self):returnself.name#作者classAuthor(models.Model):name=models.CharField(max_length=32)age=models.CharField(max_length=32)#一对一字段也应该建在查询频率较高的表中author_detail=models.OneToOneField(to='AuthorDetail')def__str__(self):returnself.name#作者详情表classAuthorDetail(models.Model):phone=models.CharField(max_length=32)addr=models.CharField(max_length=32)def__str__(self):returnself.phone
##Django终端打印SQL语句
如果你想知道你对数据库进行操作时,Django内部到底是怎么执行它的sql语句时可以加下面的配置来查看 在Django项目的settings.py文件中,在最后复制粘贴如下代码: LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } } 配置好之后,再执行任何对数据库进行操作的语句时,会自动将Django执行的sql语句打印到pycharm终端上 补充: 除了配置外,还可以通过一点.query即可查看查询语句,注意只能是queryset对象
##怎样在Django项目中直接测试orm语句
#在app01目录下test.py文件 import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day72.settings")#该句在manage.py文件中可以直接拷贝过来 import django django.setup() #手动配置完毕 便可以在下面进行测试
##ORM操作
from django.test import TestCase # Create your tests here. import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day72.settings") import django django.setup() from app01 import models # 只有quertset对象才可以查看sql语句 # print(models.Publish.objects.all().query) # (一对多表)外键字段的增删改查 # 增 # 传数字 # models.Book.objects.create(title='红楼梦',price='199',publish_id=1) # 传对象 # publish_obj = models.Publish.objects.filter(pk=2).first() # models.Book.objects.create(title='红楼梦',price='199',publish=publish_obj) # 修改 # models.Book.objects.filter(pk=1).update(publish_id=3) # 传数字 # publish_obj = models.Publish.objects.filter(pk=1).first() # # 传对象 # models.Book.objects.filter(pk=2).update(publish=publish_obj) (多对多 第三张表) 外键字段的增删改查 # add即可以传数字 也可以传对象 还支持传多个 单个单个的参数 不要传容器类型 # book_obj = models.Book.objects.filter(pk=1).first() # # book_obj.authors.add(1) #跨到第三张表 # author_obj = models.Author.objects.all() # book_obj.authors.add(*author_obj) # # author_list = models.Author.objects.all() # print(author_list) # book_obj.authors.add(*author_list) # remove # book_obj = models.Book.objects.filter(pk=1).first() # book_obj.authors.remove(1) # book_obj.authors.remove(2,3) # 放对象也可以 # set # book_obj = models.Book.objects.filter(pk=1).first() # # book_obj.authors.set([1,]) # author_list = models.Author.objects.all() # book_obj.authors.set(author_list) # clear # book_obj = models.Book.objects.filter(pk=1).first() # book_obj.authors.clear() # 清空当前对象所对应的多对多关系 """ add remove set 上面三个可以传一个或多个参数 并且即可以是数字也可以是对象 clear 不传参数 直接清空 """ """ 正向 反向 # 正向与方向的概念解释 # 一对一 # 正向:author---关联字段在author表里--->authordetail 按字段 # 反向:authordetail---关联字段在author表里--->author 按表名小写 # 查询jason作者的手机号 正向查询 # 查询地址是 :山东 的作者名字 反向查询 # 一对多 # 正向:book---关联字段在book表里--->publish 按字段 # 反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书 # 多对多 # 正向:book---关联字段在book表里--->author 按字段 # 反向:author---关联字段在book表里--->book 按表名小写_set.all() 因为一个作者对应着多个图书 """ # 基于对象的跨表查询 (都是子查询) # 1.查询书籍是红楼梦的出版社的名称 # book_obj = models.Book.objects.filter(title='红楼梦').first() # print(book_obj.publish.name) # 2.查询东方出版社出版的所有的书 # publish_obj = models.Publish.objects.filter(name='东方出版社').first() # print(publish_obj.book_set) # app01.Book.None # print(publish_obj.book_set.all()) # 3.查询作者是jason的写过的所有的书 # author_obj = models.Author.objects.filter(name='jason').first() # print(author_obj.book_set) # app01.Book.None # print(author_obj.book_set.all()) # 4.查询作者jason的住址 # author_obj = models.Author.objects.filter(name='jason').first() # print(author_obj.author_detail.addr) # 5.查询手机号是110的作者姓名 # author_detail = models.AuthorDetail.objects.filter(phone='110').first() # print(author_detail.author.age) """ 基于对象的反向查询 除了一对一直接点表名小写就可以拿到关联对象 一对多个多对多反向都必须 表名小写_set """ # 基于双下划线的跨表查询 (都是联表查询) # 1.查询书籍是红楼梦的出版社名称 # res = models.Book.objects.filter(title='红楼梦').values('publish__name') # print(res) # 2.查询书籍是红楼梦的作者姓名 # res = models.Book.objects.filter(title='红楼梦').values('authors__name','title') # print(res) # 3.查询作者jason的手机号 # res = models.Author.objects.filter(name='jason').values('author_detail__phone') # print(res) # 4.查询书籍是红楼梦的作者的手机号 # res = models.Book.objects.filter(title='红楼梦').values('authors__author_detail__phone') # print(res) # 反向查询 # 1.查询出版社为东方出版社的所有图书的名字和价格 # res = models.Publish.objects.filter(name='东方出版社').values('book__title','book__price','name') # print(res)(正查) # res1 = models.Book.objects.filter(publish__name='东方出版社').values('title','price') # print(res1)(反查) # 2.查询作者姓名是jason的手机号 # res = models.Author.objects.filter(name='jason').values('author_detail__phone') # print(res)(正查) # res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone') # print(res1)(反查) # def func(): # pass # func.name = 'hahaha' # print(func.name)
##ORM十三个必会操作总结
#1、返回QuerySet对象的方法有 all() filter() exclude() order_by() reverse() distinct() #2、特殊的QuerySet values() 返回一个可迭代的字典序列 values_list() 返回一个可迭代的元祖序列 #3、返回具体对象的 get() first() last() #4、返回布尔值的方法有: exists() #5、返回数字的方法有 count()