Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django子查询表达式包含混合类型。您必须设置输出字段_Python_Django_Subquery_Django Annotate - Fatal编程技术网

Python Django子查询表达式包含混合类型。您必须设置输出字段

Python Django子查询表达式包含混合类型。您必须设置输出字段,python,django,subquery,django-annotate,Python,Django,Subquery,Django Annotate,我正在尝试为我的models.py应税的信用证添加金额。如果我计算的余额没有应税的大学学分,它的工作。当我把应税的信用卡加入到组合中时,我得到了错误 class Account(models.Model): name = models.CharField(max_length=32) class Debit(models.Model): account = models.ForeignKey(Account, related_name='debits', on_delete=

我正在尝试为我的models.py应税的信用证添加金额。如果我计算的余额没有应税的大学学分,它的工作。当我把应税的信用卡加入到组合中时,我得到了错误

class Account(models.Model):
    name = models.CharField(max_length=32)


class Debit(models.Model):
    account = models.ForeignKey(Account, related_name='debits', on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=12, decimal_places=2)


class Credit(models.Model):
    account = models.ForeignKey(Account, related_name='credits', on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=12, decimal_places=2)
    taxable = models.BooleanField(default=False)

我的测试如下:

lass TestAccount(TestCase):
    # https://mixedquantum.blogspot.com/2017/08/django-tips-3-subquery-expressions.html

    def setUp(self) -> None:
        self.accounts = dict()
        self.accounts['fox'] = Account.objects.create(name='FOX')
        self.accounts['dog'] = Account.objects.create(name='DOG')
        self.accounts['snake'] = Account.objects.create(name='SNAKE')
        """
        # Credits
        +----------------+-----------------+-----------------+
        | account_name   |   credit_amount | taxable         |
        |----------------+-----------------|-----------------+
        | FOX            |           100.0 | False           |
        | SNAKE          |            50.0 | False           |
        | SNAKE          |            20.0 | False           |
        | DOG            |           300.0 | False           |
        | DOG            |           100.0 | True            |
        +----------------+-----------------+-----------------+
        """
        Credit.objects.create(account=self.accounts['fox'], amount=Decimal('100.0'))
        Credit.objects.create(account=self.accounts['snake'], amount=Decimal('50.0'))
        Credit.objects.create(account=self.accounts['snake'], amount=Decimal('20.0'))
        Credit.objects.create(account=self.accounts['dog'], amount=Decimal('300.0'))
        Credit.objects.create(account=self.accounts['dog'], amount=Decimal('100.0'), taxable=True)
        """
        # Debits
        +----------------+----------------+
        | account_name   |   dedit_amount |
        |----------------+----------------|
        | FOX            |           40.0 |
        | SNAKE          |           30.0 |
        | DOG            |           12.0 |
        | DOG            |           23.0 |
        +----------------+----------------+
        """
        Debit.objects.create(account=self.accounts['fox'], amount=Decimal('40.0'))
        Debit.objects.create(account=self.accounts['snake'], amount=Decimal('30.0'))
        Debit.objects.create(account=self.accounts['dog'], amount=Decimal('12.0'))
        Debit.objects.create(account=self.accounts['dog'], amount=Decimal('23.0'))

    def test_sum(self):
        credits = Credit.objects.filter(
            account=OuterRef('pk')).values('account_id').annotate(sum_credits=Sum('amount'))
        taxable_credits = Credit.objects.filter(
            account=OuterRef('pk'), taxable=True).values('account_id').annotate(sum_taxable_credits=Sum('amount'))
        debits = Debit.objects.filter(
            account=OuterRef('pk')).values('account_id').annotate(sum_debits=Sum('amount'))

        balances = Account.objects.annotate(
            credit_sum=Subquery(credits.values('sum_credits')),
            taxable_credit_sum=Subquery(taxable_credits.values('sum_taxable_credits')),
            debit_sum=Subquery(debits.values('sum_debits')),
            balance= F('credit_sum') - F('debit_sum') - F('taxable_credit_sum')
        ).values_list('name', 'balance')  # , 'taxable_credit_sum')

        self.assertEqual(balances[0], ('FOX', Decimal('60.0')))
        self.assertEqual(balances[2], ('SNAKE', Decimal('40.0')))
        self.assertEqual(balances[1], ('DOG', Decimal('365.0')))
        """
        [('FOX', Decimal('60.00')),
         ('SNAKE', Decimal('40.00')),
         ('DOG', Decimal('265.00'))]
        """
当运行测试时,我得到以下错误回溯

Error
Traceback (most recent call last):
  File "/opt/project/alpha_clinic/banking/tests/tests_models.py", line 65, in test_sum
    self.assertEqual(balances[0], ('FOX', Decimal('60.0')))
  File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 308, in __getitem__
    qs._fetch_all()
  File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 1242, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 144, in __iter__
    return compiler.results_iter(tuple_expected=True, chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1085, in results_iter
    results = self.execute_sql(MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1120, in execute_sql
    sql, params = self.as_sql()
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 474, in as_sql
    extra_select, order_by, group_by = self.pre_sql_setup()
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 54, in pre_sql_setup
    self.setup_query()
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 45, in setup_query
    self.select, self.klass_info, self.annotation_col_map = self.get_select()
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 254, in get_select
    sql, params = self.compile(col, select_format=True)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 407, in compile
    return node.output_field.select_format(self, sql, params)
  File "/usr/local/lib/python3.6/site-packages/django/utils/functional.py", line 80, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/expressions.py", line 258, in output_field
    output_field = self._resolve_output_field()
  File "/usr/local/lib/python3.6/site-packages/django/db/models/expressions.py", line 290, in _resolve_output_field
    sources_iter = (source for source in self.get_source_fields() if source is not None)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/expressions.py", line 344, in get_source_fields
    return [e._output_field_or_none for e in self.get_source_expressions()]
  File "/usr/local/lib/python3.6/site-packages/django/db/models/expressions.py", line 344, in <listcomp>
    return [e._output_field_or_none for e in self.get_source_expressions()]
  File "/usr/local/lib/python3.6/site-packages/django/utils/functional.py", line 80, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/expressions.py", line 271, in _output_field_or_none
    return self.output_field
  File "/usr/local/lib/python3.6/site-packages/django/utils/functional.py", line 80, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/expressions.py", line 258, in output_field
    output_field = self._resolve_output_field()
  File "/usr/local/lib/python3.6/site-packages/django/db/models/expressions.py", line 1010, in _resolve_output_field
    return super()._resolve_output_field()
  File "/usr/local/lib/python3.6/site-packages/django/db/models/expressions.py", line 293, in _resolve_output_field
    raise FieldError('Expression contains mixed types. You must set output_field.')
django.core.exceptions.FieldError: Expression contains mixed types. You must set output_field.
错误
回溯(最近一次呼叫最后一次):
文件“/opt/project/alpha_clinic/banking/tests/tests_models.py”,第65行,test_sum中
self.assertEqual(余额[0],('FOX',十进制('60.0'))
文件“/usr/local/lib/python3.6/site packages/django/db/models/query.py”,第308行,在__
Q._fetch_all()
文件“/usr/local/lib/python3.6/site packages/django/db/models/query.py”,第1242行,在“fetch\u all”中
self.\u result\u cache=list(self.\u iterable\u class(self))
文件“/usr/local/lib/python3.6/site packages/django/db/models/query.py”,第144行,在__
返回compiler.results\u iter(tuple\u expected=True,chunked\u fetch=self.chunked\u fetch,chunk\u size=self.chunk\u size)
文件“/usr/local/lib/python3.6/site packages/django/db/models/sql/compiler.py”,结果文件第1085行
results=self.execute\u sql(MULTI,chunked\u fetch=chunked\u fetch,chunk\u size=chunk\u size)
文件“/usr/local/lib/python3.6/site packages/django/db/models/sql/compiler.py”,第1120行,在execute\u sql中
sql,params=self.as_sql()
as_sql中的文件“/usr/local/lib/python3.6/site packages/django/db/models/sql/compiler.py”,第474行
extra\u select、order\u by、group\u by=self.pre\u sql\u setup()
文件“/usr/local/lib/python3.6/site packages/django/db/models/sql/compiler.py”,第54行,在预sql设置中
self.setup\u查询()
文件“/usr/local/lib/python3.6/site packages/django/db/models/sql/compiler.py”,第45行,在setup\u查询中
self.select、self.klass\u info、self.annotation\u col\u map=self.get\u select()
文件“/usr/local/lib/python3.6/site packages/django/db/models/sql/compiler.py”,第254行,在get_select中
sql,params=self.compile(col,select\u format=True)
文件“/usr/local/lib/python3.6/site packages/django/db/models/sql/compiler.py”,第407行,在compile中
返回节点。输出\字段。选择\格式(self、sql、params)
文件“/usr/local/lib/python3.6/site packages/django/utils/functional.py”,第80行,在__
res=instance.\uuuu dict\uuuu[self.name]=self.func(实例)
文件“/usr/local/lib/python3.6/site packages/django/db/models/expressions.py”,第258行,在输出字段中
输出\字段=自身。\解析\输出\字段()
文件“/usr/local/lib/python3.6/site packages/django/db/models/expressions.py”,第290行,在“解析输出”字段中
sources\u iter=(如果source不是None,则在self.get\u source\u fields()中为source指定源)
文件“/usr/local/lib/python3.6/site packages/django/db/models/expressions.py”,第344行,在get\u source\u字段中
在self.get\u source\u expressions()中为e返回[e.\u output\u field\u或\u none]
文件“/usr/local/lib/python3.6/site packages/django/db/models/expressions.py”,第344行,在
在self.get\u source\u expressions()中为e返回[e.\u output\u field\u或\u none]
文件“/usr/local/lib/python3.6/site packages/django/utils/functional.py”,第80行,在__
res=instance.\uuuu dict\uuuu[self.name]=self.func(实例)
文件“/usr/local/lib/python3.6/site packages/django/db/models/expressions.py”,第271行,在输出字段或无字段中
返回self.output_字段
文件“/usr/local/lib/python3.6/site packages/django/utils/functional.py”,第80行,在__
res=instance.\uuuu dict\uuuu[self.name]=self.func(实例)
文件“/usr/local/lib/python3.6/site packages/django/db/models/expressions.py”,第258行,在输出字段中
输出\字段=自身。\解析\输出\字段()
文件“/usr/local/lib/python3.6/site packages/django/db/models/expressions.py”,第1010行,在“解析输出”字段中
返回super()
文件“/usr/local/lib/python3.6/site packages/django/db/models/expressions.py”,第293行,在“解析输出”字段中
raise FIELDVERROR('表达式包含混合类型。必须设置输出\字段')
django.core.exceptions.FieldError:表达式包含混合类型。您必须设置输出字段。
我曾尝试将output_字段添加到子查询,这对我来说毫无意义,但又出现了另一个错误


请提供指导

您可以使用其他聚合功能创建这些注释,而无需使用子查询。此答案中使用的所有函数都是这样导入的

from django.db.models import Sum, Case, When, F, Value
balances = Account.objects.annotate(
    credit_sum=Sum('credits__amount', distinct=F('credits__id')),
    debit_sum=Sum('debits__amount', distinct=F('debits__id')),
    taxable_credit_sum=Sum(Case(
        When(credits__taxable=True, then=F('credits__amount')),
        default=Value(0),
        output_field=models.DecimalField()
    ), distinct=F('credits__id'))
).annotate(
    balance=F('credit_sum') - F('debit_sum') - F('taxable_credit_sum')
).order_by('id').values_list('name', 'balance')
要注释相关记录的总和,可以执行以下操作:

Account.objects.annotate(
    credit_sum=Sum('credits__amount')
).values('name', 'credit_sum')
# <QuerySet [{'name': 'FOX', 'credit_sum': Decimal('100.00')}, {'name': 'DOG', 'credit_sum': Decimal('400.00')}, {'name': 'SNAKE', 'credit_sum': Decimal('70.00')}]>
要有条件地对行进行求和或计数,您可以使用
应纳税\u信用\u sum
注释

from django.db.models import Sum, Case, When, F, Value
balances = Account.objects.annotate(
    credit_sum=Sum('credits__amount', distinct=F('credits__id')),
    debit_sum=Sum('debits__amount', distinct=F('debits__id')),
    taxable_credit_sum=Sum(Case(
        When(credits__taxable=True, then=F('credits__amount')),
        default=Value(0),
        output_field=models.DecimalField()
    ), distinct=F('credits__id'))
).annotate(
    balance=F('credit_sum') - F('debit_sum') - F('taxable_credit_sum')
).order_by('id').values_list('name', 'balance')
现在您应该有了所需的查询

您不需要同时计算抵免额和非应税抵免额 由于您只是从另一个中减去一个,因此您只需为此创建一个注释,将所有不应纳税的信用额相加即可

balances = Account.objects.annotate(
    debit_sum=Sum('debits__amount', distinct=F('debits__id')),
    non_taxable_credit_sum=Sum(Case(
        When(credits__taxable=False, then=F('credits__amount')),
        default=Value(0),
        output_field=models.DecimalField()
    ), distinct=F('credits__id'))
).annotate(
    balance=F('non_taxable_credit_sum') - F('debit_sum')
).order_by('id').values_list('name', 'balance')

您可以使用其他聚合函数创建这些注释,而无需使用
子查询
。此答案中使用的所有函数都是这样导入的

from django.db.models import Sum, Case, When, F, Value
balances = Account.objects.annotate(
    credit_sum=Sum('credits__amount', distinct=F('credits__id')),
    debit_sum=Sum('debits__amount', distinct=F('debits__id')),
    taxable_credit_sum=Sum(Case(
        When(credits__taxable=True, then=F('credits__amount')),
        default=Value(0),
        output_field=models.DecimalField()
    ), distinct=F('credits__id'))
).annotate(
    balance=F('credit_sum') - F('debit_sum') - F('taxable_credit_sum')
).order_by('id').values_list('name', 'balance')
要注释相关记录的总和,可以执行以下操作:

Account.objects.annotate(
    credit_sum=Sum('credits__amount')
).values('name', 'credit_sum')
# <QuerySet [{'name': 'FOX', 'credit_sum': Decimal('100.00')}, {'name': 'DOG', 'credit_sum': Decimal('400.00')}, {'name': 'SNAKE', 'credit_sum': Decimal('70.00')}]>
要有条件地对行进行求和或计数,您可以使用
应纳税\u信用\u sum
注释

from django.db.models import Sum, Case, When, F, Value
balances = Account.objects.annotate(
    credit_sum=Sum('credits__amount', distinct=F('credits__id')),
    debit_sum=Sum('debits__amount', distinct=F('debits__id')),
    taxable_credit_sum=Sum(Case(
        When(credits__taxable=True, then=F('credits__amount')),
        default=Value(0),
        output_field=models.DecimalField()
    ), distinct=F('credits__id'))
).annotate(
    balance=F('credit_sum') - F('debit_sum') - F('taxable_credit_sum')
).order_by('id').values_list('name', 'balance')
现在您应该有了所需的查询

您不需要同时计算抵免额和非应税抵免额 由于您只是从另一个中减去一个,因此您只需为此创建一个注释,将所有不应纳税的信用额相加即可

balances = Account.objects.annotate(
    debit_sum=Sum('debits__amount', distinct=F('debits__id')),
    non_taxable_credit_sum=Sum(Case(
        When(credits__taxable=False, then=F('credits__amount')),
        default=Value(0),
        output_field=models.DecimalField()
    ), distinct=F('credits__id'))
).annotate(
    balance=F('non_taxable_credit_sum') - F('debit_sum')
).order_by('id').values_list('name', 'balance')

您可以尝试以下操作:

credits = Credit.objects.filter(account=OuterRef('pk')).values('account_id').annotate(sum_credits=Sum('amount'))
taxable_credits = Credit.objects.filter(account=OuterRef('pk'), taxable=True).values('account_id').annotate(sum_taxable_credits=Sum('amount'))

debits = Debit.objects.filter(account=OuterRef('pk')).values('account_id').annotate(sum_debits=Sum('amount'))

balances = Account.objects.annotate(
        credit_sum=Case(When(Exists(credits), then=Subquery(credits.values('sum_credits'))), default=Value(0)),
        taxable_credit_sum=Case(When(Exists(taxable_credits), then=Subquery(taxable_credits.values('sum_taxable_credits'))), default=Value(0)),
        debit_sum=Case(When(Exists(debits), then=Subquery(debits.values('sum_debits'))), default=Value(0)),
        balance=F('credit_sum') - F('debit_sum') - F('taxable_credit_sum')
    ).values_list('name', 'balance')  # , 'taxable_credit_sum')

self.assertEqual(balances[0], ('FOX', Decimal('60.0')))
self.assertEqual(balances[2], ('SNAKE', Decimal('40.0')))
self.assertEqual(balances[1], ('DOG', Decimal('265.0')))

您可以尝试以下操作:

credits = Credit.objects.filter(account=OuterRef('pk')).values('account_id').annotate(sum_credits=Sum('amount'))
taxable_credits = Credit.objects.filter(account=OuterRef('pk'), taxable=True).values('account_id').annotate(sum_taxable_credits=Sum('amount'))

debits = Debit.objects.filter(account=OuterRef('pk')).values('account_id').annotate(sum_debits=Sum('amount'))

balances = Account.objects.annotate(
        credit_sum=Case(When(Exists(credits), then=Subquery(credits.values('sum_credits'))), default=Value(0)),
        taxable_credit_sum=Case(When(Exists(taxable_credits), then=Subquery(taxable_credits.values('sum_taxable_credits'))), default=Value(0)),
        debit_sum=Case(When(Exists(debits), then=Subquery(debits.values('sum_debits'))), default=Value(0)),
        balance=F('credit_sum') - F('debit_sum') - F('taxable_credit_sum')
    ).values_list('name', 'balance')  # , 'taxable_credit_sum')

self.assertEqual(balances[0], ('FOX', Decimal('60.0')))
self.assertEqual(balances[2], ('SNAKE', Decimal('40.0')))
self.assertEqual(balances[1], ('DOG', Decimal('265.0')))

如果您可以在一个注释中计算,您是否关心创建两个注释
贷记金额
应纳税贷记金额
?它们会在其他地方使用吗?如果只使用一种模式(
收费
或其他什么)来取代
信用
借记
模式会更容易吗?查询要容易得多你关心cre吗