Conditional Expressions建立一些逻辑关系

The conditional expression classes

from django.db import models

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,
)

When

对象用于封装条件及其结果,以便在条件表达式中使用。使用When()对象与使用filter()方法类似。可以使用字段查找或Q对象指定条件。使用then关键字提供结果。

>>> from django.db.models import F, Q, When
>>> # String arguments refer to fields; the following two examples are equivalent:
>>> When(account_type=Client.GOLD, then='name')
>>> When(account_type=Client.GOLD, then=F('name'))
>>> # You can use field lookups in the condition
>>> from datetime import date
>>> When(registered_on__gt=date(2014, 1, 1),
... registered_on__lt=date(2015, 1, 1),
... then='account_type')
>>> # Complex conditions can be created using Q objects
>>> When(Q(name__startswith="John") | Q(name__startswith="Paul"),
... then='name')

因为then关键字参数是为When()的结果保留的,所以如果模型有一个名为then的字段,就会有潜在的冲突。这可以通过两种方式解决:

>>> When(then__exact=0, then=1)
>>> When(Q(then=0), then=1)

Case

Case函数类似于python中的if elif else...,按照指定的When()对象的顺序求值,直到求出一个真值为止。返回匹配上的When()的对象。

>>> from datetime import date, timedelta
>>> from django.db.models import Case, CharField, Value, When
>>> Client.objects.create(
... name='Jane Doe',
... account_type=Client.REGULAR,
... registered_on=date.today() - timedelta(days=36))
>>> Client.objects.create(
... name='James Smith',
... account_type=Client.GOLD,
... registered_on=date.today() - timedelta(days=5))
>>> Client.objects.create(
... name='Jack Black',
... account_type=Client.PLATINUM,
... registered_on=date.today() - timedelta(days=10 * 365))
>>> # Get the discount for each Client based on the account type
>>> Client.objects.annotate(
... discount=Case(
... When(account_type=Client.GOLD, then=Value('5%')),
... When(account_type=Client.PLATINUM, then=Value('10%')),
... default=Value('0%'),
... output_field=CharField(),
... ),
... ).values_list('name', 'discount')
<QuerySet [('Jane Doe', '0%'), ('James Smith', '5%'), ('Jack Black', '10%')]>

Case()接受任意数量的When()对象作为单独的参数。其他选项使用关键字参数提供。如果没有条件求值为TRUE,则返回带有默认关键字参数的表达式。如果没有提供默认参数,则不使用任何参数。

如果我们想改变我们之前的查询,以获得折扣的基础上多久的客户一直与我们,我们可以这样做,使用查找:

>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> # Get the discount for each Client based on the registration date
>>> Client.objects.annotate(
... discount=Case(
... When(registered_on__lte=a_year_ago, then=Value('10%')),
... When(registered_on__lte=a_month_ago, then=Value('5%')),
... default=Value('0%'),
... output_field=CharField(),
... )
... ).values_list('name', 'discount')
<QuerySet [('Jane Doe', '5%'), ('James Smith', '0%'), ('Jack Black', '10%')]>

Case()也适用于filter()子句。例如,找到一个多月前注册的黄金客户和一年多前注册的白金客户:

>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> 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),
... ),
... ).values_list('name', 'account_type')
<QuerySet [('Jack Black', 'P')]>

条件表达式可以用于annotations、aggregations、lookups和updates。它们还可以与其他表达式组合和嵌套。这允许您进行强大的条件查询。

Conditional update

>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> # Update the account_type for each Client from the registration date
>>> Client.objects.update(
... account_type=Case(
... When(registered_on__lte=a_year_ago,
... then=Value(Client.PLATINUM)),
... When(registered_on__lte=a_month_ago,
... then=Value(Client.GOLD)),
... default=Value(Client.REGULAR)
... ),
... )
>>> Client.objects.values_list('name', 'account_type')
<QuerySet [('Jane Doe', 'G'), ('James Smith', 'R'), ('Jack Black', 'P')]>

Conditional aggregation

>>> # Create some more Clients first so we can have something to count
>>> Client.objects.create(
... name='Jean Grey',
... account_type=Client.REGULAR,
... registered_on=date.today())
>>> Client.objects.create(
... name='James Bond',
... account_type=Client.PLATINUM,
... registered_on=date.today())
>>> Client.objects.create(
... name='Jane Porter',
... account_type=Client.PLATINUM,
... registered_on=date.today())
>>> # Get counts for each value of account_type
>>> from django.db.models import Count
>>> Client.objects.aggregate(
... regular=Count('pk', filter=Q(account_type=Client.REGULAR)),
... gold=Count('pk', filter=Q(account_type=Client.GOLD)),
... platinum=Count('pk', filter=Q(account_type=Client.PLATINUM)),
... )
{'regular': 2, 'gold': 1, 'platinum': 3}
Transform SQL
>>> # Create some more Clients first so we can have something to count
>>> Client.objects.create(
... name='Jean Grey',
... account_type=Client.REGULAR,
... registered_on=date.today())
>>> Client.objects.create(
... name='James Bond',
... account_type=Client.PLATINUM,
... registered_on=date.today())
>>> Client.objects.create(
... name='Jane Porter',
... account_type=Client.PLATINUM,
... registered_on=date.today())
>>> # Get counts for each value of account_type
>>> from django.db.models import Count
>>> Client.objects.aggregate(
... regular=Count('pk', filter=Q(account_type=Client.REGULAR)),
... gold=Count('pk', filter=Q(account_type=Client.GOLD)),
... platinum=Count('pk', filter=Q(account_type=Client.PLATINUM)),
... )
{'regular': 2, 'gold': 1, 'platinum': 3}

