Django框架(七):Django模型系统 ② 常用查询及表关系的实现

1.常用查询

每一个Django模型类,都有一个默认的管理器objects
QuerySet表示数据库中对象的列表,他可以有0到多个过滤器,过滤器通过给定的参数缩小查询范围。
QuerySet等同于select语句,过滤器是一个限制字句,比如where,比如limit。

  • all() 获取所有
In [1]: from teacher.models import Students   
In [2]: Students.objects.all()
Out[2]: <QuerySet [<Students: 小米>, <Students: 小明>, <Students: 小李>]>  ##返回的是QuerySet
  • 获取第一条
In [3]: Students.objects.first() 
Out[3]: <Students: 小米>    #返回的是对象
  • 获取最后一条
In [4]: Students.objects.last()
Out[4]: <Students: 小李>
  • get(**kwargs)根据给定的条件获取一个对象,如果符合多个,或者没有就会报错
In [5]: Students.objects.get(pk=1)
Out[5]: <Students: 小米>
  • filter(**kwargs)过滤,根据参数提供的条件,获取一个过滤器后的QuerySet,多个条件等于 select 语句使用and连接
In [17]: Students.objects.filter(name='小明').first()                                      
Out[17]: <Students: 小明>
  • exclude()排除,作用和filter()相反
In [19]: Students.objects.exclude(pk=1)                                              
Out[19]: <QuerySet [<Students: 小明>, <Students: 小李>]>
  • get_or_create() 有则获取,无则创建,返回一个由(object, created)组成的元组,元组中的object 是一个查询到的或者是被创建的对象, created 是一个表示是否创建了新的对象的布尔值。
    get_or_create() 函数的详细介绍 https://www.cnblogs.com/zhongbokun/p/9732698.html

排序

  • order_by(*fields),根据给定的字段排序
In [20]: Students.objects.all().order_by('name')     #根据name字段正序排序                                     
Out[20]: <QuerySet [<Students: 小明>, <Students: 小李>, <Students: 小米>]>
In [21]: Students.objects.all().order_by('name','-age')      #根据age反序排序             
Out[21]: <QuerySet [<Students: 小明>, <Students: 小李>, <Students: 小米>]>
  • 切片:使用列表的切片语法操作QuerySet,除了不能负索引,其他的都可以,他等价于select语句里面的LIMITOFFSET字句
In [24]: Students.objects.all().order_by('name')[::-1]                                         
Out[24]: [<Students: 小米>, <Students: 小李>, <Students: 小明>]

限制字段查询

  • values(*fields)返回QuerySet,这个QuerySet返回的是一个字典列表。参数fields指定了select中我们想要限制查询的字段。返回的字典列表 中,只会包含我们指定的字段,如果不指定,包含所有字段。
In [25]: Students.objects.values('name')                                                       
Out[25]: <QuerySet [{'name': '小米'}, {'name': '小明'}, {'name': '小李'}]>

In [26]: print(Students.objects.values('name').query)                                                              
SELECT `teacher_students`.`name` FROM `teacher_students`
  • only(*fields)返回一个 QuerySet,跟values一样,不同的是这个QuerySet是对象列表,only一定包含主键。
In [27]: Students.objects.only('name')                                                           
Out[27]: <QuerySet [<Students: 小米>, <Students: 小明>, <Students: 小李>]>
  • defer(*fields)用法与only相反

多条件OR连接

需要使用or条件,我吗要使用到Q对象

In [28]: from django.db.models import Q    #导入Q模块

In [29]: Students.objects.filter(Q(name='小米')|Q(name='小明'))                  
Out[29]: <QuerySet [<Students: 小米>, <Students: 小明>]>

查询条件

相当于是SQL语句中的where语句后面的条件,语法为字段名__规则

