ORM常用字段及方式

创建小型数据库

模型层

  • ORM常用字段

AutoField

int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。

IntegerField

一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,)

CharField

字符类型,必须提供max_length参数, max_length表示字符长度。

DateField

日期字段,日期格式  YYYY-MM-DD,相当于Python中的datetime.date()实例。

DateTimeField

日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。

1 class User(models.Model):
2     name = models.CharField(max_length=32)
3     age = models.IntegerField()
4     register_time = models.DateField()

  1. 字段的参数

null

用于表示某个字段可以为空。

unique

如果设置为unique=True 则该字段在此表中必须是唯一的 。

db_index

如果db_index=True 则代表着为此字段设置索引。

default

为该字段设置默认值。

  2.DateField和DateTimeField

auto_now_add

配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

auto_now

配置上auto_now=True,每次更新数据记录的时候会更新该字段。

  •  关系字段

ForeignKey

外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 ‘一对多‘中‘多‘的一方。

ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。

字段参数

to

设置要关联的表

to_field

设置要关联的表的字段

on_delete

当删除关联表中的数据时,当前表与其关联的行的行为。

models.CASCADE

删除关联数据,与之关联也删除

db_constraint

是否在数据库中创建外键约束,默认为True。

  •   OneToOneField

一对一字段。

通常一对一字段用来扩展已有字段。(通俗的说就是一个人的所有信息不是放在一张表里面的,简单的信息一张表,隐私的信息另一张表,之间通过一对一外键关联)

字段参数

to

设置要关联的表。

to_field

设置要关联的字段。

on_delete

当删除关联表中的数据时,当前表与其关联的行的行为。(参考下面的例子)

1 ef func():
2     return 10
3
4 class MyModel(models.Model):
5     user = models.ForeignKey(
6         to="User",
7         to_field="id",
8         on_delete=models.SET(func)
9     )

 1 返回QuerySet对象的方法有
 2 all()
 3
 4 filter()
 5
 6 exclude()
 7
 8 order_by()
 9
10 reverse()
11
12 distinct()
13
14 特殊的QuerySet
15 values()       返回一个可迭代的字典序列
16
17 values_list() 返回一个可迭代的元祖序列
18
19 返回具体对象的
20 get()
21
22 first()
23
24 last()
25
26 返回布尔值的方法有:
27 exists()
28
29 返回数字的方法有
30 count()

操作小总结

单表查询操作演示表

