• Django ORM操作


    DjangoORM常用的操作     项目位置   G:asdORMdemo

    实例:我们来假定下面这些概念,字段和关系
    作者模型:一个作者有姓名和年龄。
    作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)
    出版商模型:出版商有名称,所在城市以及email。
    书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。
    建立关系表如下:
     
    <wiz_code_mirror>
     
     
     
    38
     
     
     
     
     
    1
    from django.db import models
    2
    3
    4
    class Author(models.Model):
    5
        nid = models.AutoField(primary_key=True)
    6
        name=models.CharField( max_length=32)
    7
        age=models.IntegerField()
    8
    9
        # 与AuthorDetail建立一对一的关系
    10
        authorDetail=models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE)
    11
    12
    13
    class AuthorDetail(models.Model):
    14
    15
        nid = models.AutoField(primary_key=True)
    16
        birthday=models.DateField()
    17
        telephone=models.BigIntegerField()
    18
        addr=models.CharField( max_length=64)
    19
    20
    21
    class Publish(models.Model):
    22
        nid = models.AutoField(primary_key=True)
    23
        name=models.CharField( max_length=32)
    24
        city=models.CharField( max_length=32)
    25
        email=models.EmailField()
    26
    27
    28
    class Book(models.Model):
    29
        nid = models.AutoField(primary_key=True)
    30
        title = models.CharField( max_length=32)
    31
        publishDate=models.DateField()
    32
        price=models.DecimalField(max_digits=5,decimal_places=2)
    33
    34
        # 与Publish建立一对多的关系,外键字段建立在多的一方
    35
        publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
    36
        # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
    37
        authors=models.ManyToManyField(to='Author',)
    38
     
     

     

    生成表如下:
         
       
     添加表记录                
    操作前先简单的录入一些数据:
    publish表:
    author表:
    authordetail表:
     
    <wiz_code_mirror>
     
     
    x
     
     
     
    1
        # 一对多创建表
    2
        # 方式一: 通过实例一个对象
    3
        publish_obj = Publish.objects.get(pk=1)
    4
        book_obj = Book.objects.create(title="西游记", publishDate="2013-03-03", publish=publish_obj, price=100.00)
    5
    6
        # 方式二: 通过外键字段 + __id
     
     
    7
        book_obj = Book.objects.create(title="西游记", publishDate="2012-12-12", price=100.00, publish_id=1)
     
     
     

            基于对象的查询        

        一对多查询 :   
    <wiz_code_mirror>
     
     
     
    x
     
     
     
     
     
    1
    # 正向查询(按字段:publish):
    2
        book_obj = Book.objects.get(title="西游记").publish.city
    3
        print(book_obj)
    4
        
    5
    # 反向查询(按表名:book_set):
    6
        book_list = Publish.objects.get(id=1).book_set.all()
    7
        for book_obj in book_list:
    8
           print(book_obj.title)
     
     
        一对一查询:    
    <wiz_code_mirror>
     
     
     
    15
     
     
     
     
     
    1
    # 正向查询(按字段:authorDetail):
    2
    3
    egon=Author.objects.filter(name="egon").first()
    4
    print(egon.authorDetail.telephone)
    5
    6
    7
    # 反向查询(按表名:author):
    8
    # 查询所有住址在北京的作者的姓名
    9
    
    
    10
    authorDetail_list=AuthorDetail.objects.filter(addr="beijing")
    11
    for obj in authorDetail_list:
    12
         print(obj.author.name)
    13
            
    14
    author_obj = AuthorDetail.objects.get(pk=1).author.name
    15
    print(author_obj)
     
     
        多对多查询:    
    <wiz_code_mirror>
     
     
     
    13
     
     
     
     
     
    1
    # 正向查询(按字段:authors)
    2
    # 金瓶眉所有作者的名字以及手机号
    3
    author_list = Book.objects.get(title="金瓶眉").authors.all()
    4
    print(author_list)
    5
    for author in author_list:
    6
        print(author.name, author.authorDetail.telephone)
    7
        
    8
    # 反向查询(按表名:book_set):
    9
    # 查询egon出过的所有书籍的名字
    10
    book_list = Author.objects.get(name="yuan").book_set.all()
    11
    for book in book_list:
    12
        print(book.title)
    13
     
     
    注意这里还可以设置related_name给外键表重命名:表名_set换成外键表的重命名即可

            基于Queryset的跨表查询        

        正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表    他们的本质都是进行了跨表查询
        一对多:查询苹果出版社出版过的所有书籍的名字与价格(一对多)    
    <wiz_code_mirror>
     
     
     
    18
     
     
     
     
     
    1
    # 练习:  查询苹果出版社出版过的所有书籍的名字与价格(一对多)
    2
    3
    # --------------------基于Queryset的跨表查询------------------
    4
    # 一对多查询
    5
    # 反向查询
    6
    # 练习:  查询苹果出版社出版过的所有书籍的名字与价格(一对多)  
    7
    book_list = Publish.objects.filter(name="苹果出版社").values("book__title", "book__price")
    8
    print(book_list)
    9
    10
    # 正向查询Book中的字段
    11
    book_list = Book.objects.filter(publish__name="苹果出版社").values("title", "price")
    12
    print(book_list)
    13
    14
    15
    # 添加了related_name: publish=models.ForeignKey(to="Publish", to_field="nid", related_name="pub", on_delete=models.CASCADE)
    16
    # 反向查询添加了related_name
    17
    book_list = Publish.objects.filter(name="苹果出版社").values("books__title", "books__price")
    18
    print(book_list)
     
     
        多对多:查询alex出过的所有书籍的名字(多对多)    
    <wiz_code_mirror>
     
     
     
    8
     
     
     
     
     
    1
     # 练习: 查询alex出过的所有书籍的名字(多对多)
    2
        # 反向
    3
        book_obj = Author.objects.filter(name="alex").values("book__title")
    4
        print(book_obj)
    5
    6
        # 正向
    7
        book_list = Book.objects.filter(authors__name="alex").values("title")
    8
        print(book_list)
     
     
        一对一:查询alex的手机号    
    <wiz_code_mirror>
     
     
     
    5
     
     
     
     
     
    1
    # 正向查询
    2
    ret=Author.objects.filter(name="alex").values("authordetail__telephone")
    3
    4
    # 反向查询
    5
    ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")
     
     
        进阶练习    
    <wiz_code_mirror>
     
     
     
    10
     
     
     
     
     
    1
    # 查询苹果出版社出版过的所有书籍的名字以及作者的姓名
    2
    3
    ret = Book.objects.filter(publish__name="苹果出版社").values("title", "authors__authorDetail__addr")
    4
    print(ret)
    5
    6
    # 练习: 手机号以133开头的作者出版过的所有书籍名称以及出版社名称
    7
    8
    ret = Book.objects.filter(authors__authorDetail__telephone__regex="133").values("title", "publish__name")
    9
    print(ret)
    10
     
     
            聚合查询和分组查询        
    聚合查询就是mysql里面的聚合函数!
            aggregate        
    <wiz_code_mirror>
     
     
     
    15
     
     
     
     
     
    1
    from django.db.models import Avg, Sum, Max, Min, Count
    2
    3
    4
    avg_price = Book.objects.all().aggregate(Avg("price"))
    5
    print(avg_price)
    6
    >>> {'price__avg': 19.79}   # 返回一个字典 
    7
    8
    # 指定一个键
    9
    avg_price = (Book.objects.all().aggregate(print_avg=Avg("price")))
    10
    print(avg_price)
    11
    >>> {'print_avg': 19.79}
    12
    13
        price = Book.objects.all().aggregate(Avg("price"), Sum("price"), Max("price"))
    14
        print(price)
    15
    >>> {'price__avg': 19.79, 'price__sum': Decimal('98.95'), 'price__max': Decimal('29.00')}
     
     
    分组查询就是mysql里面的group_by!
            annotate        

    <wiz_code_mirror>
     
     
     
    x
     
     
     
     
     
    1
    # 查询每本书作者的个数
    2
    3
    # select SUM(author_id), book_id from app01_author_books GROUP BY app01_author_books.book_id
    4
    ret = Book.objects.all().annotate(author_num=Count("author"))
    5
    print(ret)
    6
    # <QuerySet [<Book: 跟pontoon学python>, <Book: pontoon想跟dandylee谈朋友>, <Book: 特别想跟dandylee谈朋友>, <Book: pontoon一定要努力学好python>, <Book: 争取一入行就跟取加dandylee的微信>]>
    7
    8
    注意这里!他相当于给Book表增加了一个字段author_num(作者的数量)
    9
    for book in ret:
    10
        print("书名:{}, 作者数量:{}".format(book.title, book.author_num))
    11
    >>> 书名:特别想跟dandylee谈朋友, 作者数量:2
    12
    书名:pontoon一定要努力学好python, 作者数量:0
    13
    书名:争取一入行就跟取加dandylee的微信, 作者数量:0
    14
            
    15
    --------------------------------------------------------------------------------------------------------------------------------
    16
    # 查询作者数量大于1的书
    17
    ret = Book.objects.all().annotate(author_num=Count("author")).filter(author_num__gt=1)
    18
    print(ret)
    19
    20
    >>><QuerySet [<Book: 跟pontoon学python>, <Book: 特别想跟dandylee谈朋友>]>
    21
    # ret = Book.objects.all().annotate(author_num=Count("author"))得到的是一个查询集,可以用filter进行筛选(Having)
    22
    23
    for book in ret:
    24
        print("书名: %s, 作者的个数: %s" % (book.title, book.author_num))
    25
    26
    >>>书名: 跟pontoon学python, 作者的个数: 3
    27
    书名: 特别想跟dandylee谈朋友, 作者的个数: 2
    28
     
     
    F查询就是mySQL里面的两个字段进行比较
        F    
    给 book表增加两个新字段
    <wiz_code_mirror>
     
     
     
    9
     
     
     
     
     
    1
    class Book(models.Model):
    2
        id = models.AutoField(primary_key=True)
    3
        price = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    4
        # 库存
    5
        kucun = models.IntegerField(default=0)
    6
        # 售出
    7
        sail = models.IntegerField(default=0)
    8
        title = models.CharField(max_length=32)
    9
        publisher = models.ForeignKey(to="Publisher", to_field='id', on_delete=models.CASCADE, related_name="books")
     
     
    <wiz_code_mirror>
     
     
     
    1
     
     
     
     
     
    1
        
     
     
        Q    或运算 相当与mySQL里面的 or
    <wiz_code_mirror>
     
     
     
     
     
     
     
     
     
    1
        # 查询卖出数卖出数小于100 价格小于10.00的书
    2
        ret = Book.objects.filter(Q(sail__lt=100) | Q(price__lt=10.00))
    3
        print(ret)
    4
        
    5
        # 查询# 查询卖出数卖出数小于100 价格小于10.00的书,书名包含pontoon的书
    6
        ret = Book.objects.filter(Q(sail__lt=100) | Q(price__lt=10.00), title__contains="pontoon")
    7
        print(ret)
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    Android测试提升效率批处理脚本
    iOS系统设备网络抓包工具介绍:越狱和不越狱的办法
    用于管理Linux系统中的各种服务的命令service命令
    linux sort 命令详解
    在loadrunner操作中,所碰见问题及解决方法
    Unable to connect to the remote server 问题(已经解决)
    均值、中位数、众数
    修改Android 界面颜色
    设置Android程序图标和程序标题
    Android中的EditText默认时不弹出软键盘的方法
  • 原文地址:https://www.cnblogs.com/pontoon/p/10216862.html
Copyright © 2020-2023  润新知