In [30]: Students.objects.filter(name__exact='小米')    # 等同于namet='小米'     
Out[30]: <QuerySet [<Students: 小米>]>
  • exact - 精确匹配
  • iexact - 忽略大小写
  • contains - 模糊匹配,等同于%条件%
  • icontains - 大小写不敏感模糊匹配
  • in - 字段名__规则=列表 只要条件在列表中都匹配
  • gt - 大于
  • gte - 大于等于
  • lt - 小于
  • lte - 小于等于
  • startwith - 以什么条件开始
  • istartwith - 以什么条件开始,忽略大小写
  • endwith - 以什么结尾
  • iendwith - 以什么结尾,忽略大小写
  • range - 范围区间
  • isnull - filter(age__isnull=True)字段为空的

聚合函数

  • count统计数量 (严格来说不算聚合函数)
In [31]: Students.objects.all().count()                                                     
Out[31]: 3
  • Avg 计算平均值
In [32]: from django.db.models import Avg #导入模块
In [34]: Students.objects.aggregate(age_avg=Avg('age'))                                                                 
Out[34]: {'age_avg': 15.0}
  • Max - 找出最大值
  • Mix - 找出最小值
  • Sum - 计算求和
分组聚合

分组需要结合values,annotate和聚合 ,方法 看下面的案例
查询男生女生多少人:

In [35]: from django.db.models import Count  

In [37]: Students.objects.values('sex').annotate(Count('sex'))        
Out[37]: <QuerySet [{'sex': 1, 'sex__count': 3}]>

关于聚合查询的详细介绍 ==》https://blog.csdn.net/weixin_42134789/article/details/84567365

2.常用模型字段类型

  • int - IntegetField:整型,映射到数据库中的int类型
  • varchar - CharField : 字符类型,映射到数据库中的varchar类型,通过max_length指定最大长度,max-length为必须参数,否则会报错
  • longtext - TextField:文本类型,映射到数据库中的text类型
  • tinyint - 布尔类型,映射到数据库中的tinyint类型,在使用的时候,传递True/False进去。如果要可以为空,则用NullBooleanField
  • date - DateField:日期类型,没有时间
  • datetime - DateTimeField:日期时间类型。映射到数据库中的是datetime类型,在使用的时候,可以设置DateField.auto_now每次保存对象时,自动设置该字段为当前时间。设置DateField.auto_now_add当对象第一次被创建时自动设置当前时间

3.常用模型字段参数

  • primary_key: 指定是否为主键
  • unique: 指定是否唯一。
  • null: 指定是否为空,默认为False。
  • blank: 等于True时form表单验证时可以为空,默认为False。
  • default: 设置默认值。
  • DateField.auto_now: 每次修改都会将当前时间更新进去,只有调用,QuerySet.update方法将不会调用。这个参数只是Date和DateTime以及TimModel.save()方法才会调用e类才有的。
  • DateField.auto_now_add: 第一次添加进去,都会将当前时间设置进去。以后修改,不会修改这个值

4.表关系实现

Django中,模型通过特殊的字段进行关系连接

  • 一对一

from django.db import models

# Create your models here.

class Students (models.Model): # 一个类代表一个数据表
    id = models.AutoField(primary_key=True) ##创建一个可以自动生成的主键,这条也可以不写,Django中会自动生成主键
    name = models.CharField(verbose_name='姓名',max_length=20)   ##创建字符类型字段,最大长度为20,设置提示信息'姓名'
                                            ### max_length为CharField的必须参数
    age = models.SmallIntegerField(verbose_name='年龄',null=True) ##创建值可以为null的小整型字段,
    sex = models.SmallIntegerField(default=1)   ##创建缺省值为1的小整型字段
    qq = models.CharField(max_length=20,null=True)
    phone = models.CharField(max_length=20,null=True)
    c_time = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)  ##创建日期时间类型字段,自动创建当前时间

    def __str__(self):
        return self.name

class StudentsDetail(models.Model):  #学生详情表
    student = models.OneToOneField('Students',on_delete=models.CASCADE) #一对一关联,关联Students类,on_delete代表级联,关联的Students表删除后自动删除此表
    card_num = models.CharField(verbose_name='身份证号码',max_length=20,unique=True,null=True)
    college = models.CharField('毕业院校',max_length=20,default='家里蹲')
  • 一对多