1 # 单表查询表
2 class User(models.Model):
3     name = models.CharField(max_length=32)
4     age = models.IntegerField()
5     register_time = models.DateField()
6
7     def __str__(self):
8         return ‘对象的名字:%s‘%self.name

  1  # 新增数据
  2     # 基于create创建
  3     # user_obj = models.User.objects.create(name=‘tank‘,age=73,register_time=‘2019-2-14‘)
  4     # print(user_obj.register_time)
  5     # 基于对象的绑定方法创建
  6     # user_obj = models.User(name=‘kevin‘,age=30,register_time=‘2019-1-1‘)
  7     # user_obj.save()
  8     # from datetime import datetime
  9     # ctime = datetime.now()
 10     # models.User.objects.create(name=‘egon‘, age=18, register_time=ctime)
 11
 12
 13     # 修改数据
 14     # 基于对象
 15     # user_obj = models.User.objects.filter(name=‘jason‘).first()
 16     # user_obj.age = 17
 17     # user_obj.save()
 18     # 基于queryset
 19     # models.User.objects.filter(name=‘kevin‘).update(age=66)
 20
 21
 22     # 删除数据
 23     # 基于queryset
 24     # models.User.objects.filter(name=‘egon‘).delete()
 25     # 基于对象
 26     # user_obj = models.User.objects.filter(name=‘owen‘).first()
 27     # user_obj.delete()
 28
 29
 30     # 查询数据
 31     # < 1 > all(): 查询所有结果
 32
 33     # < 2 > filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
 34     # res = models.User.objects.filter(name=‘jason‘,age=17)
 35     # filter内可以放多个限制条件但是需要注意的是多个条件之间是and关系
 36     # print(res)
 37
 38     # < 3 > get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)
 39     # 不推荐使用
 40
 41     # < 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
 42     # res = models.User.objects.exclude(name=‘jason‘)
 43     # print(res)
 44     # < 5 > order_by(*field): 对查询结果排序(‘-id‘) / (‘price‘)
 45     # res = models.User.objects.order_by(‘age‘)   # 默认是升序
 46     # res = models.User.objects.order_by(‘-age‘)  # 可以在排序的字段前面加一个减号就是降序
 47     # res = models.User.objects.order_by(‘name‘)
 48     # res = models.User.objects.order_by(‘-name‘)
 49     # print(res)
 50
 51     # < 6 > reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向
 52     # res = models.User.objects.order_by(‘age‘).reverse()
 53     # print(res)
 54
 55     # < 7 > count(): 返回数据库中匹配查询(QuerySet) 的对象数量。
 56     # res = models.User.objects.count()
 57     # res = models.User.objects.all().count()
 58     # print(res)
 59
 60     # < 8 > first(): 返回第一条记录
 61     # res = models.User.objects.all().first()
 62     # res = models.User.objects.all()[0]  # 不支持负数的索引取值
 63     # print(res)
 64
 65     # < 9 > last(): 返回最后一条记录
 66     # res = models.User.objects.all().last()
 67     # print(res)
 68
 69     # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False
 70     # res = models.User.objects.all().exists()
 71     # res1 = models.User.objects.filter(name=‘jason‘,age=3).exists()
 72     # print(res,res1)
 73
 74     # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
 75     # model的实例化对象,而是一个可迭代的字典序列
 76     # res = models.User.objects.values(‘name‘)  # 列表套字典
 77     # res = models.User.objects.values(‘name‘,‘age‘)  # 列表套字典
 78     # print(res)
 79
 80     # < 12 > values_list(*field): 它与values()
 81     # 非常相似,它返回的是一个元组序列,values返回的是一个字典序列
 82     # res = models.User.objects.values_list(‘name‘,‘age‘)  # 列表套元祖
 83     # print(res)
 84
 85     # < 13 > distinct(): 从返回结果中剔除重复纪录  去重的对象必须是完全相同的数据才能去重
 86     # res = models.User.objects.values(‘name‘,‘age‘).distinct()
 87     # print(res)
 88
 89
 90     # 神奇的双下划线查询
 91
 92     # 查询年轻大于44岁的用户
 93     # res = models.User.objects.filter(age__gt=44)
 94     # print(res)
 95     # 查询年轻小于44岁的用户
 96     # res = models.User.objects.filter(age__lt=44)
 97     # print(res)
 98     # 查询年轻大于等于44岁的用户
 99     # res = models.User.objects.filter(age__gte=44)
100     # print(res)
101     # 查询年轻小于等于44岁的用户
102     # res = models.User.objects.filter(age__lte=44)
103     # print(res)
104
105     # 查询年龄是44或者22或者73的用户
106     # res = models.User.objects.filter(age__in=[44,22,73])
107     # print(res)
108
109     # 查询年龄在22到44范围内
110     # res = models.User.objects.filter(age__range=[22,44])
111     # print(res)
112
113
114     # 用的是mysql数据库
115     # 查询年份
116     # res = models.Book.objects.filter(publish_date__year=2019)
117     # print(res)
118
119
120     # 查询名字中包含字母n的用户  sqlite数据库演示不出来大小写的情况!!!
121     # res = models.Author.objects.filter(name__contains=‘n‘)
122     # res = models.Author.objects.filter(name__icontains=‘n‘)
123     # print(res)
124     # res = models.User.objects.filter(name__icontains=‘e‘)  # 无视大小写
125     # print(res)
126
127     # 查询名字以j开头的用户
128     # res = models.User.objects.filter(name__startswith=‘j‘)
129     # print(res)
130     # 查询名字以n结尾的用户
131     # res = models.User.objects.filter(name__endswith=‘n‘)
132     # print(res)
133
134     # 查询注册是在2017年的用户
135     # res = models.User.objects.filter(register_time__year=2017)  # sqlite对日期格式不太精准
136     # print(res)

