当前位置

网站首页> 程序设计 > 开源项目 > 程序开发 > 浏览文章

django 1.8 官方文档翻译:2-5-9 条件表达式

作者:小梦 来源: 网络 时间: 2024-04-27 阅读:

条件表达式

New in Django 1.8.

条件表达式允许你在过滤器、注解、聚合和更新操作中使用 if ... elif ... else的逻辑。条件表达式为表中的每一行计算一系列的条件,并且返回匹配到的结果表达式。条件表达式也可以像其它 表达式一样混合和嵌套。

条件表达式类

我们会在后面的例子中使用下面的模型:

from django.db import modelsclass 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

class When(condition=None, then=None, **lookups)[source]

When()对象用于封装条件和它的结果,为了在条件表达式中使用。使用When()对象和使用filter() 方法类似。条件可以使用字段查找 或者 Q 来指定。结果通过使用then关键字来提供。

一些例子:

>>> from django.db.models import When, F, Q>>> # 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()的结果而保留,如果Model有名称为 then的字段,会有潜在的冲突。这可以用以下两种办法解决:

>>> from django.db.models import Value>>> When(then__exact=0, then=1)>>> When(Q(then=0), then=1)

Case

class Case(*cases, **extra)[source]

Case()表达式就像是Python中的if ... elif ... else语句。每个提供的When()中的condition 按照顺序计算,直到得到一个真值。返回匹配When() 对象的result表达式。

一个简单的例子:

>>>>>> from datetime import date, timedelta>>> from django.db.models import CharField, Case, 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')[('Jane Doe', '0%'), ('James Smith', '5%'), ('Jack Black', '10%')]

Case() 接受任意数量的When()对象作为独立的参数。其它选项使用关键字参数提供。如果没有条件为TRUE,表达式会返回提供的default关键字参数。如果没有提供default参数,会使用Value(None)

如果我们想要修改之前的查询,来获取基于Client跟着我们多长时间的折扣,我们应该这样使用查找:

>>> 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')[('Jane Doe', '5%'), ('James Smith', '0%'), ('Jack Black', '10%')]

注意

记住条件按照顺序来计算,所以上面的例子中,即使第二个条件匹配到了 Jane Doe 和 Jack Black,我们也得到了正确的结果。这就像Python中的if ... elif ... else语句一样。

高级查询

条件表达式可以用于注解、聚合、查找和更新。它们也可以和其它表达式混合和嵌套。这可以让你构造更强大的条件查询。

条件更新

假设我们想要为客户端修改account_type来匹配它们的注册日期。我们可以使用条件表达式和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')[('Jane Doe', 'G'), ('James Smith', 'R'), ('Jack Black', 'P')]

条件聚合

如果我们想要弄清楚每个account_type有多少客户端,要怎么做呢?我们可以在聚合函数中嵌套条件表达式来实现:

>>> # 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 IntegerField, Sum>>> Client.objects.aggregate(...     regular=Sum(...         Case(When(account_type=Client.REGULAR, then=1),...  output_field=IntegerField())...     ),...     gold=Sum(...         Case(When(account_type=Client.GOLD, then=1),...  output_field=IntegerField())...     ),...     platinum=Sum(...         Case(When(account_type=Client.PLATINUM, then=1),...  output_field=IntegerField())...     )... ){'regular': 2, 'gold': 1, 'platinum': 3}

译者:Django 文档协作翻译小组,原文:Conditional Expressions。

本文以 CC BY-NC-SA 3.0 协议发布,转载请保留作者署名和文章出处。

Django 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质。交流群:467338606。

网友最爱