from django.db import models

# Create your models here.

class Students (models.Model): # 一个类代表一个数据表
    id = models.AutoField(primary_key=True) ##创建一个可以自动生成的主键,这条也可以不写,Django中会自动生成主键
    name = models.CharField(verbose_name='姓名',max_length=20)   ##创建字符类型字段,最大长度为20,设置提示信息'姓名'
                                            ### max_length为CharField的必须参数
    age = models.SmallIntegerField(verbose_name='年龄',null=True) ##创建值可以为null的小整型字段,
    sex = models.SmallIntegerField(default=1)   ##创建缺省值为1的小整型字段
    qq = models.CharField(max_length=20,null=True)
    phone = models.CharField(max_length=20,null=True)
    c_time = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)  ##创建日期时间类型字段,自动创建当前时间
    grade = models.ForeignKey('Grade',on_delete=models.SET_NULL,null=True) #一对多关联,外键关联Grade班级表,models.SET_NULL设置班级表删除后,此字段自动为NULL

    def __str__(self):
        return self.name

class StudentsDetail(models.Model):
    student = models.OneToOneField('Students',on_delete=models.CASCADE) #一对一关联,关联Students类,on_delete代表级联,关联的Students表删除后自动删除此表
    card_num = models.CharField(verbose_name='身份证号码',max_length=20,unique=True,null=True)
    college = models.CharField('毕业院校',max_length=20,default='家里蹲')

class Grade(models.Model):
    name = models.CharField('班级名称',max_length=20,)
    num = models.CharField('班期',max_length=20)
  • 多对多

from django.db import models

# Create your models here.

class Students (models.Model): # 一个类代表一个数据表
    id = models.AutoField(primary_key=True) ##创建一个可以自动生成的主键,这条也可以不写,Django中会自动生成主键
    name = models.CharField(verbose_name='姓名',max_length=20)   ##创建字符类型字段,最大长度为20,设置提示信息'姓名'
                                            ### max_length为CharField的必须参数
    age = models.SmallIntegerField(verbose_name='年龄',null=True) ##创建值可以为null的小整型字段,
    sex = models.SmallIntegerField(default=1)   ##创建缺省值为1的小整型字段
    qq = models.CharField(max_length=20,null=True)
    phone = models.CharField(max_length=20,null=True)
    c_time = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)  ##创建日期时间类型字段,自动创建当前时间
    grade = models.ForeignKey('Grade',on_delete=models.SET_NULL,null=True) #一对多关联,外键关联Grade班级表,models.SET_NULL设置班级表删除后,此字段自动为NULL

    def __str__(self):
        return self.name

class StudentsDetail(models.Model):
    student = models.OneToOneField('Students',on_delete=models.CASCADE) #一对一关联,关联Students类,on_delete代表级联,关联的Students表删除后自动删除此表
    card_num = models.CharField(verbose_name='身份证号码',max_length=20,unique=True,null=True)
    college = models.CharField('毕业院校',max_length=20,default='家里蹲')

class Grade(models.Model):
    name = models.CharField('班级名称',max_length=20,)
    num = models.CharField('班期',max_length=20)

class Course(models.Model):
    name = models.CharField('课程名称',max_length=20)
    #student = models.ManyToManyField('Students') #多对多关联,默认会创建一张中间表,当你需要中间表中添加额外字段,最好指定一张中间表
    student = models.ManyToManyField('Students',through='Enroll') #多对多关联,指定Enroll表为中间表

class Enroll(models.Model):  #多对多的中间表,等于一张报名表
    student = models.ForeignKey('Students',on_delete=models.CASCADE) #外键关联学生表
    course = models.ForeignKey('Course',on_delete=models.CASCADE) #外键关联课程表
    c_time = models.DateTimeField(auto_now_add=True)
    paid = models.FloatField('付款',default=0)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容