单表查询操作演示表2

1 class Book(models.Model):
2       name = models.CharField(max_length=32)
3     price = models.DecimalField(max_digits=8,decimal_place=2)
4     publish = models.CharField(max_length=32)
5     author = models.CharField(max_length=32)
6     create_time = models.DateField(null=True)
7     # 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
8     # 配置上auto_now=True,每次更新数据记录的时候会更新该字段。

 1 新增数据
 2
 3             # 第一种:有返回值,并且就是当前被创建的数据对象
 4         modles.Book.objects.create(name=‘‘,price=‘‘,publish=‘‘,author=‘‘,create_time=‘2019-5-1‘)
 5         # 第二种:先实例化产生对象,然后调用save方法保存
 6         book_obj = models.Book(name=‘‘,price=‘‘,publish=‘‘,author=‘‘,create_time=‘2019-5-1‘)
 7         book_obj.save()
 8         # 2.验证时间格式字段即可以传字符串也可以传时间对象
 9         import datetime
10         ctime = datetime.datetime.now()
11         book = models.Book.objects.create(name=‘‘,price=‘‘,author=‘‘,create_time=ctime)
12
13 删除数据
14
15             """删除数据"""
16         # 1.删除书名为xxx的这本书  queryset方法
17         res = models.Book.objects.filter(name=‘‘).delete()
18         print(res)
19         # 2.删除书名为xxx的这本书  queryset方法
20         res = models.Book.objects.filter(name=‘‘).first()
21         res.delete()
22
23 修改数据
24
25             # 1.queryset修改
26         models.Book.objects.filter(name=‘‘).update(price=‘‘)
27         # 2.对象修改
28         book = models.Book.objects.filter(name=‘‘).first()
29         book.price = 66.66
30         book.save()  # 对象只有保存方法 这样也能实现修改需求
31
32 查询数据
33
34             <1> all():                  查询所有结果
35         <2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象
36         <3> get(**kwargs):          返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)
37         <4> exclude(**kwargs):      它包含了与所给筛选条件不匹配的对象
38         <5> order_by(*field):       对查询结果排序(‘-id‘)/(‘price‘)
39
40         <6> reverse():              对查询结果反向排序     >>>前面要先有排序才能反向
41         <7> count():                返回数据库中匹配查询(QuerySet)的对象数量。
42         <8> first():                返回第一条记录
43         <9> last():                返回最后一条记录
44         <10> exists():              如果QuerySet包含数据,就返回True,否则返回False
45         <11> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列                             model的实例化对象,而是一个可迭代的字典序列
46         <12> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
47         <13> distinct():            从返回结果中剔除重复纪录
48     # *******************
49            # 必须完全一样才可以去重(意味着带了id就没有意义了)
50            # res = models.Book.objects.all().values(‘name‘).distinct()  先查一个重复的值再去重
51
52 基于双下划线的查询
53
54     # 价格 大于 小于 大于等于 小于等于
55     filter(price__gt=‘90‘)
56     filter(price__lt=‘90‘)
57     filter(price_gte=‘90‘)
58     filter(price_lte=‘90‘)
59
60     # 存在与某几个条件中
61     filter(price__in=[‘11‘,‘22‘,‘33‘])
62     # 在某个范围内
63     filter(price__range=[50,90])
64
65     # 模糊查询
66     filter(title__contains=‘西‘)
67     filter(title__icontains=‘P‘)
68
69     # 以什么开头 以什么结尾
70
71     # 按年查询
72     filter(create_time__year=‘2017‘)

