Django在两个字段上组合过滤器

时间:2017-02-08 05:25:09

标签: django django-queryset

我对Django比较新。我在过滤数据时遇到问题。我有两个模型,如下所示:

Account(models.Model):
    name = models.CharField(max_length=60)
    hotel = models.ForeignKey(Hotel)
    account_type = models.CharField(choices=ACCOUNT_TYPE, max_length=30)

Transaction(models.Model):        
    account = models.ForeignKey(Account, related_name='transaction')
    transaction_type = models.CharField(choices=TRANSACTION_TYPE, max_length=15)
    description = models.CharField(max_length=100, blank=True, null=True)
    date_created = models.DateTimeField(default=timezone.now)

ACCOUT_TYPE 是:

ACCOUNT_TYPE = (
  (0, 'Asset'),
  (1, 'Liabilities'),
  (2, 'Equity'),
  (3, 'Income'),
  (4, 'Expense')
)

我想过滤指定日期范围内帐户类型为IncomeExpense的所有交易。如何在Django中组合这些过滤器?

我试过这样的话:

income_account = Account.objects.filter(account_type=3)
expense_account = Account.objects.filter(account_type=4)
transactions = Transaction.objects.filter(Q(
  account=income_account,
  date_created__gte=request.data['start_date'],
  date_created__lte=request.data['end_date']
) & Q(
  account=expense_account,
date_created__gte=request.data['start_date'],
date_created__lte=request.data['end_date'])).order_by('date_created')

但它没有用。它引发了以下错误:

  ProgrammingError: more than one row returned by a subquery used as an expression

4 个答案:

答案 0 :(得分:2)

income_accountexpense_account不是单个对象,而是一个对象列表。因此,不是account=income_account而是account=expense_account尝试使用inaccount__in=income_accountaccount__in=expense_account。 你也可以像这样简化查询集:

accounts = Account.objects.filter(Q(account_type=3) | Q(account_type=4))
transactions = Transaction.objects.filter(
    account__in=accounts,
    date_created__gte=request.data['start_date'],
    date_created__lte=request.data['end_date']
).order_by('date_created')

答案 1 :(得分:1)

您可以只使用一个查询集,而不是拥有多个查询集,因为Q允许OR过滤器。你可以这样做:

Transaction.objects.filter(
    (Q(account__account_type=3) | Q(account__account_type=4)) &
    Q(date_created__range=[start_date, end_date])
)

__range可用于获取指定的start_dateend_date之间的日期。

答案 2 :(得分:1)

您始终可以使用MSG_CONFIRM按多个值查找记录。因此,如果您希望in Transaction ACCOUNT_TYPE Income, Expense,您可以像这样使用它。

Transaction.objects.filter(Q(account__in=[3,4]) & Q(date_created__gte=request.data['start_date']) & Q(date_created__lte=request.data['end_date'])).order_by('date_created')

答案 3 :(得分:0)

这对你有用: -

result = Account.objects.filter((account_type__in['Income','Expense'])
                   OR
result = Account.objects.filter((account_type__in['0','4'])

我已将0和4作为字符串,因为您已将account_type视为CharField。