zoukankan      html  css  js  c++  java
  • django之跨表查询及添加记录

    创建表

    书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many); 一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。

    创建一对一的关系:OneToOne("要绑定关系的表名")

    创建一对多的关系:ForeignKey("要绑定关系的表名")

    创建多对多的关系:ManyToMany("要绑定关系的表名")  会自动创建第三张表

    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")  #建立的一对一的关系

    注意:临时添加的字段,首先你得考虑之前的数据有没有。设置一个默认值。(default=0 或者 null=True)

    通过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',
            },
        }
    }  

    多表操作

    增删改

    一对多的书籍记录增删改

    # 针对外键关联的字段 两种添加方式
    # 第一种通过publish_id
    # 第二种通过publish传出版社对象
    
    # 删除书籍直接查询删除即可,删除出版社会级联删除
    
    # 编辑数据也是两种对应的方式(对象点的方式(这里能点publish和publish_id)最后点save(),queryset方式update())

    多对多的书籍与作者的增删改

    """前提:先获取书籍对象,再通过书籍对象点authors来进行书籍作者的增删改查"""
    # 1.给书籍新增作者add
      # 1.add可以传作者id,也可以直接传作者对象,并且支持传多个位置参数(不要混着用)
      
    # 2.给书籍删除作者remove
        # 1.remove同样可以传id,对象,并且支持传多个位置参数(不要混着用)
    
    # 3.直接清空书籍对象所有的作者数据clear()不用传任何参数
    
    # 4.修改书籍对象所关联的作者信息set,注意点set括号内必须传可迭代对象,里面可以传id,对象
        
    """总结:一对多增删改,多对多add,remove,clear,set"""

    正反向概念

    基于对象的查询

    # 一对一
    # 正向:author---关联字段在author表里--->authordetail        按字段
    # 反向:authordetail---关联字段在author表里--->author        按表名小写
        # 查询jason作者的手机号   正向查询
        # 查询地址是 :山东 的作者名字   反向查询
      
    # 一对多
    # 正向:book---关联字段在book表里--->publish        按字段
    # 反向:publish---关联字段在book表里--->book        按表名小写_set.all() 因为一个出版社对应着多个图书
    
    # 多对多
    # 正向:book---关联字段在book表里--->author        按字段
    # 反向:author---关联字段在book表里--->book        按表名小写_set.all() 因为一个作者对应着多个图书
      
      
    
    # 连续跨表
        # 查询图书是三国演义的作者的手机号,先查书,再正向查到作者,在正向查手机号
    
    # 总结:基于对象的查询都是子查询,这里可以用django配置文件自动打印sql语句的配置做演示

    基于双下划线的查询

    -连表查询
            -一对一双下划线查询
                -正向:按字段,跨表可以在filter,也可以在values中
                -反向:按表名小写,跨表可以在filter,也可以在values中
        # 查询jason作者的手机号   正向查询  跨表的话,按字段
        # ret=Author.objects.filter(name='jason').values('authordetail__phone')
        # 以authordetail作为基表 反向查询,按表名小写  跨表的话,用表名小写
        # ret=AuthorDetail.objects.filter(author__name='jason').values('phone')
        
        # 查询jason这个作者的性别和手机号
        # 正向
        # ret=Author.objects.filter(name='jason').values('sex','authordetail__phone')
    
        # 查询手机号是13888888的作者性别
        # ret=Author.objects.filter(authordetail__phone='13888888').values('sex')
        # ret=AuthorDetail.objects.filter(phone='13888888').values('author__sex')
        
    总结 其实你在查询的时候先把orm查询语句写出来,再看用到的条件是否在当前表内,在就直接获取,不在就按照正向按字段反向按表名来查即可
    比如:
        1.查询出版社为北方出版社的所有图书的名字和价格
        res1 = Publish.objects.filter(name='').values('book__name','book__price')
        res2 = Book.objects.filter(publish__name='').values('name','price')
        2.查询北方出版社出版的价格大于19的书
        res1 = Publish.objects.filter(name='',book__price__gt=19).values('book__name','book__price)

    聚合查询

    关键字 aggregate

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

    利用聚合函数

    实例:

    models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price"))
    {'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}

    可以起别名:

    models.Book.objects.aggregate(average_price=Avg('price'))
    {'average_price': 13.233333}

    分组查询

    关键字 annotate

    1.统计每一本书的作者个数

    res = models.Book.objects.annotate(an=Count('authors')).values('an')
    print(res)

    2.统计每个出版社卖的最便宜的书

    res = models.Publish.objects.annotate(mp=Min('book__price'))
    print(res)

    F查询和Q查询

    F查询:

    在上面的所有例子中,我们构造的过滤器都是将字段值与某个常量值做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

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

    from django.db.models import F

    1.查询库存数大于卖出数的书籍

    res = models.Book.objects.filter(kucun__gt=F('maichu'))
    print(res)

    2.将书籍的库存数全部增加1000

    models.Book.objects.update(kucun=F('kucun')+1000)

    3.把所有书名后面面加上’新款‘

    from django.db.models.functions import Concat
    from django.db.models import Value
    models.Book.objects.update(title=Concat(F('title')),Value('新款'))

    Q查询 

    默认是and    |是or

    1.查询书籍名称是三国演义或者价格是444.44

    from django.db.models import Q
    
    res = models.Book.objects.filter(Q(title='三国演义')|Q(price=444.44))
    print(res)

    not  ~小波浪号  取反的意思

    res = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444))

    Q的高级用法

    q=Q()
    q.connector = 'or' #修改查询条件的关系  默认是and
    q.children.append(('title__contans','三国演义'))
    q.children.append(('price__gt',444))  #往列表里添加筛选条件
    res = models.Book.objects.filter(q) 
    print(res)
    万般皆下品,唯有读书高!
  • 相关阅读:
    topcoder srm 320 div1
    topcoder srm 325 div1
    topcoder srm 330 div1
    topcoder srm 335 div1
    topcoder srm 340 div1
    topcoder srm 300 div1
    topcoder srm 305 div1
    topcoder srm 310 div1
    topcoder srm 315 div1
    如何统计iOS产品不同渠道的下载量?
  • 原文地址:https://www.cnblogs.com/s686zhou/p/11565242.html
Copyright © 2011-2022 走看看