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='江南'))
      '''

    希望你眼眸有星辰,心中有山海,从此以梦为马,不负韶华
  • 相关阅读:
    【Language】 TIOBE Programming Community Index for February 2013
    【diary】good health, good code
    【web】a little bug of cnblog
    【Git】git bush 常用命令
    【web】Baidu zone ,let the world know you
    【diary】help others ,help yourself ,coding is happiness
    【Git】Chinese messy code in widows git log
    【windows】add some font into computer
    SqlServer启动参数配置
    关于sqlserver中xml数据的操作
  • 原文地址:https://www.cnblogs.com/daviddd/p/12050229.html
Copyright © 2011-2022 走看看