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)
 
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/pontoon/p/10216862.html