• django框架基础ORM跨表操作长期维护


     ###############    一对一跨表查询    ################

    import os
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM.settings")
        import django
        django.setup()
        from app01 import models
    
        # 一对一查询记录:author和authordetile是一对一的关系
        # 正向查询(按字段 authorDetail)
        # 反向查询(按表名 author):因为是一对一的关系了,就不用_set了。
    
        # 正向查询:查询egon的手机号
        # 基于对象的
        egon_obj = models.Author.objects.filter(name="egon").first()
        print(egon_obj.authorDetail.telephone)
        # 反向查询:手机号为13245的作者的姓名
        deital_obj = models.AuthorDetail.objects.filter(telephone="15001903539").first()
        print(deital_obj.author.name)

     ###############    一对多的跨表查询    ################

    import os
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM.settings")
        import django
        django.setup()
        from app01 import models
    
        # 外键的跨表查询
        # 正向查找,从多的一边查找一的一边,这是查询书籍id为1的出版社的名字
        # 基于对象:
        book1 = models.Book.objects.first()
        publiseh1 = book1.publish.name
        print(publiseh1)  # tenlen
        # 基于下划线的:
        book2 = models.Book.objects.filter(nid=1).values("publish__name")
        print(book2)  # <QuerySet [{'publish__name': 'tenlen'}]>
    
        # 反向查找
        # 基于对象
        publisher_obj = models.Publish.objects.get(nid=1)  # get返回一个对象
        book3=publisher_obj.book_set.all()
        # 如果在外键中设置了related_name = books
        # book3 = publisher_obj.books.all()
        print(book3)
        # 基于下划线的
        book4 = models.Publish.objects.filter(nid=1).values('book__title')  # <QuerySet [<Book: 红楼梦>]>
        # 如果在外键中设置了 related_name = books
        # book4 = models.Publish.objects.filter(id=1).values("books__title")  # <QuerySet [{'book__title': '红楼梦'}]>
        print(book4)

     ###############    一对多添加记录    ################

    import os
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM.settings")
        import django
        django.setup()
        from app01 import models
    
        # 一对多的添加
        # 方式一:如果是这样直接指定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()

     ###############    一对多修改记录    ################

    if __name__ == "__main__":
        import os,django
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_django.settings")
        django.setup()
        from app01 import models
    
        # 一对多的修改,
        # 前端传入id,new_book_title,new_publisher_id
        # edit_id=1
        # new_book_title='水浒传'
        # new_publisher_id=1
        # edit_book_obj = models.Book.objects.get(id=edit_id)
        # edit_book_obj.title = new_book_title
        # edit_book_obj.publisher_id = new_publisher_id
        # edit_book_obj.save()  # 保存

     ###############    多对多跨表查询    ################

    import os
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM.settings")
        import django
        django.setup()
        from app01 import models
    
        # 多对多查询记录:
        # 正向查询(按字段authorlist)
        # 反向查询(按表名book_set)
    
        # 正向查询:查询追风筝的人的这本书的所有的作者的姓名和年龄
        # 基于对象的
        book_obj = models.Book.objects.filter(title="红楼梦")[0]
        print(book_obj.authors.all().values("name", "age"))  # 这本书关联的所有作者对象的集合
    
    
        # 反向查询:查询作者是haiyan的这个人出了哪几本书的信息
        # 基于对象的
        haiyan_obj = models.Author.objects.filter(name="egon")[0]
        print(haiyan_obj)
        print("bookinfo====", haiyan_obj.book_set.all().first().title)  # 与该作者关联的所有书对象的集合
        # 基于下划线的
        ret = models.Author.objects.filter(name="egon").values("book__title")
        print(ret)

     ###############    多对多跨表添加数据    ################

    import os
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM.settings")
        import django
        django.setup()
        from app01 import models
    
        # 多对多操作
        # 作者和书籍就是多对多的,
    
        # 通过作者创建一本书籍
        author_obj = models.Author.objects.first()
        from datetime import date
        author_obj.book.create(title='鬼吹灯',publisher_id=1,price=123,inventory_num=123,sales_num=123,pub_data=date(1999,1,1))
    
        # 绑定多对多关系 添加一个
        book_obj = models.Book.objects.first()
        author_obj.book.add(book_obj)
    
        # 绑定多对多关系 添加多个
        book_obj = models.Book.objects.filter(id__gt=4)
        author_obj.book.add(*book_obj)
    
        # 解除绑定:remove: # 将某个特定的对象从被关联对象集合中去除。
        # 清除绑定:clear”  # 清空被关联对象集合。
        author_obj.book.remove(book_obj)
        author_obj.book.clear()
        # 总结:remove和clear的区别
        # remove:得吧你要清除的数据筛选出来,然后移除
        # clear:不用查,直接就把数据都清空了。
    
        # 外键的反向操作,
        # 找到id=1的出版社,
        # publisher_obj = models.Publisher.objects.get(id=1)
        # publisher_obj.books.clear()  # 这个只是把书关联的出版社字段清空了,这本书还在,
        # 对于ForeignKey对象,clear()和remove()方法仅在null=True时存在

      

     ###############    多对多跨表修改数据    ################

    if __name__ == "__main__":
        import os,django
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_django.settings")
        django.setup()
        from app01 import models
    
        # 多对多的修改,
        edit_id=6
        new_author='南派三叔'
        new_publisher_id=1
        new_books=(1,2)
        edit_author_obj = models.Author.objects.get(id=edit_id)
        edit_author_obj.name = new_author
        edit_author_obj.book.set(new_books)  # 这种表关联的方式是符合更新值的,这个要记住,new_books是书的id,可以是多个值,
        edit_author_obj.save()

     ###############    django--聚合和分组    ################

    if __name__ == "__main__":
        import os, django
    
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM.settings")
        django.setup()
        from app01 import models
    
        from django.db.models import Avg, Sum, Max, Min, Count
    
        # 聚合函数: aggregate
        # aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。
        # 查询所有书的数目
        print(models.Book.objects.all().aggregate(Count('nid')))  # 这是返回一个字典
        print(models.Book.objects.all().count())  # 这是返回一个数字,不是字典,
    
        # 书籍销量总和
        print(models.Book.objects.all().aggregate(Sum('price')))  # 返回也是一个字典  {'price__sum': Decimal('123.00')}
        print(models.Book.objects.all().aggregate(Sum('price')).values())  # 取值  dict_values([Decimal('123.00')])
        # 最大和最小就是一样的使用方法
        ret=models.Book.objects.all().aggregate(price_avg=Avg('price'),price_max=Max('price'),
                                                price_min=Min('price'),price_sum=Sum('price'))  # 为聚合值指定一个名称
        print(ret.get('price_max'))  # 可以通过这种方式把值取出来,
    
        # 单表查询分组
        # 我们在这里先复习一下SQL语句的分组
        # 员工表  id name age salary provice dept
        # 我们使用原生SQL语句,按照部分分组求平均工资:
        # select dept,AVG(salary) from employee group by dept;
        # ORM查询:
        # from django.db.models import Avg
        # Employee.objects.values("dept").annotate(avg=Avg("salary").values(dept, "avg")
        # 逻辑
        # 第一步就是按照部门分组,就先把部门查出来,
        # 第二步就是annotate,里面是聚合函数,
        # 第三步就是聚合之后平均值就是一个字段,就可以拿出来了,展示字段
    
        # 连表查询的分组:
        # 员工表  id name age salary provice dept_id
        # 部门表  id name
        # SQL查询:
        # select dept.name,AVG(salary) from employee
        # inner join dept on (employee.dept_id=dept.id)
        # group by dept_id;
        # ORM查询:
        # from django.db.models import Avg
        # models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg")
    
        # 更多的例子
        # 示例1:统计每一本书的作者个数
        ret1 = models.Book.objects.all().annotate(author_num=Count('author'))  # count里面是表名,
        # ret1是把所有的书查询出来了,但是里面的具体的书是多了一个属性就是author_num,
        for book in ret1:
            print(book.author_num)
        # 对结果还可以进行过滤,
        ret2 = models.Book.objects.all().annotate(author_num=Count('author')).filter(author_num__gt=1)
    
        # 示例2:统计出每个出版社买的最便宜的书的价格
        # 第一种方法
        publisher_list = models.Publish.objects.annotate(min_price=Min("book__price"))
        for obj in publisher_list:
            print(obj.min_price)
        # 第二种方法
        models.Book.objects.values("publisher__name").annotate(min_price=Min("price"))
        # < QuerySet[{'publisher__name': '沙河出版社', 'min_price': Decimal('9.90')},
        #            {'publisher__name': '人民出版社', 'min_price': Decimal('19.90')}] >
    
        # 示例3:统计不止一个作者的图书
        models.Book.objects.annotate(author_num=Count("author")).filter(author_num__gt=1)
    
        # 示例4:根据一本图书作者数量的多少对查询集 QuerySet进行排序
        models.Book.objects.annotate(author_num=Count("author")).order_by("author_num")
    
        # 示例5:查询各个作者出的书的总价格
        models.Author.objects.annotate(sum_price=Sum("book__price")).values("name", "sum_price")

     ###############    ORMorm多对多的三种方式    ################

    if __name__ == "__main__":
        import os, django
    
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_django.settings")
        django.setup()
        from app01 import models
    
        # orm多对多的三种方式
    
        # 多对多的方式
        # 1,orm自动帮我创建第三张表,书和作者之间的第三张表就是自动创建的,
        # 2,自己创建第三张表,利用外键分别关联作者和书,查询比较麻烦
        # 3,自己创建第三张表,使用orm的manyTomanyField,指定一下,
        #     book=models.ManyToManyField(to='book',through='Author2Book',through_fields=("author","book"))
        #     第三种的查询方式和第一种的查询方式一样的,因为已经做了关联了,
    
        # 我们使用第几种,
        # 如果第三张表没有额外的字段,就使用第一种方法,
        # 如果第三张表有额外的字段,这种可以使用第三种方法和第一种方法,
        # 比如相亲网站,一个男的可以联系多个女的,一个女的也可以联系多个男的,这就是多对多的,
        # 约会记录,多对多,这个表的结构,
        # id boy_id girl_id date 约会时间,
        # 注意:
        # 第三种方式,这种add() remove() 就没有了,
        # 举例:
        # 从作者关联的书里面移除id是1的书
        # 之前使用第一种方法的时候是:
        # models.Author.objects.get(id=1).book.remove(1)
        # 现在自己建第三张表,就不能使用这种方式了,
        # models.Author2Book.objects.get(author_id=1,book_id=1).delete()
    
        # 使用第一种方法:查询id=1的作者关联的书,
        # author_obj=models.Author.objects.get(id=4)
        # ret=author_obj.book.all()
        # print(ret)
    
        # 使用自己创建的第三张表,就不能使用这种方法了,因为里面没有book这个属性啊,
        # 怎么拿?
        # 先拿到作者为1的数据,在关联表
        ret = models.Author2Book.objects.filter(author_id=4).values_list('book_id')
        print(ret)  # <QuerySet [(4,), (5,)]>
        ret = [i[0] for i in ret]  # 看来列表推导式还是需要研究一下
        ret = models.Book.objects.filter(id__in=ret)
        print(ret)
        # 所以这种自己建立第三张表是比较麻烦的,
    
        

    对应的表结构

    # 自己创建第三张表的表结构
    class Book(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
    
    
    # 自己创建第三张表,并通过ManyToManyField指定关联
    class Author(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者姓名")
        books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))
        # through_fields接受一个2元组('field1','field2'):
        # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。
    
    
    class Author2Book(models.Model):
        author = models.ForeignKey(to="Author")
        book = models.ForeignKey(to="Book")
    
        class Meta:
            unique_together = ("author", "book")

     ###############    ORM的F和Q操作    ################

    import os
    
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ORM.settings")
        import django
    
        django.setup()
        from app01 import models
    
        # F查询
        # 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?
        # Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
        # 1、查看评论数大于阅读数的书
        from django.db.models import F
        print(models.Book.objects.filter(commentNum__gt=F("readNum")))
        # 2、修改操作也可以使用F函数, 比如将id大于1的所有的书的价格涨价100元
        print(models.Book.objects.filter(nid__gt=1).update(price=F("price") + 100))
        # 3、Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
        # # 查询评论数大于收藏数2倍的书籍
        # models.Book.objects.filter(commnetNum__lt=F('keepNum')*2)
    
        # Q查询:
        # filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。
        # Q对象,表示查询条件之间的逻辑关系,与&,或 | 非~(波浪号),
        # 1、查询id大于1并且评论数大于100的书
        from django.db.models import Q
        print(models.Book.objects.filter(nid__gt=1, commentNum__gt=100))
        print(models.Book.objects.filter(nid__gt=1).filter(commentNum__gt=100))
        print(models.Book.objects.filter(Q(nid__gt=1) & Q(commentNum__gt=100)))
        # 2、查询评论数大于100或者阅读数小于200的书
        print(models.Book.objects.filter(Q(commentNum__gt=100) | Q(readNum__lt=200)))
        # Q 对象可以使用& 和| 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。
        # 3、查询年份等于2017年或者价格大于200的书
        print(models.Book.objects.filter(Q(publishDdata__year=2017) | Q(price__gt=200)))
        # 4、查询年份不是2017年或者价格大于200的书
        print(models.Book.objects.filter(~Q(publishDdata__year=2017) & Q(price__gt=200)))
        # 查询id不等于1的书籍
        book4 = models.Book.objects.filter(~Q(id=1))

     ###############    ORM    ################

     ###############    ORM    ################

  • 相关阅读:
    hdu 1164 Eddy's research I
    hdu 3794 Magic Coupon
    hdu 1460 完数
    hdu 1201 18岁生日
    求一组整数中所有素数之和
    备忘录
    c判断括弧是否匹配
    N!大整数阶乘问题
    计算一个人从出生到现在活了多少天
    java web.xml配置详解(转)
  • 原文地址:https://www.cnblogs.com/andy0816/p/12320253.html
Copyright © 2020-2023  润新知