多表查询操作演示表

 1 # 多表查询表
 2 class Book(models.Model):
 3     title = models.CharField(max_length=32)
 4     price = models.DecimalField(max_digits=8,decimal_places=2)
 5     publish_date = models.DateField(auto_now_add=True)
 6     # 外键关系
 7     publish = models.ForeignKey(to=‘Publish‘)
 8     authors = models.ManyToManyField(to=‘Author‘)  # 虚拟字段, 信号字段
 9
10     def __str__(self):
11         return ‘书籍对象的名字:%s‘%self.title
12
13
14 class Publish(models.Model):
15     name = models.CharField(max_length=32)
16     addr = models.CharField(max_length=32)
17     email = models.EmailField()  # 对应就是varchar类型
18
19     def __str__(self):
20         return ‘出版社对象的名字:%s‘%self.name
21
22
23 class Author(models.Model):
24     name = models.CharField(max_length=32)
25     age = models.IntegerField()
26     authordetail = models.OneToOneField(to=‘AuthorDetail‘)
27
28     def __str__(self):
29         return  ‘作者对象的名字:%s‘%self.name
30
31
32 class AuthorDetail(models.Model):
33     phone = models.CharField(max_length=32)
34     addr = models.CharField(max_length=32)

  1     # 多表查询
  2     # 新增
  3     # 直接写id
  4     # models.Book.objects.create(title=‘红楼梦‘,price=66.66,publish_id=1)
  5     # 传数据对象
  6     # publish_obj = models.Publish.objects.filter(pk=2).first()
  7     # models.Book.objects.create(title=‘三国演义‘,price=199.99,publish=publish_obj)
  8
  9     # 修改
 10     # queryset修改
 11     # models.Book.objects.filter(pk=1).update(publish_id=3)
 12     # publish_obj = models.Publish.objects.filter(pk=2).first()
 13     # models.Book.objects.filter(pk=1).update(publish=publish_obj)
 14     # 对象修改
 15     # book_obj = models.Book.objects.filter(pk=1).first()
 16     # book_obj.publish_id = 3  # 点表中真实存在的字段名
 17     # book_obj.save()
 18     # publish_obj = models.Publish.objects.filter(pk=2).first()
 19     # book_obj.publish = publish_obj  # 点orm中字段名 传该字段对应的表的数据对象
 20     # book_obj.save()
 21
 22     # 删除
 23     # models.Book.objects.filter(pk=1).delete()
 24     # models.Publish.objects.filter(pk=1).delete()
 25
 26     # book_obj = models.Book.objects.filter(pk=3).first()
 27     # book_obj.delete()
 28
 29
 30     # 给书籍绑定与作者之间的关系
 31     # 添加关系 add:add支持传数字或对象,并且都可以传多个
 32     # book_obj = models.Book.objects.filter(pk=3).first()
 33     # # book_obj.authors.add(1)
 34     # # book_obj.authors.add(2,3)
 35     # author_obj = models.Author.objects.filter(pk=1).first()
 36     # author_obj1 = models.Author.objects.filter(pk=3).first()
 37     # # book_obj.authors.add(author_obj)
 38     # book_obj.authors.add(author_obj,author_obj1)
 39
 40     # 修改书籍与作者的关系  set()  set传的必须是可迭代对象!!!
 41     # book_obj = models.Book.objects.filter(pk=3).first()
 42     # 可以传数字和对象,并且支持传多个
 43     # book_obj.authors.set((1,))
 44     # book_obj.authors.set((1,2,3))
 45     #
 46     # author_list = models.Author.objects.all()
 47     # book_obj = models.Book.objects.filter(pk=3).first()
 48     # book_obj.authors.set(author_list)
 49
 50
 51     # 删除书籍与作者的绑定关系
 52     # book_obj = models.Book.objects.filter(pk=3).first()
 53     # # book_obj.authors.remove(1)
 54     # # book_obj.authors.remove(2,3)
 55     # # author_obj = models.Author.objects.all().first()
 56     # author_list = models.Author.objects.all()
 57     # # book_obj.authors.remove(author_obj)
 58     # book_obj.authors.remove(*author_list)  # 需要将queryset打散
 59
 60
 61     # 清空  clear()  清空的是你当前这个表记录对应的绑定关系
 62     # book_obj = models.Book.objects.filter(pk=3).first()
 63     # book_obj.authors.clear()
 64
 65
 66     # 基于对象的表查询
 67     # 正向
 68     # 查询书籍是三国演义的出版社邮箱
 69     # book_obj = models.Book.objects.filter(title=‘三国演义‘).first()
 70     # print(book_obj.publish.email)
 71     # 查询书籍是小王子的作者的姓名
 72     # book_obj = models.Book.objects.filter(title=‘小王子‘).first()
 73     # print(book_obj.authors)  # app01.Author.None
 74     # print(book_obj.authors.all())
 75     # 查询作者为jason电话号码
 76     # user_obj = models.Author.objects.filter(name=‘jason‘).first()
 77     # print(user_obj.authordetail.phone)
 78
 79     # 反向
 80     # 查询出版社是东方出版社出版的书籍                  一对多字段的反向查询
 81     # publish_obj = models.Publish.objects.filter(name=‘东方出版社‘).first()
 82     # print(publish_obj.book_set)  # app01.Book.None
 83     # print(publish_obj.book_set.all())
 84
 85     # 查询作者jason写过的所有的书                      多对多字段的反向查询
 86     # author_obj = models.Author.objects.filter(name=‘jason‘).first()
 87     # print(author_obj.book_set)  # app01.Book.None
 88     # print(author_obj.book_set.all())
 89
 90     # 查询作者电话号码是110的作者姓名                   一对一字段的反向查询
 91     # authordetail_obj = models.AuthorDetail.objects.filter(phone=110).first()
 92     # print(authordetail_obj.author.name)
 93
 94     # 基于双下滑线的查询
 95     # 正向
 96     # 查询书籍为三国演义的出版社地址
 97     # res = models.Book.objects.filter(title=‘三国演义‘).values(‘publish__addr‘,‘title‘)
 98     # print(res)
 99     # 查询书籍为小王子的作者的姓名
