Django之Model进阶
一 原生sql的使用
# 1) 原生sql(有些sql用orm写不出来)
# 2) 两种方案
# 第一种:用的比较少
from django.db import connection
cursor = connection.cursor()
cursor.execute("""SELECT * from app01_book where id = %s""", [1])
# 默认结果显示元组,若要显示字典的话,需要自定义设置,django未直接提供相关方法
row = cursor.fetchone()
print(row) # (1, '西游记', Decimal('21.00'), datetime.datetime(2020, 10, 14, 20, 34, 25, 995754), 1, 99, 200)
row = cursor.fetchall()
print(row) # ()
# 第二种,用的多
# 1) 查找 id 大于3的书
books = models.Book.objects.raw('select * from app01_book where id >3')
print(books) # <RawQuerySet: select * from app01_book where id >3>
for book in books:
print(book.name) # Python从入门到入狱 三体
# 2) 查找 所有 出版社信息
books = models.Book.objects.raw('select * from app01_publish')
for book in books:
# print(books.__dict__)
print(book.name, end='<|-|>')
print(book.addr, end='<|-|>')
print(book.email, end='<|-|>')
print(book.price)
"""
北京出版社<|-|>北京<|-|>bj@qq.com<|-|>21.00
沙河出版社<|-|>北京<|-|>sh@qq.com<|-|>22.22
三体出版社<|-|>三体星<|-|>st@qq.com<|-|>66.66
"""
# 3)
authors = models.Author.objects.raw('SELECT app01_author.id,app01_author. NAME,app01_authordetail.gender FROM app01_author JOIN app01_authordetail ON app01_author.author_detail_id = app01_authordetail.id WHERE app01_authordetail.gender = 0')
for author in authors:
print(author.name)
print(author.__dict__)
"""
刘老牛 {'_state': <django.db.models.base.ModelState object at 0x000002035ED9AD00>, 'id': 1, 'NAME': '刘老牛', 'gender': 0, 'name': '刘老牛'}
小矮根 {'_state': <django.db.models.base.ModelState object at 0x000002035ED9ADC0>, 'id': 2, 'NAME': '小矮根', 'gender': 0, 'name': '小矮根'}
萧鼎 {'_state': <django.db.models.base.ModelState object at 0x000002035ED9AD00>, 'id': 3, 'NAME': '萧鼎', 'gender': 0, 'name': '萧鼎'}
刘慈欣 {'_state': <django.db.models.base.ModelState object at 0x000002035ED9AE20>, 'id': 4, 'NAME': '刘慈欣', 'gender': 0, 'name': '刘慈欣'}
"""
二 defer与only
# 由于使用了values()之后,可以取出想要的字段的数据,但是一个字典数组,我们仍然想要数据是一个对象,因此使用defer和only。
1) defer('id','name'): 取出对象,字段除了id和name都有
2) only('id','name'): 取的对象,只有id和name
3) 注意:如果点,依然能点出其它列,但是不要点了,因为取没有的列,会再次查询数据库
# #---->>>> defer和only(查询优化相关)
books = models.Book.objects.all().only('name')
print(books[0].name)
print(books[0].price) # 可以查出来,但是会造成效率问题,多查询了一次才查出来的
books = models.Book.objects.all().only('name')
print(books[0].__dict__)
books = models.Book.objects.all().defer('name', 'price')
print(books[0].__dict__)
"""
(0.000) SELECT `app01_book`.`id`, `app01_book`.`name` FROM `app01_book` LIMIT 1; args=()
(0.000) SELECT `app01_book`.`id`, `app01_book`.`publish_date`, `app01_book`.`publish_id`, `app01_book`.`read_num`, `app01_book`.`commit_num` FROM `app01_book` LIMIT 1; args=()
{'_state': <django.db.models.base.ModelState object at 0x0000026ECE849F40>, 'id': 1, 'name': '西游记'}
{'_state': <django.db.models.base.ModelState object at 0x0000026ECE871340>, 'id': 1, 'publish_date': datetime.datetime(2020, 10, 14, 20, 34, 25, 995754), 'publish_id': 1, 'read_num': 200, 'commit_num': 99}
"""
三 事务(三种粒度)
# djanog orm中使用事务:原子性操作,要么都成功,要么都失败
# #---->>>> 事务:ACID,事务的隔离级别
# 示例:新增一个作者详情,新增一个作者
# 1 局部使用
from django.db import transaction
with transaction.atomic(): # 都在事务中,要么都成功,要么都失败
author_detail = models.AuthorDetail.objects.create(addr='xxx', phone='123', sex=1)
# raise Exception('抛了异常')
author = models.Author.objects.create(name='llqz', age=19, author_detail=author_detail)
# 2 视图函数装饰器,这一个视图函数都在一个事务中
@transaction.atomic
def index(request):
return HttpResponse('ok')
# 3 整个http请求,在事务中,在setting.py中配置
'''
DATABASES = {
'default': {
...
'PORT': 3306,
'ATOMIC_REQUEST': True,
}
}
'ATOMIC_REQUEST': True,
设置为True统一个http请求对应的所有sql都放在一个事务中执行(要么所有都成功,要么所有都失败)。
'''