﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
34745	"Arbitrary rhs of lookup gives ""Object has no attribute 'contains_aggregate'"""	Jacob Walls	nobody	"This example overrides `JSONField.get_prep_value` to return some arbitrary SQL. Later, a lookup raises an `AttributeError`.

It also includes two commented out workarounds. I don't know if this usage is supported, but I bisected the behavior change to f42ccdd835e5b3f0914b5e6f87621c648136ea36, which no longer uses `getattr()` to silence `AttributeError` for right-hand sides. I found this upgrading a [https://github.com/archesproject/arches/blob/03b0b1d6211004fd353952a07473ed52652f00ad/arches/app/models/fields/i18n.py#L38 3.2 project] to 4.0.


----

If this usage isn't supported, what is the recommended interface to implement when writing a custom `as_sql()` method?

models.py:
{{{
from django.db import models
from django.db.models.fields.json import JSONField
from django.db.models.sql.where import NothingNode

class ArbitrarySQL:  # class ArbitrarySQL(NothingNode):
    # contains_aggregate = False
    def as_sql(self, compiler, connection):
        return ""'{}'"", ()


class MyJSONField(JSONField):
    def get_prep_value(self, value):
        return ArbitrarySQL()


class MyModel(models.Model):
    config = MyJSONField()
}}}

Gives:
{{{
>>> from repro_app.models import MyModel
>>> MyModel.objects.filter(config={})
Traceback (most recent call last):
  File ""<console>"", line 1, in <module>
  File ""/Users/jwalls/django/django/db/models/query.py"", line 373, in __repr__
    data = list(self[: REPR_OUTPUT_SIZE + 1])
  File ""/Users/jwalls/django/django/db/models/query.py"", line 397, in __iter__
    self._fetch_all()
  File ""/Users/jwalls/django/django/db/models/query.py"", line 1897, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File ""/Users/jwalls/django/django/db/models/query.py"", line 90, in __iter__
    results = compiler.execute_sql(
  File ""/Users/jwalls/django/django/db/models/sql/compiler.py"", line 1549, in execute_sql
    sql, params = self.as_sql()
  File ""/Users/jwalls/django/django/db/models/sql/compiler.py"", line 736, in as_sql
    extra_select, order_by, group_by = self.pre_sql_setup(
  File ""/Users/jwalls/django/django/db/models/sql/compiler.py"", line 86, in pre_sql_setup
    self.where, self.having, self.qualify = self.query.where.split_having_qualify(
  File ""/Users/jwalls/django/django/db/models/sql/where.py"", line 46, in split_having_qualify
    if not self.contains_aggregate and not self.contains_over_clause:
  File ""/Users/jwalls/django/django/utils/functional.py"", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File ""/Users/jwalls/django/django/db/models/sql/where.py"", line 249, in contains_aggregate
    return self._contains_aggregate(self)
  File ""/Users/jwalls/django/django/db/models/sql/where.py"", line 244, in _contains_aggregate
    return any(cls._contains_aggregate(c) for c in obj.children)
  File ""/Users/jwalls/django/django/db/models/sql/where.py"", line 244, in <genexpr>
    return any(cls._contains_aggregate(c) for c in obj.children)
  File ""/Users/jwalls/django/django/db/models/sql/where.py"", line 245, in _contains_aggregate
    return obj.contains_aggregate
  File ""/Users/jwalls/django/django/utils/functional.py"", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File ""/Users/jwalls/django/django/db/models/expressions.py"", line 242, in contains_aggregate
    return any(
  File ""/Users/jwalls/django/django/db/models/expressions.py"", line 243, in <genexpr>
    expr and expr.contains_aggregate for expr in self.get_source_expressions()
AttributeError: 'ArbitrarySQL' object has no attribute 'contains_aggregate'
}}}"	Bug	closed	Database layer (models, ORM)	dev	Normal	invalid			Unreviewed	0	0	0	0	0	0
