前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >django orm(2)

django orm(2)

作者头像
GH
发布2019-12-16 15:47:28
1.1K0
发布2019-12-16 15:47:28
举报

聚合函数

这里的聚合函数和SQL里的聚合函数对应,在使用前需要先进行模块的导入:

代码语言:javascript
复制
from django.db.models import Max,Min,Sum,Count,Avg

常用的聚合函数有求最大值、最小值、和、计数、平均数,具体使用看下面几个例子:

  1. 筛选出价格最高的书籍 res = models.Book.objects.aggregate(mr = Max('price'))
  2. 求书籍的总价格 res1 = models.Book.objects.aggregate(mr = Sum('price'))
  3. 求书籍的平均价格 res1 = models.Book.objects.aggregate(agv1 = Agv('price'))
  4. 求书籍的最大值、最小值、平均价格、总价格 res1 = models.Book.objects.aggregate(mp = Max('price'), mi = Min('price'),cou = Count('price'),sum1 = Sum('price'),avg1 = Avg('price')) print(res1) #{'mp': Decimal('100.00'), 'mi': Decimal('10.00'), 'cou': 6, 'sum1': Decimal('312.00'), 'avg1': 52.0}

分组查询

分组查询主要应用在比如查询班级中男生、女生的个数等需要先分组再查询的场景,分组操作使用的annotate内部调用的是SQL语句group by,分着查询需要和聚合函数联用。按谁分组,models就是谁,annotaten内部传入筛选的条件。

通过下面几个例子看Django的分组查询:

1.统计每一本书的作者的个数

这里就需要每一本书为一组,然后统计每本书的作者的个数:

代码语言:javascript
复制
res = models.Book.objects.annotate(author_num=Count('author__id')).values('name','author_num')
print(res)
#<QuerySet [{'name': '乖,摸摸头', 'author_num': 2}, {'name': '向着光亮那方', 'author_num': 1}, {'name': '你坏', 'author_num': 1}, {'name': '你的孤独虽败犹荣', 'author_num': 1}, {'name': '三体', 'author_num': 0}, {'name': '乡村教师', 'author_num': 0}]>

2.统计出每个出版社卖的最便宜的书的价格

代码语言:javascript
复制
res = models.Publisher.objects.annotate(min_price=Min('book__price')).values('publisher_name','book__name','book__price')
print(res)
#<QuerySet [{'publisher_name': '湖南文艺出版社', 'book__name': '你坏', 'book__price': Decimal('49.00')}, {'publisher_name': '大象出版社', 'book__name': '乖,摸摸头', 'book__price': Decimal('50.00')}, {'publisher_name': '人民文学出版社', 'book__name': '向着光亮那方', 'book__price': Decimal('51.00')}]>

按照某一个字段进行分组,然后按照另一字段进行查找或排序。

代码语言:javascript
复制
# res = models.Publish.objects.values('想要分组的字段名').annotate(min_price=Min('book__price')).values('name','min_price')


res = models.Book.objects.values('price').annotate(min_price=Min('price')).values('name','min_price')
print(res)
#<QuerySet [{'name': '乖,摸摸头', 'min_price': Decimal('50.00')}, {'name': '向着光亮那方', 'min_price': Decimal('51.00')}, {'name': '你坏', 'min_price': Decimal('49.00')}, {'name': '你的孤独虽败犹荣', 'min_price': Decimal('52.00')}, {'name': '三体', 'min_price': Decimal('100.00')}, {'name': '乡村教师', 'min_price': Decimal('10.00')}]>

3.统计不止一个作者的图书

代码语言:javascript
复制
res = models.Book.objects.annotate(author_num=Count('author__id')).filter(author_num__gt=1).values('name','author_num')
print(res)
#<QuerySet [{'name': '乖,摸摸头', 'author_num': 2}]>

4.查询各个作者出的书的总价格,打印作者名字,总价格

关键字:annotate

借助于聚合函数,Django中models后面点什么就按什么分组

代码语言:javascript
复制
res2 = models.Author.objects.annotate(sum_price=Sum('book__price')).values('auth_name','sum_price')
# print(res2)
#<QuerySet [{'auth_name': '刘同', 'sum_price': Decimal('153.00')}, {'auth_name': '大冰', 'sum_price': Decimal('99.00')}, {'auth_name': '刘慈欣', 'sum_price': None}]>

F与Q查询

使用F和Q查询前需要先导入模块:

代码语言:javascript
复制
from django.db.models import F,Q

F查询

F查询主要解决字段与字段间对比查询的问题,双下划线查询只能实现单个字段的范围查询,引入F查询我们就能够实现不同字段间的对比查询,比如查询出库存数大于卖出数的书籍就是库存和卖出两个字段的对比查询。这里的字段需要在同一张表内方可。

代码语言:javascript
复制
# 1. 查询库存数大于卖出数的书籍
res3 = models.Book.objects.filter(stock__gt=F('sell')).values('name')
print(res3)
#<QuerySet [{'auth_name': '刘同', 'sum_price': Decimal('153.00')}, {'auth_name': '大冰', 'sum_price': Decimal('99.00')}, {'auth_name': '刘慈欣', 'sum_price': None}]><QuerySet []>

# 2. 将所有书的价格上涨100块
book_objs = models.Book.objects.all().update(price=F('price')+100)
print(book_objs.values('price'))

# 3.将所有书的名称后面全部加上 "爆款" 后缀,操作字符串数据需要借助于Concat方法
from django.db.models.functions import Concat
from django.db.models import Value
res4 = models.Book.objects.update(name=Concat(F('name'),Value('新作')))