100     # res = models.Book.objects.filter(title=‘小王子‘).values("authors__name",‘title‘)
101     # print(res)
102     # 查询作者为jason的家乡
103     # res = models.Author.objects.filter(name=‘jason‘).values(‘authordetail__addr‘)
104     # print(res)
105
106     # 反向
107     # 查询南方出版社出版的书名
108     # res = models.Publish.objects.filter(name=‘南方出版社‘).values(‘book__title‘)
109     # print(res)
110     # 查询电话号码为120的作者姓名
111     # res = models.AuthorDetail.objects.filter(phone=120).values(‘author__name‘)
112     # print(res)
113     # 查询作者为jason的写的书的名字
114     # res = models.Author.objects.filter(name=‘jason‘).values(‘book__title‘)
115     # print(res)
116     # 查询书籍为三国演义的作者的电话号码
117     # res = models.Book.objects.filter(title=‘三国演义‘).values(‘authors__authordetail__phone‘)
118     # print(res)
119
120     # 查询jason作者的手机号
121     # 正向
122     # res = models.Author.objects.filter(name=‘jason‘).values(‘authordetail__phone‘)
123     # print(res)
124     # 反向
125     # res = models.AuthorDetail.objects.filter(author__name=‘jason‘).values(‘phone‘)
126     # print(res)
127
128     # 查询出版社为东方出版社的所有图书的名字和价格
129     # 正向
130     # res = models.Publish.objects.filter(name=‘东方出版社‘).values(‘book__title‘,‘book__price‘)
131     # print(res)
132     # 反向
133     # res = models.Book.objects.filter(publish__name=‘东方出版社‘).values(‘title‘,‘price‘)
134     # print(res)
135
136     # 查询东方出版社出版的价格大于400的书
137     # 正向
138     # res = models.Publish.objects.filter(name="东方出版社",book__price__gt=400).values(‘book__title‘,‘book__price‘)
139     # print(res)
140     # 反向
141     # res = models.Book.objects.filter(price__gt=400,publish__name=‘东方出版社‘).values(‘title‘,‘price‘)
142     # print(res)
143
144
145
146     # 聚合查询  aggregate
147     from django.db.models import Max,Min,Count,Sum,Avg
148     # 查询所有书籍的作者个数
149     # res = models.Book.objects.filter(pk=3).aggregate(count_num=Count(‘authors‘))
150     # print(res)
151     # 查询所有出版社出版的书的平均价格
152     # res = models.Publish.objects.aggregate(avg_price=Avg(‘book__price‘))
153     # print(res)  # 4498.636
154     # 统计东方出版社出版的书籍的个数
155     # res = models.Publish.objects.filter(name=‘东方出版社‘).aggregate(count_num=Count(‘book__id‘))
156     # print(res)
157
158
159     # 分组查询(group_by)   annotate
160     # 统计每个出版社出版的书的平均价格
161     # res = models.Publish.objects.annotate(avg_price=Avg(‘book__price‘)).values(‘name‘,‘avg_price‘)
162     # print(res)
163     # 统计每一本书的作者个数
164     # res = models.Book.objects.annotate(count_num=Count(‘authors‘)).values(‘title‘,‘count_num‘)
165     # print(res)
166     # 统计出每个出版社卖的最便宜的书的价格
167     # res = models.Publish.objects.annotate(min_price=Min(‘book__price‘)).values(‘name‘,‘min_price‘)
168     # print(res)
169     # 查询每个作者出的书的总价格
170     # res = models.Author.objects.annotate(sum_price=Sum(‘book__price‘)).values(‘name‘,‘sum_price‘)
171     # print(res)

