django之模型层(待补充)
Posted michealjy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django之模型层(待补充)相关的知识,希望对你有一定的参考价值。
模型层
1. ORM查询
所有代码都是在test.py
文件中运行的
注意:我如果想在test.py
文件中测试相关代码,那么必须要进行配置,不然会报以下的错误
django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
意思就是,django
本身是一个搭好的框架,你不能单独运行某一个文件,它是一个整体,运行文件前必须要进行环境配置
所以我们的思路就是在test.py
文件中,让它一启动改文件,就把相关的环境配置好,于是就加了下面几句
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "one_search.settings")
import django
django.setup()
## 这几句话的意思就是,启动该文件时,把暴露给用户的配置文件字符串名加到内部环境变量大字典中,然后启动django,就相当于一小型的manage.py启动文件。
查看ORM
语句对应的sql
语句有两种方式
- 如果适合
queryset
对象,可以直接点query
查看 - 配置文件中直接配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level': 'DEBUG',
},
}}
## 例1 用query
from app01 import models
res = models.Book.objects.all()
res1 = models.Book.objects.all().query
print(res)
print(res1)
#<QuerySet [<Book: 科比自传>, <Book: 艾弗森自传>, <Book: 乔布斯自传>, <Book: 扎克伯格自传>, <Book: 马云自传>]>
#SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date` FROM `app01_book`
## 例2 用配置文件,直接写一句就可以了。
res = models.Book.objects.all()
#<QuerySet [<Book: 科比自传>, <Book: 艾弗森自传>, <Book: 乔布斯自传>, <Book: 扎克伯格自传>, <Book: 马云自传>]>
#(0.001) SELECT @@SQL_AUTO_IS_NULL; args=None
#(0.001) SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date` FROM `app01_book` LIMIT 21; args=()
只要是queryset对象就可以无限制的点queryset对象的方法
queryset.filter().filter().filter(),即使queryset对象是空也没关系
2.单表的增删改操作
## 增
# 方式一
models.Book.objects.create(title='时间简史',price=123.23,publish_date='2019-10-24')
'''
这样就会往数据库中存入数据,同时打印出sql语句
INSERT INTO 'app01_book'('title', 'price', 'publish_data') VALUES('时间简史', '123.23', '2019-10-24'); args=['时间简史', '123.23', '2019-10-24']
'''
# 方式二
from datetime import date
ctime = date.today()
book_obj = models.Book(title='时间简史', price=123, publish_date=ctime)
book_obj.save()
#结果和方式一是一样的
## 改
# 方式一
models.Book.object.filter(pk=1).update(price=999.66)
'''
会把主键为1的数据的价格改为999.66,同时打印出sql语句
UPDATE 'app01_book' SET 'price'='999.66' WHERE pk=1;
args=('999.66', 1)
'''
# 方式二
book_obj = models.Book.object.filter(pk=1).first()
book_obj.title = '奥尼尔自传'
book_obj.save()
'''
打印结果同上,只不过这种效率比较低,会把所有的数据重新保存一遍
'''
## 删除
models.Book.object.filter(pk=1).delete()
3. 单表查询(13+__)
13+
## 1.all() 查询所有 QuerySet
res = models.Book.objects.all() #惰性查询
print(res)
for i in res:
print(i.title)
'''
会先把sql语句打印出来
SELECT 'app01_book'.'id','app01_book'.'title','app01_book'.'price','app01_book'.'publish_date' FROM 'app01_book';
<QuerySet [<Book: 科比自传>, <Book: 艾弗森自传>, <Book: 乔布斯自传>, <Book: 扎克伯格自传>, <Book: 马云自传>, <Book: 时间简史>]>
科比自传
艾弗森自传
乔布斯自传
扎克伯格自传
马云自传
时间简史
'''
## 2.filter()
res = models.Book.object.filter(pk=2)
print(res)
'''
就相当于语句: select * from book where id = 2
'''
## 3.get() #不建议使用,这个是数据对象本身
## 4.first() 拿第一个
## 5.last() 拿最后一个
res = models.Book.objects.all()
print(res.first())
print(res.last())
'''
sql语句:
select * from book order by id asc/desc limit 1
'''
## 6.exclude 除此之外
#先取出id不是1的所有记录,然后再筛选出id为2的值
res = models.Book.objects.exclude(pk=1).filter(pk=2)
print(res)|
"""
sql语句就是:
select * from book where (not(id=1) and id=2)
"""
## 7.values 列表套字典
res = models.Book.objects.values('title')
for r in res:
print(r.ger('title'))
'''
返回的是一个一个字典,每个字典是title: 书名
'''
## 8.values_list 列表套元组
res = models.Book.objects.values_list('title')
print(res)
'''
返回的是一个一个元组,每个元组是 (书名,)
'''
## 9.count() 统计数据的个数
res = models.Book.objects.count()
res1 = models.Book.objects.all().count()
print(res)
'''
返回的是数字,表示有多少个数据,上面两句话是等价的
'''
## 10.distinct() 去重
"""去重:数据必须是一模一样的情况下才能去重"""
res = models.Book.objects.all().distinct()
# 上面这句去不了重,因为id不可能一样,因此需要按照其他的字段先筛选出一批,在进行去重就是避免id的干扰
res1 = models.Book.objects.values('title', 'price').distinct()
print(res1)
'''
sql语句就是:
select distinct book.title,book.price from book
'''
## 11.order_by() 排序
res = models.Book.objects.order_by('price') #默认是升序排序
res1 = models.Book.objects.order_by('-price') #降序排序
print(res)
'''
sql语句就是:
select * from book order by 'price' asc
'''
## 12.reverse() 前面必须是先结果排序才可以反转
res = models.Book.objects.order_by('price').reverse()
print(res)
'''
sql语句就是:
select * from book order by 'price' desc
'''
## 13.exists()
res = models.Book.objects.filter(pk=1).exists()
print(res)
'''
就是判断是否存在这个记录
'''
双下划线
# __gt/__lt/__gte/__lte=(大于,小于,大于等于,小于等于)
## 查询价格大于200的书籍
res = models.Book.objects.filter(price__get=200)
# __in=[1,2,3] 在列表中就返回,找到一个即可
res = models.Book.objects.filter(price__in=[200, 123.33])
# __range=(200, 700) 顾头不顾尾,在200-700之间
res = models.Book.objects.filter(price__range=(200, 700))
# 模糊匹配
##查询书籍名称中包含p的
res = models.Book.objects.filter(title__contains='p') #区分大小写
res = models.Book.objects.filter(title__icontains='p') #忽略大小写
##以什么开头/结尾 __startswith / __endswith
res = models.Book.objects.filter(title__startswith='三')
##日期
res = models.Book.objects.filter(publish_date__month='10')
res = models.Book.objects.filter(publish_date__year='2019')
多表操作(增删改和简单的查)
### 一对多字段的增删改查
##增
# 直接传出版社主键值
models.Book.objects.create(title='时间简史', price=123.22, publish_id=1)
'''前提是先在出版社中加入id为1的数据,这样就成功插入'''
# 直接传出版社数据对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title="科比自传",price=342.44, publish=publish_obj)
##查
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish) #拿到当前所对应的的出版社对象
print(book_obj.publish_id) #获取表中的实际字段值
##改
models.Book.objects.filter(pk=1).update
多表查询(ORM
跨表查询)
#正向查询和反向查询
例如:外键在book表上,book表和publish表是一对多的关系,那么,从book表开始查询,就是正向查询,否则就是反向查询
##记住一句话
正向查询按字段
反向查询按表名小写(一对多或者多对多时外键不唯一,这时候就需要 小写表名_set.all())
## 1.子查询
#1.查询时间简史的出版社名字
book_obj = models.Book.objects.filter(title='时间简史').first()
print(book_obj.publish.name)
print(book_obj.publish.addr)
"""正向查询按字段"""
#2.查询书籍主键是7的作者姓名
book_obj = models.Book.objects.filter(pk=7).first()
print(book_obj.authors) #会打印app01.Author.None 原因是由很多值,但是只接收了一个
"""正确的是""" print(book_obj.authors.all())
#3.查询作者是michael的手机号
author_obj = models.Author.objects.filter(name='michael').first()
print(author_obj.author_detail.phone)
'''
小总结:
正向查询按字段, 当该字段所对应的数据有多个的时候,加.all() 否则直接点外键字段拿到的是数据对象
'''
#4.查询出版社是人民出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='人民出版社').first()
print(publish_obj.book_set.all())
##5.查询作者是jason写过的所有的书
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set.all())
##6.查询手机号是234的作者
author_detail_obj = models.AuthorDetail.objects.filter(phone=234).first()
print(author_detail.author.name)
'''
小总结:
反向查找按照表名的小写形式
加set的时候是一对多或者多对多,主键值不唯一,小写表名_set.all()
一对一的时候不需要加任何东西,直接点属性
'''
##2.基于双下划线的跨表查询(是按字段查询的,不是按表名) 连表查询
"""
mysql
left join
inner join
right join
union
"""
#1.查询书籍是艾弗森自传的出版社名称
#正向
res = models.Book.objects.filter(title="艾弗森自传").values('publish__name')
print(res)
'''
原生sql:
select publish.name from book inner join publish on (book_id = publish_id) where book.title='艾弗森自传'
'''
#反向
res = models.Publish.objects.filter(book__title='艾弗森自传').values('name')
#2.查询作者是jason的手机号码
#正向
res = models.Author.objects.filter(name='jason').values('author_detail__phone')
print(res)
#反向
res = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
#3.查询手机号是123的作者姓名
##正向
res = models.AuthorDetail.objects.filter(phone=123).values('author__name')
##反向
res = models.Author.objects.filter(author_detail__phone=123).values('name')
#4.查询出版社是东方出版社的书籍名字
#正向
res = models.Publish.objects.filter(name="东方出版社").values('book__title')
#反向
res = models.Book.objects.filter(publish__name='东方出版社').values('title')
#5.查询作者是jason的写过的书的名字和价格
##正向
res = models.Author.objects.filter(name='jason').values('book__title', 'book_price')
##反向
res = models.Book.objects.filter(authors__name='jason').values('title', 'price')
'''反向查找需要到第三张()'''
#6.查询书籍是时间简史的作者的手机号
res = models.Book.objects.filter(title='时间简史').values('authors__author_detail__phone')
print(res)
以上是关于django之模型层(待补充)的主要内容,如果未能解决你的问题,请参考以下文章