Django之Model进阶

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都放在一个事务中执行(要么所有都成功,要么所有都失败)。

    '''
posted @ 2021-06-25 19:57  越关山  阅读(74)  评论(0)    收藏  举报