首页 > 其他分享 >Django条件查询的Case,When具体使用

Django条件查询的Case,When具体使用

时间:2023-04-07 16:56:54浏览次数:40  
标签:Case __ registered When Value Django Client

这个操作类似于数据库中 if elif else 的逻辑。

1、数据准备:

models.py

class Client(models.Model):
    REGULAR = 'R'
    GOLD = 'G'
    PLATINUM = 'P'
    ACCOUNT_TYPE_CHOICES = [
        (REGULAR, 'Regular'),
        (GOLD, 'Gold'),
        (PLATINUM, 'Platinum'),
    ]
    name = models.CharField(max_length=50)
    registered_on = models.DateField()
    account_type = models.CharField(
        max_length=1,
        choices=ACCOUNT_TYPE_CHOICES,
        default=REGULAR,
    )

迁移数据:

from blog.models import Client

Client.objects.create(name="client_1", registered_on="2020-01-01", account_type="R")
Client.objects.create(name="client_2", registered_on="2021-07-12", account_type="G")
Client.objects.create(name="client_3", registered_on="2022-09-20", account_type="P")
Client.objects.create(name="client_4", registered_on="2022-12-07", account_type="P")

2、When 和 Case 操作新增字段返回

When 和 Case 的函数,这个其实就对应于 SQL 里的 CASE 和 WHEN 函数。目前有这么一个需求,想要筛选出所有季节为 Spring 的数据。

通过判断 registered_on 字段的月份区间来得到一个新的字段:

from django.db.models import Case, Value, When
from blog.models import Client

results = Client.objects.annotate(
    season=
        Case(
            When(registered_on__month__in=[1,2,3], then=Value("Spring")),
            When(registered_on__month__in=[4,5,6], then=Value("Summer")),
            When(registered_on__month__in=[7,8,9], then=Value("Autumn")),
            When(registered_on__month__in=[10,11,12], then=Value("Winter")),
            default=Value("Spring")
        )
    )

Case() 函数内包含了四种 When 的可能性,然后会有一个 default 默认值

在每一个 When() 函数里,前一个是个表达式,可以是这种形式,也可以是 Q() 操作的语句,then= 表示如果满足前面的表达式,那么值的内容将会是后面的值。

在值的定义里,我们这里用到了 Value() 函数,Value() 表示其值是一个字符串。

获取字段值

如果该字段取值是获取某个字段的内容,比如 Client 里的 name 字段,就不需要 Value() 函数来操作,可以直接使用:

When(registered_on__month__in=[1,2,3], then="name")

或者通过 F() 函数来取字段值:

from django.db.models import F
When(registered_on__month__in=[1,2,3], then=F("name"))

在不需要对字段内容进行操作的情况下,上面两条命令的作用是一样的

3、条件搜索

还是前面的需求,我们需要对 Client 的数据进行数据筛选,筛选出 season 为 Spring 的数据,可以在上面的操作中接着 filter():

results = Client.objects.annotate(
    season=
        Case(
            When(registered_on__month__in=[1,2,3], then=Value("Spring")),
            When(registered_on__month__in=[4,5,6], then=Value("Summer")),
            When(registered_on__month__in=[7,8,9], then=Value("Autumn")),
            When(registered_on__month__in=[10,11,12], then=Value("Winter")),
            default=Value("Spring")
        )
    ).filter(season="Spring")

根据条件进行filter

对于 Client 这个 model,我们想实现这样的搜索条件:

要查找一个月前注册的黄金客户和一年前注册的白金客户:

对于这个需求,在之前我们怎么做? 使用 Q() 语法来连接:

from blog.models import Client
from datetime import date, timedelta
from django.db.models import Q

a_month_ago = date.today() - timedelta(days=30)
a_year_ago = date.today() - timedelta(days=365)


condition = (Q(account_type=Client.GOLD) & Q(registered_on__lte=a_month_ago))| \
    (Q(account_type= Client.PLATINUM) & Q(registered_on__lte= a_year_ago)) 

Client.objects.filter(condition)

在这里,如果用到我们的 Case 和 When 的函数也是可以的:

Client.objects.filter(
    registered_on__lte=Case(
        When(account_type=Client.GOLD, then=a_month_ago),
        When(account_type=Client.PLATINUM, then=a_year_ago)
    )
)

 

例子:

假设有一个 TestModel,有一个 field_1 的字段,现在需要将数据按照 B,C,A 的顺序返回结果,那么这里用到 Case 和 When 的处理方法就可以,我们可以通过条件得出一个新的字段 priority,然后 order_by("priority") 即可。

TestModel.objects.annotate(
    priority=Case(
        When(field_1="B", then=1),
        When(field_1="C", then=2),
        When(field_1="A", then=3),
        default=4
    )
).order_by("priority")

