• django6-orm进阶操作


    1.创建django环境的脚本

      在自定义脚本中操作orm ,但是自定义脚本中不具备django的环境 

    ###test.py 脚本,引入django的环境即可使用orm操作数据库
    import
    os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django1.settings") import django django.setup() from app1 import models

    2.orm字段的类型

      AutoField        自增长字段 ,代替默认的id字段成为表的主键 ,必须有主键参数

      BooleanField        布尔值字段 ,可以是0或1

      CharField         字符串类型 ,默认使用边长的varchar类型

      IntegerField       整数类型 ,最好用charfield存

      DecimalField        小数类型 ,可以限定整体的最大长度max_digits ,限定小数位长度decimal_places(四舍五入)

      DateTiemField      日期时间类型 ,常用两个参数 标记时间节点 auto_now_add自动记录创建时间 ,auto_now自动记录修改时间

        test_id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        sex = models.BooleanField()
        age = models.IntegerField()
        price = models.DecimalField(max_digits=10, decimal_places=2)
        create_time = models.DateField(auto_now_add=True)
        update_time = models.DateField(auto_now=True)

    3.orm字段的参数

      null = True        该字段是否可以为空 ,True表示可以为空

      default= '默认值'       该字段为空时的默认值

      primary_key=True       指定该字段为主键

      db_index           为字段创建索引

      db_column= '属性名'      默认django的字段名与db中的名字是一致的 ,db_column可以改变db中该字段的名字    

           

    4.自定义字段

      根据数据库中的字段类型, 自定义django的orm的字段 ,比如ChairField默认使用的是varchar速度较慢 ,我们换成定长的char类型

    class MycharField(models.Field):
        """
        自定义的char类型的字段类
        """
        def __init__(self, max_length, *args, **kwargs):
            self.max_length = max_length
            super(MycharField, self).__init__(max_length=max_length, *args, **kwargs)
    
        def db_type(self, connection):
            """
            指定字段数据库类型
            :param connection: 
            :return: 
            """
            return 'char({})'.format(self.max_length)
    
    
    class testn(models.Model):
        name = MycharField(max_length=12)

    5.django的admin后台管理系统

      使用web操作界面操作我们的orm对象 ,完成对数据库的修改 ,其中可以将我们想通过界面操作的表都注册

    ###创建管理员###
    python manage.py createsuperuser
    
    ###settings.py设置一下中文  LANGUAGE_CODE = 'zh-hans'
    ###注册到admin中### from django.contrib import admin from app1 import models 
    # 将表注册在admin系统 admin.site.register(models.presslist) admin.site.register(models.Book)

      字段参数与admin系统相关的

        blank = False              #该字段再admin界面填写不能为空

        BooleanField(choices=((0,'男'),(1,'女')))   #布尔值类型与admin界面显示建立对应关系

      嵌套类与admin系统关系类Meta

    class Person1(models.Model):  
        ......
        ......
        def __str__(self):
            return 'obj:{}'.format(self.name)        
    
        class Meta:
            db_table = "Person" ##数据库的表默认是与类名一致 ,这里可以自定义
    
            # 定义admin后台管理系统中该表每条数据的名字
            verbose_name = '个人信息'
    
            # 定义admin后台管理系统中整张表的意义名字
            verbose_name_plural = '所有用户信息'

     6.常规操作(查询筛选排序)

      分类:通过返回结果分类
        返回QuerySet的:all filter exclude values values_list distinct order_by reverse
        返回对象的: get first last
        返回布尔值: exists
        返回数字的: count
      详细使用:
        models.类名.object.create(属性=值,属性=值...) #创建一条记录
        models.类名.object.all() #取出所有对象放入对象列表
        models.类名.object.get('字段'=值) #获取对象,有重复值或者不存在都会报错 ,仅取唯一对象
        models.类名.object.filter('字段'=值) #可以获取匹配所有对象 ,放入对象列表
        models.类名.object.filter('字段'=值).exists() #可以获取匹配所有对象 ,匹配直接返回bool值
        models.类名.object.exclude('字段'=值) #与filter作用相反
        models.类名.object.filter('字段' = 值).fist() #取出对象列表的第一个对象
        models.类名.object.filter('字段' = 值).last() #取出对象列表的第最后一个对象
        models.类名.object.all().values() #取出对象列表中所有对象的属性以字典形式放入列表
        models.类名.object.all().values().distinct() #取出对象列表中所有对象的属性以字典形式放入列表 ,去重!!!!
        models.类名.object.all().values_list() #取出对象列表中所有对象的属性以字典形式放入元组
        models.类名.object.all().values_list('字段1','字段2') #仅显示某些字段
        models.Person1.objects.order_by('age') #按照age属性,升序排序放入对象列表
        models.Person1.objects.order_by('-age') #按照age属性,降序排序放入对象列表
        models.Person1.objects.order_by('-age','pk') #先按照age属性降序排列,当age一样,再按照nid属性进行升序排列放入对象列表
        models.Person1.objects.order_by('-age', 'pk') #对象列表数据翻转!!!
      技巧: 先取出对象列表 ,对对象列表灵活操作

     7.双下划线查询(模糊匹配,范围筛选)

       场景: 获取cpu是16和8的所有对象 ,获取主键小于100的所有对象 ,找到字段1为空的所有对象

       1)对属性范围划分

        gt大于 lt小于 gte大于等于 lte小于等于 in在元祖内的匹配 range范围匹配

          print(models.HostInfo.objects.filter(Cpu__lt=8))

          print(models.HostInfo.objects.filter(Cpu__gte=8))

          print(models.HostInfo.objects.filter(Cpu__in=(2,4)))

          print(models.HostInfo.objects.filter(Cpu__range=(8,64)))

      2)对属性模糊匹配

        模糊匹配: contains='匹配关键字'                  #只要该字段包含关键字就会被列出 icontains不区分大小写

            print(models.HostInfo.objects.filter(IP__contains='1.1.1'))

        开头结尾匹配: startswith  endswith  istartswith  iendswith        #匹配开头到开头结尾对象就会被列出 ,加 'i' 不区分大小写

            print(models.HostInfo.objects.filter(IP__contains='1.1.1'))

       3)匹配空字段与否

        可以将某个字段为空或不为空的全部列出来

          print(models.HostInfo.objects.filter(hostname__isnull=False)

          print(models.HostInfo.objects.filter(hostname__isnull=True))    #列出hostname字段为空的所有对象

    8.orm外键跨表查询 ,外键一对多

      这里我将  多的一方称为多表 , 一的一方称为一表

      多表中存在一表的id值 ,作为外键的关联字段 ,查询分为查询方向(正向,反向)查询结果(对象 ,属性)

    ####外键两张表 一对多    多对多三张表
    ##models.py
    class
    presslist(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name class Book(models.Model): name = models.CharField(max_length=32) p_id = models.ForeignKey('presslist', on_delete=models.CASCADE) def __str__(self): return self.name

    class Author(models.Model):
    name = models.CharField(max_length=32)
    books = models.ManyToManyField('Book')

    def __str__(self):
    return self.name
    ###########注册到admin中
    ##造数据
    # models.presslist.objects.create(name='樱花出版社')
    # models.presslist.objects.create(name='葡萄出版社')
    # models.presslist.objects.create(name='农夫出版社')
    # models.presslist.objects.create(name='苹果出版社')
    # models.presslist.objects.create(name='桃子出版社')

    # models.Book.objects.create(name='python初级',p_id_id=11)
    # models.Book.objects.create(name='python中级',p_id_id=13)
    # models.Book.objects.create(name='python高级',p_id_id=14)
    # models.Book.objects.create(name='java初级',p_id_id=15)
    # models.Book.objects.create(name='java高级',p_id_id=11)

    # models.Book.objects.create(name='service mesh',p_id_id=12)
    # models.Book.objects.create(name='django框架',p_id_id=12)

      外键之正向查询 : 使用多表对象获取一表的对象或者属性(多表有外键字段)

    # 跨表获取一表对象! 跨表获取一表属性
        obj = models.Book.objects.filter(name='python初级').first()      
        print(obj.p_id)        #一表对象
        obj1 = models.Book.objects.values_list("p_id__pk")     #一表属性
    print(obj1)          

      外键之反向查询 : 使用一表对象获取多表的对象或属性(一表无外键字段 ,但是有关系管理对象_set)

        # 跨表获取多表对象 ! 跨表获取一表属性
       obj2 = models.presslist.objects.filter(name='樱花出版社').first() print(obj2.book_set.all())  #多表对象 obj3 = models.presslist.objects.values_list('book__name') #多表属性 print(obj3)           

      外键跨表查询看似混乱 ,实际很简单 ,多表使用字段 ,一表使用关系管理对象_set 。多使用value

    9.多对多跨查询

      多对多则没有正反查询, 其中拥有ManyToManyField字段的表可以通过, 属性.all()获取关系管理对象 . 没有ManyToManyField字段的表通过  另张表名_set.all()获取关系管理对象

        obj = models.Author.objects.filter(name='鲁迅')[0]
       
      
    print(obj.books.all().values())          #跨表查询作者为鲁迅的所有书籍对象 obj1 = models.Book.objects.filter(name='python初级')[0] print(obj1.author_set.all().values())       #跨表查询书籍为'python初级'的所有作者对象

    10.外键与多对多的新增 ,关联 ,删除

      1)跨表创建记录 ,根据一个表的对象, 创建另一张表记录

        # 给作者对象跨表加本书
        auth = models.Author.objects.filter(name='鲁迅')[0]
        auth.books.create(name='故事会', p_id_id=12)
        print(auth.books.all().values())
        # 给书对象跨表加个作者 
        bk = models.Book.objects.filter(name='java初级')[0]
        bk.author_set.create(name='苏轼')
        print(bk.author_set.all().values())

      2)跨表关联已有对象

        #给已有的书关联一个已有作者
        bk = models.Book.objects.filter(name='java初级')[0]
        bk.author_set.add(*[1])
        print(bk.author_set.all().values())
    
        #给已有的作者关联一个已有的书
        auth = models.Author.objects.filter(name='佚名')[0]
        auth.books.add(*[14,15,16])
        print(auth.books.all().values())

      3)跨表删除  

        remove()    #删除指定关系

        clear()     #清空关系

        set()      #清空+重置关系

        #给已有的书删除一个已有作者
        bk = models.Book.objects.filter(name='java初级')[0]
        bk.author_set.remove(*[1])
        print(bk.author_set.all().values())
    
        #给已有的作者删除一个已有的书
        auth = models.Author.objects.filter(name='佚名')[0]
        auth.books.remove(*[14,15,16])
        print(auth.books.all().values())

    11.高级查询

      1)聚合查询

        相当于mysql中的聚合函数(avg ,sum ,count ,max...) ,貌似仅用于int类型  

        需要加载聚合函数 ,使用aggregate()方法 ,可以同时执行多个聚合函数查询 ,返回字典

    ##
    from django.db.models import Avg, Sum, Count, Max, Min

    print(models.Book.objects.aggregate(Sum('pk'), Max('pk'), Min('pk'), Avg('pk'), Count('pk')))

      2)分组查询

        根据一个条件分组 ,如对书进行分组 ,可以使用本表的p_id出版社分组 ,也可以使用跨表的作者条件分组 

        先获取对象列表 ,再使用annotate

    ##加入一个字段book表
        price = models.IntegerField(max_length=32)
    print(models.Book.objects.values('author__name').annotate(sum=Sum('price')))      #将书以作者名字分组
    print(models.Book.objects.values('p_id_id').annotate(sum=Sum('price')).values('p_id__name','sum'))  #将书以出版社名字分组

      3)F查询 ,F更新

        F能拿出其他字段数据作为条件!!!!!!!!

        F是个神奇的东西 ,可以理解为能把其他字段的值拿过来使用 ,如我有两个字段 销量 库存 ,F操作更新库存update=销量*2 ,F操作查询库存<销量

        F查询为book新增销量与库存字段! !数据迁移 ,手动添加数据

        xl = models.IntegerField(max_length=32)
        kc = models.IntegerField(max_length=32)

        F查询 :销量大于库存的书 ,销量小于库存的书 

        from django.db.models import F
    
        print(models.Book.objects.filter(xl__lt=F('kc')).values('xl','kc'))
        print(models.Book.objects.filter(xl__gt=F('kc')).values('xl','kc'))

        F更新 :保证库存为销量的3倍值      

        models.Book.objects.update(kc=F('xl') * 3)
        print(models.Book.objects.all().values('xl', 'kc'))

      4)Q逻辑关系筛选

        Q和F没有关系 - - ,Q可以做逻辑筛选    & | ~ (与或非)    

        Q筛选 :不超过100元的书且属于樱花出版社的书有哪些

    from django.db.models import Q
    print(models.Book.objects.filter(Q(price__lt=100) & Q(p_id_id=11)).values('price','p_id__name'))

        Q筛选 :价格在100以上和50以下的书籍

    print(models.Book.objects.filter(Q(price__gt=100) | Q(price__lt=50)).values('price'))

    12.事务

      一些列sql操作组成一个整体 ,当所有sql成功 ,那么整体就是成功的. 如果其中一条sql失败了那么全部回滚 

      使用transaction(交易)模块的atomic(原子)方法 ,但是外层需要异常处理 ,肯定会中断程序

        with transaction.atomic():

          sql

          sql

        from app1 import models
        from django.db import transaction
    
        try:
            with transaction.atomic():
                models.Book.objects.create(name='mysql事务1', p_id_id=12, price=67, xl=0, kc=20)
                models.Book.objects.create(name='mysql事务进阶1', p_id_id=13, price=87, xl=0, kc=20)
                int('ol')
        except Exception as e:
            print(e)

       

  • 相关阅读:
    Guava学习笔记(4):Ordering犀利的比较器
    Guava学习笔记(3):复写的Object常用方法
    Guava学习笔记(1):Optional优雅的使用null
    [BZOJ1076][SCOI2008]奖励关
    [BZOJ1821][JSOI2010]部落划分
    [BZOJ1041]圆上的整点
    [Luogu2324]八数码难题
    [BZOJ1085][SCOI2005]骑士精神
    [BZOJ3109] [cqoi2013]新数独
    [LnOI2019]长脖子鹿省选模拟赛 东京夏日相会
  • 原文地址:https://www.cnblogs.com/quguanwen/p/11400431.html
Copyright © 2020-2023  润新知