创建图书管理系统表(给作者表加一张作者详情表为了一对一的查询),诠释一对一关联其实就是外健关联再加一个唯一性约束而已

ForeignKey(unique=Ture) >>> OneToOneField()
# 即一对一可以用ForeignKey来做,但是需要设唯一性约束并且会报警告信息,不建议使用,建议用OneToOneField
# 用了OneToOneField和用ForeignKey会自动在字段后面加_id
# 用了ManyToMany会自动创建第三张表

一对多的书籍记录增删改查

# 针对外键关联的字段 两种添加方式
# 第一种通过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)
"""

再次强调:

  1. 对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。

聚合查询和分组查询

聚合(利用聚合函数)

aggregate()QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。

键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。

用到的内置函数:

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

示例:

>>> from django.db.models import Avg, Sum, Max, Min, Count
>>> models.Book.objects.all().aggregate(Avg("price"))
{‘price__avg‘: 13.233333}

如果你想要为聚合值指定一个名称,可以向聚合子句提供它。

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

如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

>>> 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‘)}

分组

我们在这里先复习一下SQL语句的分组。

假设现在有一张公司职员表:

我们使用原生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分组,
这里有dept字段,所以按照dept字段分组

连表查询的分组:

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:统计每一本书的作者个数

>>> book_list = models.Book.objects.all().annotate(author_num=Count("author"))
>>> for obj in book_list:
...     print(obj.author_num)
...
1

示例2:统计出每个出版社买的最便宜的书的价格

>>> publisher_list = models.Publisher.objects.annotate(min_price=Min("book__price"))
>>> for obj in publisher_list:
...     print(obj.min_price)
...
9.90
19.90

方法二:

>>> 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)
<QuerySet [<Book: 番茄物语>]>

示例4:根据一本图书作者数量的多少对查询集 QuerySet进行排序

>>> models.Book.objects.annotate(author_num=Count("author")).order_by("author_num")
<QuerySet [<Book: 香蕉物语>, <Book: 橘子物语>, <Book: 番茄物语>]>

示例5:查询各个作者出的书的总价格

 

总结

value里面的参数对应的是sql语句中的select要查找显示的字段,

filter里面的参数相当于where或者having里面的筛选条件

annotate本身表示group by的作用,前面找寻分组依据,内部放置显示可能用到的聚合运算式,后面跟filter来增加限制条件,最后的value来表示分组后想要查找的字段值

原文地址:https://www.cnblogs.com/huangxuanya/p/11012696.html

时间: 2024-11-12 00:12:55

ORM常用字段及方式的相关文章

ORM常用字段

Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中. ORM在业务逻辑层和数据库层之间充当了桥梁的作用. ORM由来 让我们从O/R开始.字母O起源于"对象"(Object),而R则来自于"关系&qu

ORM常用字段和参数

ORM常用字段和参数 一.ORM字段 1. AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为id的列. 2. IntegerField 一个整数类型,范围在 -2147483648 to 2147483647. 3. CharField 字符类型,必须提供max_length参数, max_length表示字符长度. 4. DateField 日期字段,日期格式 YYYY-MM-DD,相当于Python中的da

orm常用字段和数据库优化查询

一.Django ORM 常用字段和参数 1.常用字段 models中所有的字段类型其实本质就那几种,整形varchar什么的,都没有实际的约束作用,虽然在models中没有任何限制作用,但是还是要分门别类,对于校验性组件校验非常有用就比如说邮箱类型,你在输入邮箱的时候如果不按照邮箱格式输入,瞎鸡儿输入会提示你不合法,虽然输入的是字符串,但是不是规定的邮箱字符串 AutoField() [int primary key auto_increment)] int自增列,必须填入参数 primary

orm 常用字段及参数

一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. id字段是自动添加的,如果你想要指定自定义主键,只需在其中一个字段中指定 primary_key=True 即可.如果Django发现你已经明确地设置了Field.primary_key,它将不会添加自动ID列. 本示例中的CREATE TABLE SQL使用PostgreSQL语法进行格式化,但值

ORM常用字段及参数

目录 ORM常用字段及参数 ORM常用字段 ORM字段参数 关系字段 必知必会13条 13个必会操作总结 ORM常用字段及参数 ORM常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为id的列. IntegerField 一个整数类型,范围在 -2147483648 to 2147483647.(一般不用它来存手机号(位数也不够),直接用字符串存,) CharField 字符类型,必须提供max_len

Django ORM常用字段及参数

目录 Django ORM常用字段及参数 models中的常用字段 字段内的关键字参数 数据库查询优化(面试问题) Django ORM如何开启事务操作 MTV与MVC模型(了解) Django ORM常用字段及参数 models中的常用字段 models中常用字段与数据库中的对应关系 models中常用字段 数据库对应字段 AutoField(primary_key=True) 主键字段 CharField(max_length=32) varchar(32) IntegerField() i

python3开发进阶-Django框架的ORM常用字段和参数

阅读目录 常用字段 字段合集 自定义字段 字段参数 关系参数 多对多的关联关系的三种方式 一.常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为id的列. IntegerField 一个整数类型,范围在 -2147483648 to 2147483647.  (最大十位) CharField 字符类型,必须提供max_length参数, max_length表示字符长度. DateField 日期字段,

Django&mdash;ORM常用字段和参数

一.ORM常用的字段和参数 1.0 常用字段 # AutoField: int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为id的列. # IntegerField: 一个整数类型,范围在 -2147483648 to 2147483647.(一般不用它来存手机号(位数也不够),直接用字符串存,) # CharField: 字符类型,必须提供max_length参数, max_length表示字符长度 # DateField: 日期字

Django ORM 常用字段和参数

一:常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为id的列. IntegerField 一个整数类型,范围在 -2147483648 to 2147483647. CharField 字符类型,必须提供max_length参数, max_length表示字符长度. DateField 日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例. DateTim