zoukankan      html  css  js  c++  java
  • orm之多表操作

    表结构

    • class Book(models.Model):
          nid = models.AutoField(primary_key=True)  # 自增id(可以不写,默认会有自增id)
          title = models.CharField(max_length=32)
          publishDdata = models.DateField()  # 出版日期
          price = models.DecimalField(max_digits=5, decimal_places=2)  # 一共5位,保留两位小数
      
          #一个出版社有多本书,关联字段要写在多的一方
          # 不用命名为publish_id,因为django为我们自动就加上了_id
          publish = models.ForeignKey("Publish")  #foreignkey(表名)建立的一对多关系
          # publish是实例对象关联的出版社对象
          authorlist = models.ManyToManyField("Author")  #建立的多对多的关系
          def __str__(self):  #__str__方法使用来吧对象转换成字符串的,你返回啥内容就打印啥
              return self.title
      class Publish(models.Model):
          #不写id的时候数据库会自动给你增加自增id
          name =models.CharField(max_length=32)
          addr = models.CharField(max_length=32)
      
          def __str__(self):
              return self.name
      class Author(models.Model):
          name = models.CharField(max_length=32)
          age = models.IntegerField()
      
      class AuthorDeital(models.Model):
          tel = models.IntegerField()
          addr = models.CharField(max_length=32)
          author = models.OneToOneField("Author")  #建立的一对一的关系
      
    • 建立一对一的关系

      • OneToOneField()

      • 就是foreignkey+unique,只不过不需要我们自己来写参数了,并且orm会自动帮你给这个字段名字拼上一个_id,数据库中字段名称为authorDetail_id
        
      • au=models.OneToOneField("AuthorDetail",on_delete=models.CASCADE)
        
    • 建立一对多的关系

      • ForeignKey()

      • publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE,)
        
    • 建立多对多关系

      • ManyToManyField可以建在两个模型中的任意一个,自动创建第三张
        
    • 注意

      • 临时添加的字段,首先得考虑之前的数据有没有,设置一个默认值

      • 1、 表的名称myapp_modelName,是根据 模型中的元数据自动生成的,也可以覆写为别的名称  

        2、id 字段是自动添加的

        3、对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名

        4、这个例子中的CREATE TABLE SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。

        5、定义好模型之后,你需要告诉Django _使用_这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加models.py所在应用的名称。

        6、外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。

    logging-SQL语句

    • LOGGING = {
          'version': 1,
          'disable_existing_loggers': False,
          'handlers': {
              'console':{
                  'level':'DEBUG',
                  'class':'logging.StreamHandler',
              },
          },
          'loggers': {
              'django.db.backends': {
                  'handlers': ['console'],
                  'propagate': True,
                  'level':'DEBUG',
              },
          }
      }
      

    增删改查

    1,增

    • 一对多添加

      • # 一对多的添加
            # 方式一:如果是这样直接指定publish_id字段去添加值,前提是你的主表里面必须有数据
            # 主表:没有被关联的(因为book表是要依赖于publish这个表的)也就是publish表
            # 子表:关联的表
            models.Book.objects.create(title="追风筝的人",publishDdata="2015-5-8",price="111",publish_id=1)
            # 方式二:推荐
            pub_obj = models.Publish.objects.filter(name="人民出版社")[0]
            print(pub_obj)
            models.Book.objects.create(title = "简爱",publishDdata="2000-6-6",price="222",publish=pub_obj)
        
            # 方式三:save
            pubObj= models.Publish.objects.get(name="人民出版社") #只有一个的时候用get,拿到的直接就是一个对象
            bookObj = models.Book(title = "真正的勇士",publishDdata="2015-9-9",price="50",publish=pubObj)
            bookObj.save()
        
    • 多对多添加的两种方式

      • # 多对多的添加的两种方式
            # 方式一:
            # 先创建一本书:
            pub_obj=models.Publish.objects.filter(name="江南出版社").first()
            book_obj = models.Book.objects.create(title="醉玲珑",publishDdata="2015-4-10",price="222",publish=pub_obj)
            # #通过作者的名字django默认找到id
            haiyan_obj = models.Author.objects.filter(name="haiyan")[0]
            egon_obj = models.Author.objects.filter(name="egon")[0]
            xiaoxiao_obj = models.Author.objects.filter(name="xiaoxiao")[0]
            # 绑定多对多的关系、
            book_obj.authorlist.add(haiyan_obj, egon_obj, xiaoxiao_obj)
        
            # 方式二=========,查出所有的作者
            pub_obj = models.Publish.objects.filter(name="江南出版社").first()
            book_obj = models.Book.objects.create(title="醉玲珑", publishDdata="2015-4-10", price="222", publish=pub_obj)
            authers = models.Author.objects.all()
            # #绑定多对多关系
            book_obj.authorlist.add(*authers)
        

    2,删

    • remove:将某个特定的对象从被关联对象集合中去除,即解除关联关系

      •  # 解除多对多的关系(remove)
            book_obj=models.Book.objects.filter(title="醉玲珑").last() #找到书对象
            authers=models.Author.objects.filter(id__lt=3)  #找到符合条件的作者对象
            book_obj.authorlist.remove(*authers) #因为清除的是多条,得加个*
        
    • 清除绑定:clear

      • 清空被关联对象集合

      •  # 清除关系方法(clear)
            book_obj= models.Book.objects.filter(title="红楼梦")
            for book_obj_item in book_obj:#把所有红楼梦的都给清空了
                book_obj_item.authorlist.clear()
        
    • 两者区别:

      • remove:先将要清除的数据筛选出来,然后移除
      • clear:不用查,直接就把数据都清空了。
      • 各有应用场景

    3,改

    • 改和查一样

    4,查

    • 一对一查询记录

      • 正向查询:按字段属性
      • 反向查询:按表名,一对一用不到_set
    • 一对多查询记录

      • 正向查询:按字段属性
      • 反向查询:按表名_set
    • 多对多查询记录

      • 正向查询:按字段属性
      • 反向查询:按表名__set
    • related_name:别名

      • 你可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Article model 中做一下更改: publish = ForeignKey(Blog, related_name='bookList'),那么接下来就会如我们看到这般:

        # 查询 人民出版社出版过的所有书籍
         
           publish=Publish.objects.get(name="人民出版社")
         
           book_list=publish.bookList.all()  # 与人民出版社关联的所有书籍对象集合
        

    双下划线的跨表查询

    • 正向查询:按字段属性
    • 反向查询:按表名____
    • 先筛选,然后通过跨表查值的方法

    聚合查询

    • aggregate(*args, **kwargs),只对一个组进行聚合

    • SQL原生语句中的聚合为group by

    • aggregate()是QuerySet的一个终止子句,也就是不在返回一个QuerySet集合,他返回一些键值对

    • from django.db.models import Avg, Sum, Count, Max, Min
      
      #查询所有图书的平均价格
      ret = models.Book.objects.all().aggregrate(Avg("price"))
      print(ret)
      

    分组查询

    • annotate():为QuerySet中每一个对象都生成一个独立的汇总值,是对分组完之后的结果进行聚合

    • from django.db.models import Count
      
      #统计每一本书的作者个数
      方式一:
      ret = models.Book.objects.all().annotate(authorNum = Count("authorlist__name")).values("authorNum")
      #values中的内容就是要分组的内容,
      
      #统计不止一个作者的书
      ret = models.Book.objects.annotate(num_authors=Count("authorlist__name")).filter(num__gt=1).values("title","num_authors")
      
      #统计各个作者出书的总价格
      ret = models.Author.objects.all().annotate(pricrSum = Sum("book__price")).values("name","priceSum")
      
    • 总结

      • 按什么分组就以它作为基表
      • values在前,表示group by,也可以省略不写,默认为pk =====在后,表示取值,
      • filter在前,表示where条件====在后表示having
      • 在前与在后比较的是annotate()

    F查询和Q查询

    1,F查询

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

    • 
      from django.db.models import F
        前面的filter里面都是用字段与一个常量比较, 如果要比较的是两个字段呢,就需要借助F函数了
      
        不只是filter, 其他地方也可以用, 比如update
      
        用的时候将F()包裹某个字段就能拿到它的值了
      
        现将Book表插入阅读数与评论数两个字段后执行数据库迁移命令
      
        eg: 查询评论数大于阅读数的书
        	Book.objects.all().filter(commit_num__gt=F('read_num'))
      
        eg: 把所有书的评论数加1
        	Book.objects.all().update(commit_num=F('commit_num')+1)
        	
        eg: 把python这本书的阅读数减5
        	Book.objects.all().filter(name='python').update(reat_num=F('reat_num') - 5)
      

    Q查询

    • filte() 筛选中的关键字参数都是一起进行’AND’的,如果需要执行跟复杂的查询,例如or语句,则需要使用Q对象

    • &————与

    • |—————或

    • ~————非

    • 将两个条件分别用Q()包裹,中间放与或非符号

    • '''
      filter里面放多个条件时我们用逗号隔开他默认是and的关系

      Q函数是为了表示 与& , 或|, 非~ 的

      将两个条件分别用Q()包裹中间放与或非符号

      导入Q函数
      from django.db.models import Q

      eg: 查询作者名字是江南或者名字是egon的书的书名和作者
      Book.objects.all().filter(Q(authors__name='江南') | Q(authors__name='egon')).values('name','authors__name')

      eg: 查询作者不是江南的书
      Book.objects.filter(~Q(authors__name='江南'))
      '''

    希望你眼眸有星辰,心中有山海,从此以梦为马,不负韶华
  • 相关阅读:
    ajax上传文件
    nginx location指令详解
    总结php删除html标签和标签内的内容的方法
    useBuiltIns: 'usage'
    uni-app如何页面传参数的几种方法总结
    基于 schema 的数据校验
    canvas时点击事件和长按冲突
    vue 下载文件流,后台是get方式 ,并且导出出现excel乱码问题
    uni-app canvas 实现文字居中
    git reflog 回退
  • 原文地址:https://www.cnblogs.com/daviddd/p/12050229.html
Copyright © 2011-2022 走看看