4、条件更新

除了前面对数据进行条件的筛选,我们还可以根据条件来对数据进行更新

假设现在需求是对 registered_on 字段的年份进行条件更新: 年份为 2020年的 account_type 字段内容变为 Client.PLATINUM 年份为 2021年的 account_type 字段内容变为 Client.REGULAR

那么相应的代码应该如下:

Client.objects.update(
    account_type=Case(
        When(registered_on__year=2020, then=Value(Client.PLATINUM)),
        When(registered_on__year=2021, then=Value(Client.REGULAR)),
        default=Value(Client.GOLD)
    )
)

需要注意的是,在上面的代码中我们没有针对数据进行 filter() 操作,所以作用的是全表数据,其他非 2020 和 2021 年份的数据也会被更新,如果仅希望操作 2020 和 2021 年的数据,可以加上 filter() 的条件限制:

Client.objects.filter(registered_on__year__in=[2020, 2021]).update(
    account_type=Case(
        When(registered_on__year=2020, then=Value(Client.PLATINUM)),
        When(registered_on__year=2021, then=Value(Client.REGULAR)),
        default=Value(Client.GOLD)
    )
)

 

 

参考自:https://www.cnblogs.com/zonghan/p/17044123.html

标签:Case,__,registered,When,Value,Django,Client
From: https://www.cnblogs.com/shaoyishi/p/17296706.html

相关文章

  • django-content-type简单示例
    fromdjango.contrib.contenttypes.fieldsimportGenericForeignKeyfromdjango.contrib.contenttypes.modelsimportContentTypefromdjango.dbimportmodelsclassComment(models.Model):content_type=models.ForeignKey(ContentType,on_delete=models.CASCA......
  • django记录基础操作日志
    1.新增middleware.py中间件:需要在setting.py注册classLoggingMiddleware:"""日志记录模块:操作用户、操作ip、请求路径、请求方式、请求时间"""def__init__(self,get_response):self.get_response=get_responsedef__call__(self,......
  • kettle从入门到精通 第十课 kettle switch/case、过滤记录、数值范围
    1、java代码里面有ifelse、switch-case等流程控制,kettle也有相应控件。下图便用到switch/case、过滤记录、数值范围控件。 2、 switch/case步骤1)步骤名称:可自定义2)switch字段:需要判断的字段,从前置步骤中选择3)使用字符串包含比较:如果勾选效果和java里面的contains一样,否则......
  • Django笔记十八之save函数的继承操作和指定字段更新等实例方法
    本文首发于微信公众号:Hunter后端原文链接:Django笔记十八之save函数的继承操作和指定字段更新等实例方法这篇笔记主要介绍Django一些实例方法。什么是实例,我们知道通过filter()的一些筛选方法,得到的是QuerySet,而QuerySet取单条数据,通过索引,或者first()或者last()等......
  • Django之models
    常用字段and非常用字段autofieldint自增列,必须填入参数primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。但是这个基本咋没用过,建表也都是使用的默认idIntegerField一个整数类型,范围在-2147483648to2147483647CharField这个最常用,啥都能用他,......
  • Django向数据库添加数据
    一、添家数据到数据库一般通过shell命令打开Python命令行:pythonmanage.pyshell打开交付式命令行>>>frompollsapp.modelsimportChoice,Question>>>fromdjango.utilsimporttimezone>>>q=Question(question......
  • Django笔记十六之aggregate聚合操作
    本文首发于微信公众号:Hunter后端原文链接:Django笔记十六之aggregate聚合操作这一篇笔记介绍一下关于聚合的操作,aggregate。常用的聚合操作比如有平均数,总数,最大值,最小值等等用到的model如下classAuthor(models.Model):name=models.CharField(max_length=100)......
  • Django框架学习日记(导航)
    Django框架学习日记(导航)Django框架学习日记(一)Django框架的快速上手Django框架学习日记(二)Django框架模板相关......
  • django.db.utils.OperationalError: (2026, 'SSL connection error: unknown error nu
    写给自己的问题备忘录django.db.utils.OperationalError:(2026,'SSLconnectionerror:unknownerrornumber')执行:pythonmanage.pymigrate报错,如下。  明明上个项目还好好的,怎么换个就不行了,网上的答案各种各种。决定从自己配置找原因,对比发现,两个环境的 mysqlclie......
  • 重装系统之后的Django项目配置(WSL)
    重装系统之后的Django项目配置(WSL)升级固态硬盘之后,只能重装系统,这样一来就得重新来配置项目的开发环境。Linux环境下Django项目需要用到python解释器,在开发过程中,不同的项目可能会用到不同版本的库,为了防止环境下包的版本冲突,选择在windows的linux子环境中来安装多版本的pytho......