Q查询

利用Q查询可以实现filter()查询时,查询条件的或非(| 、~)的关系。

说明:如果Q对象和关键字参数一起使用,Q对象必须放在前面。

代码语言:javascript
复制
# 1.查询一下书籍名称是乡村教师 或者 库存数是500的书籍
res4 = models.Book.objects.filter(Q(name='乡村教师新作')|Q(stock=500)).values('name')
print(res4)#或
#<QuerySet [{'name': '三体新作'}, {'name': '乡村教师新作'}]>
#查询出除乡村教师新版和库存数等于500的书籍名称
res5 = models.Book.objects.filter(~Q(name='乡村教师新作')|~Q(stock=500)).values('name')
print(res5)#非
Q对象的高级用法

我们可以根据要求不断给q对象添加筛选条件,然后进行查询,如:

代码语言:javascript
复制
# 1.查询一下书籍名称是乡村教师 或者 库存数是500的书籍
q = Q()#实例化一个Q的对象,之后我们可以按照我们的要求给q添加条件
q.connector = 'or'#默认是and,这里设置的就是各筛选条件之间的关系
q.children.append(('name','乡村教师新作'))#添加筛选条件name='乡村教师'
q.children.append(('stock',500))#添加筛选条件stock=500
res6 = models.Book.objects.filter(q).values('name')#按照我们的要求进行筛选
print(res6)

事务

事务的操作相当于起了一个单独的进程,当操作执行成功之前,数据库中的数据不会有任何的变化,只有当操作结束且执行成功了数据库中的数据才会发生变化,而且这个变化是不可逆的,在操作未执行结束时(没有提交数据时)可以如果我们的操作有错误,可以执行回滚指令,撤销前面的操作(这里的撤销是撤销前面的所有),事务的原子性其实就是我们起一个事务对多张表进行数据操作时,要么这多张表同时被修改成功,要么都不被修改。银行转账就是利用了事务的这一特点。

Django中的事务

还未进行详细讲解

orm字段及参数

常用字段:

字段

描述

AutoField

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

IntegerField

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

CharField

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

DateField

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

DateTimeField

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

字段参数:

参数

描述

null

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

unique

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

db_index

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

default

为该字段设置默认值。

auto_now_add

(日期与时间字段参数)配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

auto_now

(日期与时间字段参数)配置上auto_now=True,每次更新数据记录的时候会更新该字段。

Django字段集合

代码语言:javascript
复制
    AutoField(Field)
        - int自增列,必须填入参数 primary_key=True

    BigAutoField(AutoField)
        - bigint自增列,必须填入参数 primary_key=True

        注:当model中如果没有自增列,则自动会创建一个列名为id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自动创建一个列名为id的且为自增的整数列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定义自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整数 -32768 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整数 0 ~ 32767
    IntegerField(Field)
        - 整数列(有符号的) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整数 0 ~ 2147483647

    BigIntegerField(IntegerField):
        - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807

    BooleanField(Field)
        - 布尔值类型

    NullBooleanField(Field):
        - 可以为空的布尔值

    CharField(Field)
        - 字符类型
        - 必须提供max_length参数, max_length表示字符长度

    TextField(Field)
        - 文本类型

    EmailField(CharField):
        - 字符串类型,Django Admin以及ModelForm中提供验证机制

    IPAddressField(Field)
        - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制

    GenericIPAddressField(Field)
        - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
        - 参数:
            protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both"

    URLField(CharField)
        - 字符串类型,Django Admin以及ModelForm中提供验证 URL

    SlugField(CharField)
        - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)

    CommaSeparatedIntegerField(CharField)
        - 字符串类型,格式必须为逗号分割的数字

    UUIDField(Field)
        - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证

    FilePathField(Field)
        - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
        - 参数:
                path,                      文件夹路径
                match=None,                正则匹配
                recursive=False,           递归下面的文件夹
                allow_files=True,          允许文件
                allow_folders=False,       允许文件夹

    FileField(Field)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      上传文件的保存路径
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage

    ImageField(FileField)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      上传文件的保存路径
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
            width_field=None,   上传图片的高度保存的数据库字段名(字符串)
            height_field=None   上传图片的宽度保存的数据库字段名(字符串)

    DateTimeField(DateField)
        - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 时间格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

    FloatField(Field)
        - 浮点型

    DecimalField(Field)
        - 10进制小数
        - 参数:
            max_digits,小数总长度
            decimal_places,小数位长度

    BinaryField(Field)
        - 二进制类型

 字段合集

Django的字段与数据库字段的对应关系:

代码语言:javascript
复制
对应关系:
    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',

ORM字段与MySQL字段对应关系

自定义char字段

自定义字段可以使用下面的方法,其实我们也只是更改一下字段的数据长度、字段的名字等,Django中的字段已经很丰富了。

代码语言:javascript
复制
# 如何自定义字段类型
class MyCharField(models.Field):
    def __init__(self,max_length,*args,**kwargs):
        self.max_length = max_length
        # 重新调用父类的方法
        super().__init__(max_length=max_length,*args,**kwargs)


    def db_type(self, connection):
        return 'char(%s)'%self.max_length
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 聚合函数
  • 分组查询
  • F与Q查询
    • F查询
      • Q查询
        • Q对象的高级用法
    • 事务
      • Django中的事务
      • orm字段及参数
      • 自定义char字段
      相关产品与服务
      数据库
      云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档