django学习第九天---raw查询原生sql和python脚本中调用django环境和ORM锁和事务

  • 在模型查询api不够用的情况下,我们还可以使用原始的sql语句进行查询
  • 方式1 raw()
      raw()方法,返回模型的实例django.db.models.query.RawQuerySet 实例
      这个RawQuerySet实例可以像一般的QuerySet那也,通过迭代来提供对象实例
      #注意:raw()语句查询必须包含主键
      ret = models.Book.objects.raw('select * from app01_book;')      
      #raw只能操作前面表的数据,比如Book
            print(ret)
            for i in ret:
                  print(i,type(i)) #Book Object
      
      raw()方法自动将查询字段映射到模型字段,还可以通过translations参数指定一个把查询的字段名和ORM对象实例的字段名互相对应的字典
      d = {'title':'xx'} #title是数据库中字段名,把title映射为xx
      ret = models.Book.objects.raw('select * from app01_book;',translations=d)
      for i in ret:
            print(i.price,i.xx)#调用i.xx得到的值相当于i.title得到的值

      原生sql还可以使用参数,注意不要自己使用字符串格式化拼接sql,防止sql注入
      d = {'title':'xx'}
      ret = models.Book.objects.raw('select * from app01_book where id>%s',translations=d,params=[1,])
      for i in ret:
            print(i.id,i.xx) #打印结果为id>1的所有数据
  • 方式2 直接从django提供的接口中获取数据库连接,然后使用pymysql一样操作数据库
      from django.db import connection
      cursor = connection.cursor()
      cursor.execute('select * from app01_book where id>%s',[1])
      #ret = cursor.fetchone() 查一条
      ret = cursor.fetchall() 查所有

python脚本中调用django环境

      xx.py文件,随便建一个文件,单独运行这个文件时,想获取到django的内容环境,需要下面的写法,下面这段代码就是manage.py文件中的开头那一段代码
      import os
      if __name__ == '__main__':
            os.environ.setdefault('DJANGO_SETTINGS_MODULE','django_orm2.settings')
      import django
      django.setup()
      #然后就可以操作了,如下面操作模型类
      from app01 import models #引入也要写在上面三句话之后
      print(models.Book.objects.all())
      

补充多个app配置models

  • app01的models文件内容
      from django.db import models
      class UserInfo(models.Model):
            name = model.CharField(max_length=12)
  • app02的models文件内容
      from django.db import models
      class Class(models.Model):
            user = models.ForeignKey('app01.UserInfo')#如果需要两个app之间的models进行关联,直接这样写就可以,或者直接将那个被关联的表,通过import的方法引入进行关联。

ORM锁和事务

加锁写法必须用在事务里面

      作用:可以通过锁防止数据被其它事务修改
      model.Book.objects.select_for_update().all()
      原生sql写法
      select * from app01_book for update;

事务写法

  • 方式1
      DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mxshop',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': '123',
       
        "ATOMIC_REQUESTS": True, #全局开启事务,绑定的是http请求响应整个过程  
          },
      }
      工作原理:当有请求过来时,django会在调用视图方法前开启一个事务,如果请求正确处理并正确返回了结果,django就会提交该事务,否则,django会回滚该事务
  • 方式2 给视图函数直接加装饰器,表示整个视图逻辑中的sql都捆绑为一个事务操作
      from django.db import transaction
      #sql一旦出错,会自动回滚
      @transaction.atomic
      def viewfunc(request):
            sid = transaction.savepoint() #创建保存点
            #This code executes inside a transaction
            do_stuff() #事务和变量等处理逻辑是没关系的

            do_other_stuff()
            transaction.savepoint_rollback(sid) #回滚保存点
            transaction.savepoint_commit(sid)#提交保存点
  • 方式3 给逻辑加视图
      from django.db import transaction
      def viewfunc(request):
            #This code executes in autocommit mode(Django's default)
            do_stuff()

            with transaction.atomic():  #加事务
                  #This code executes inside a transaction
                  do_more_stuff()
                  #model.Book.objects.select_for_update().all()
            do_other_stuff()