Conditional Expressions的更多相关文章

  1. Simplifying Conditional Expressions(简化条件表达式)

    1.Decompose Conditional(分解条件表达式) 2.Consolidate Conditional Expressions(合并条件表达式) 3.Consolidate Duplic ...

  2. Replace Nested Conditional with Guard Clauses(用卫语句代替嵌套循环)

    函数中的条件逻辑,使人难以看清正常的执行路径. 使用卫语句表现所有特殊情况. double getPayAmount() {double result;if (_isDead) result = de ...

  3. 「操作系统」: Conditional Move Instructions(trap)

    Not all conditional expressions can be compiled using conditional moves. Most significantly, the abs ...

  4. java语言中的匿名类与lambda表达式介绍与总结 (Anonymous Classes and Lambda Expressions)

    2017/6/30 转载写明出处:http://www.cnblogs.com/daren-lin/p/anonymous-classes-and-lambda-expressions-in-java ...

  5. Delphi CompilerVersion Constant / Compiler Conditional Defines

    http://delphi.wikia.com/wiki/CompilerVersion_Constant The CompilerVersion constant identifies the in ...

  6. [LeetCode] Ternary Expression Parser 三元表达式解析器

    Given a string representing arbitrarily nested ternary expressions, calculate the result of the expr ...

  7. Ternary Expression Parser

    Given a string representing arbitrarily nested ternary expressions, calculate the result of the expr ...

  8. SH Script Grammar

    http://linux.about.com/library/cmd/blcmdl1_sh.htm http://pubs.opengroup.org/onlinepubs/9699919799/ut ...

  9. Effective Python2 读书笔记2

    Item 14: Prefer Exceptions to Returning None Functions that returns None to indicate special meaning ...

随机推荐

  1. rtmp连接服务器失败(一个低级错误)

    由于rtmp底层使用的也是socket ,所以如果想正常使用RTMP_Connect(); 则需要在使用该连接之前先初始化套接字: WORD wVersionRequested; WSADATA ws ...

  2. jquery UI 的 datapicker 中文汉化问题

    这个问题自己上网上百度的了很多的方法都没有 具体一点的东西,好在自己没有放弃 从昨天到现在,自己 摸索了很久终于找到了汉化的方法了,希望可以帮助到像我这样刚入web门的小白. 废话不说了直接来干货吧! ...

  3. cf478B-Random Teams 【排列组合】

    http://codeforces.com/problemset/problem/478/B B. Random Teams   n participants of the competition w ...

  4. Python操作SQLServer示例

    本文主要是Python操作SQLServer示例,包括执行查询及更新操作(写入中文). 需要注意的是:读取数据的时候需要decode('utf-8'),写数据的时候需要encode('utf-8'), ...

  5. Python学习笔记_二维数组的查找判断

    在进行数据处理的工作中,有时只是通过一维的list和有一个Key,一个value组成的字典,仍无法满足使用,比如,有三列.或四列,个数由不太多. 举一个现实应用场景:学号.姓名.手机号,可以再加元素 ...

  6. SqlServer——系统函数

    1) CASE CASE有两种使用形式:一种是简单的CASE函数,另一种是搜索型的CASE函数. [1]简单的 CASE 函数 Format: CASE input_expression WHEN w ...

  7. 第二话:javascript中闭包的理解

    闭包是什么? 通过闭包,子函数得以访问父函数的上下文环境,即使父函数已经结束执行. OK,我来简单叙述下,先上图. 都知道函数是javascript整个世界,对象是函数,方法是函数,并且js中实质性的 ...

  8. ConcurrentHashMap的实现原理与使用

    一.适应ConcurrentHashMap的原因 HashMap存在线程不安全的问题,HashTable效率十分低下,因此,ConcurrentHashMap有了合适的登场机会. (1)HashTab ...

  9. code1047 邮票面值设计

    dfs+dp dfs枚举每种情况,每层递归确定第k个数i:i = a[k-1]+1 to a[k-1]*n+1 当枚举完一个序列时,使用check()测试它能达到的max 使用dp.设dp[i]为凑成 ...

  10. Debian/Linux系统安全配置教程

    禁止root SSH登陆 配置SSH Key 配置iptables 当我们安装完Linux系统作为服务器后,总有一系列的安全配置需要进行.特别是当你的服务器Ip是对外网开放的话.全世界有很多不怀好意的 ...