• Django之ORM(三) F查询和Q查询,事务及其他


    F与Q查询


    Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。


    settings.py

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        # 'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'ORM2',
            'PORT': 3306,
            'HOST': '127.0.0.1',
            'USER': 'root',
            'PASSWORD': 123
    
        }
    }
    
    

    init.py

    import pymysql
    pymysql.install_as_MySQLdb()
    

    models.py

    from django.db import models
    
    
    # Create your models here.
    
    class Product(models.Model):
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        maichu = models.IntegerField()
        kucun = models.IntegerField()
    
        def __str__(self):
            return '对象的名字:%s'%self.name
    

    执行命令创建表

    pycharm菜单-tools-run manage.py TASK
    $ makemigrations
    $ migrate
    

    tests.py

    from django.test import TestCase
    
    # Create your tests here.
    
    import os
    
    
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM2.settings")
        import django
        django.setup()
        from app01 import models
    

    初始数据


    F查询


    查询卖出数大于库存数的商品

    from django.db.models import F,Q
        # F查询 给一个字段就能拿到字段的值
        res=models.Product.objects.filter(maichu__gt=F('kucun'))
        print(res)
    

    将所有商品的价格提高100块

    models.Product.objects.update(price=F('price')+100)
    


    将所有商品的名字后面都加上一个爆款

    from django.db.models.functions import Concat
        from django.db.models import Value
        models.Product.objects.update(name=Concat(F('name'),Value('爆款')))
    


    Q查询


    <1> 查询价格是288.88并且名字是衣服同款爆款的商品(与查询)

    from django.db.models import Q
        from django.db.models import Q
    
        res = models.Product.objects.filter(Q(price='288.88'),Q(name='衣服爆款'))
        # 这里 第一个Q参数后面必须是传字符串,如果传数字(Q(price=288.88)),无法查询出对象
        print(res)
    

    <2> 查询价格是288.88或者名字是帽子同款爆款的商品(或查询)

    from django.db.models import Q
    res = models.Product.objects.filter(Q(price='288.88') | Q(name='裤子爆款'))  # or
    	print(res)
      # <QuerySet [<Product: 对象的名字:衣服爆款>, <Product: 对象的名字:裤子爆款>]>
    

    <3> 查询价格不是288.88并且名字是裤子爆款的商品

    混合使用 需要注意的是Q对象必须放在普通的过滤条件前面

    res=models.Product.objects.filter(~Q(price='288.88'),Q(name='裤子爆款'))
    print(res)
    

    <4> 查询价格不是288.88或者名字是裤子爆款的商品

    res=models.Product.objects.filter(Q(name='裤子爆款')|~Q(price='288.88'))
    print(res)
    

    Q对象补充

    Q的源码

    class Q(tree.Node):
        """
        Encapsulates filters as objects that can then be combined logically (using
        `&` and `|`).
        """
        # Connection types
        AND = 'AND'
        OR = 'OR'
        default = AND
    
        def __init__(self, *args, **kwargs):
            super(Q, self).__init__(children=list(args) + list(kwargs.items()
    

    Q本身就是一个类,实例化一个对象,将所有的条件传入children这个属性中,而children这个属性是是列表,将条件写成一个小元组的方式作为一个整体传入children这个列表,小元组的第一个元素是字段名,第二个元素是写希望字段名符合的条件


    例如

    Q=q()
    
    q.children.append((‘字段名’,‘条件’))
    

    <1> 查询价格是288.88或者名字是帽子同款爆款的商品

      from django.db.models import F, Q 
      q = Q()
      q.connector = 'or'
      q.children.append(('price', '288.88'))
      q.children.append(('name', '裤子爆款'))
      res = models.Product.objects.filter(q) # # Q对象查询默认也是and
      	print(res)
    

    <2> 查询价格是288.88或者名字是衣服爆款的商品

      from django.db.models import F, Q 
      q = Q()
      q.children.append(('price', '288.88'))
      q.children.append(('name', '衣服爆款'))
      res = models.Product.objects.filter(q) # # Q对象查询默认也是and
      	print(res)
    

    事务

    事务的ACID

    原子性
    一致性
    隔离性
    持久性

    id=1的商品卖出去一件

        from django.db import transaction
        from django.db.models import F
    
        with transaction.atomic():
            # 在with代码块儿写你的事务操作
            models.Product.objects.filter(id=1).update(kucun=F('kucun') - 1)
            models.Product.objects.filter(id=1).update(maichu=F('maichu') + 1)
    

    自定义ORM字段


    models.py

    from django.db import models
    
    
    class MycharField(models.Field):
        def __init__(self,max_length,*args,**kwargs):
            self.max_length=max_length
            super().__init__(max_length=max_length,*args,**kwargs)
    
        def db_type(self,connection):
            return 'char(%s)'%self.max_length
    
    
    class Product(models.Model):
        name = models.CharField(max_length=32) # 都是类实例化的对象
        price = models.DecimalField(max_digits=8, decimal_places=2)
        maichu = models.IntegerField()
        kucun = models.IntegerField()
        info=MycharField(max_length=32,null=True) # 该字段可以为空
    
        def __str__(self):
            return '对象的名字:%s'%self.name
    

    执行manage.py命令

    菜单-tools-Run manager.py Task
    $ makemigrations
    $ migrate
    


    only与defer

    res = models.Product.objects.filter(id=1).values('name').first()
    print(res)
    

    这个过程中执行了3条sql语句

    (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0.000) SELECT VERSION(); args=None
    (0.000) SELECT `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 1 LIMIT 21; args=(1,)
    

    only

    如果取only指定的字段,不去数据库取值,直接在应用程序的缓存中取值

    案例1

    res=models.Product.objects.filter(pk=1).only('name').first()
    print(res.name)
    

    这个过程执行了3条SQL语句

    (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0.000) SELECT VERSION(); args=None
    (0.000) SELECT `app01_product`.`id`, `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 1 ORDER BY `app01_product`.`id` ASC LIMIT 1; args=(1,)
    

    案例2

    res=models.Product.objects.filter(pk=1).only('name').first()
    print(res.price)
    

    这个过程中执行了4条SQL语句,因为price字段不在only里面配置,所以price字段的值是去数据库里面取

    (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0.000) SELECT VERSION(); args=None
    (0.000) SELECT `app01_product`.`id`, `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 1 ORDER BY `app01_product`.`id` ASC LIMIT 1; args=(1,)
    (0.000) SELECT `app01_product`.`id`, `app01_product`.`price` FROM `app01_product` WHERE `app01_product`.`id` = 1; args=(1,)
    

    defer

    与only相反,如果取defer指定的字段,则是去数据库取值,其他的字段直接在应用程序的缓存中取值


    案例1

    res=models.Product.objects.filter(pk=1).defer('name').first()
    print(res.name)
    

    执行了4条SQL语句

    (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0.000) SELECT VERSION(); args=None
    (0.000) SELECT `app01_product`.`id`, `app01_product`.`price`, `app01_product`.`maichu`, `app01_product`.`kucun`, `app01_product`.`info` FROM `app01_product` WHERE `app01_product`.`id` = 1 ORDER BY `app01_product`.`id` ASC LIMIT 1; args=(1,)
    (0.000) SELECT `app01_product`.`id`, `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 1; args=(1,)
    

    案例2

    res=models.Product.objects.filter(pk=1).defer('name').first()
    print(res.price)
    

    执行了3条SQL语句

    (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0.000) SELECT VERSION(); args=None
    (0.001) SELECT `app01_product`.`id`, `app01_product`.`price`, `app01_product`.`maichu`, `app01_product`.`kucun`, `app01_product`.`info` FROM `app01_product` WHERE `app01_product`.`id` = 1 ORDER BY `app01_product`.`id` ASC LIMIT 1; args=(1,)
    

    字段

    choices

    models.py

    from django.db import models
    
    class Product(models.Model):
        name = models.CharField(max_length=32) # 都是类实例化的对象
        price = models.DecimalField(max_digits=8, decimal_places=2)
        maichu = models.IntegerField()
        kucun = models.IntegerField()
        info=MycharField(max_length=32,null=True) # 该字段可以为空
    
        choices=((1,'男'),(2,'女'),(3,'其他'))
        gender=models.IntegerField(choices=choices,default=2)
    
        def __str__(self):
            return '对象的名字:%s'%self.name
    

    更新字段操作

    菜单-tools-Run manager.py Task
    $ makemigrations
    $ migrate
    

    tests.py

    import os
    
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM2.settings")
        import django
    
        django.setup()
        from app01 import models  
      	res=models.Product.objects.filter(id=1).first()
        print(res.get_gender_display()) # 获取编号对应的中文注释
    
  • 相关阅读:
    第0次作业
    第4次作业
    第3次作业
    第2次作业
    C#浮点数保留位数
    第0次作业
    软件工程第4次作业
    软件工程第3次作业
    软件工程第2次作业
    软件工程第1次作业
  • 原文地址:https://www.cnblogs.com/cjwnb/p/11802810.html
Copyright © 2020-2023  润新知