Query.alias_map пуст при попытке присоединиться к набору queryset
Я создал пользовательский join, который я пытаюсь присоединить обратно к набору запросов, чтобы выполнить "полное присоединение" к подзапросу.
SQL, который я пытаюсь сгенерировать, выглядит примерно так:
select * from foo
full join (some subquery goes here) as bar on bar.x = foo.x
и я создал метод для создания пользовательского соединения с SQL, необходимым для этого.
def join_to_subquery_with_function(table, function_model, table_field, function_field, queryset, alias, table_function_params):
foreign_object = ForeignObject(to=function_model, on_delete=DO_NOTHING, from_fields=[None], to_fields=[None], rel=None)
foreign_object.opts = Options(table._meta)
foreign_object.opts.model = table
foreign_object.get_joining_columns = lambda: ((table_field, function_field),)
# Create the join and manually apply it to the queryset
join = TableToSubqueryFunctionJoin(
function_model._meta.db_table, table._meta.db_table,
alias, "FULL JOIN", foreign_object, True, table_function_params=table_function_params, queryset=queryset)
# Prepare the alias for join
queryset.query.alias_map[alias] = alias
join.table_alias = alias
queryset.query.external_aliases[alias] = alias
queryset.query.join(join)
return queryset
а класс TableToSubqueryFunctionJoin, который используется для генерации соединения, выглядит так:
class TableToSubqueryFunctionJoin(Join): def init(self, table_name, parent_alias, table_alias, join_type, join_field, nullable, filtered_relation=None, table_function_params=None, queryset=None): super().init(table_name, parent_alias, table_alias, join_type, join_field, nullable, filtered_relation) self.table_function_params = table_function_params self.queryset = queryset
def as_sql(self, compiler, connection):
for (lhs_col, rhs_col) in self.join_cols:
on_clause_sql = '{}.{} = {}.{}'.format(
self.parent_alias,
lhs_col,
self.table_alias,
rhs_col,
)
function_placeholders = '%s::date, %s::date, %s::interval'
resolved_params = []
for param in self.table_function_params:
if isinstance(param, F):
resolved_param = param.resolve_expression(self.queryset.query)
else:
resolved_param = param
resolved_params.append(resolved_param)
table_function_params = []
for param in resolved_params:
if hasattr(param, 'as_sql'):
param_sql, param_params = param.as_sql(compiler, connection)
table_function_params.append(param_params)
else:
table_function_params.append(param)
sql = '{} (select * from {}({})) {} ON ({})'.format(
self.join_type,
compiler.quote_name_unless_alias(self.table_name),
function_placeholders,
self.table_alias,
on_clause_sql
)
return sql, table_function_params
Создать набор запросов и присоединить его к этой функции должно быть достаточно просто, но когда я это делаю, я получаю следующую ошибку:
File "/Users/timmcgee/Documents/main-site/helpers/models/joins.py", line 152, in join_to_subquery_with_function
queryset.query.join(join)
File "/Users/timmcgee/Documents/main-site/venv/lib/python3.6/site-packages/django/db/models/sql/query.py", line 995, in join
if self.alias_map[join.parent_alias].join_type == LOUTER or join.nullable:
KeyError: 'FooBar'
Есть ли дополнительный шаг к добавлению пользовательского псевдонима в набор запросов, который я упустил?