Created
December 4, 2013 17:56
-
-
Save mitchellrj/7792290 to your computer and use it in GitHub Desktop.
Quick and dirty monkey-patch for Django issue #21554. https://code.djangoproject.com/ticket/21554
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def patch_21554(): | |
"""See https://code.djangoproject.com/ticket/21554 """ | |
try: | |
from collections import UserDict | |
except ImportError: | |
from UserDict import UserDict | |
class OneToOneDict(UserDict): | |
def __init__(self, *args, **kwargs): | |
self.reverse = {} | |
UserDict.__init__(self, *args, **kwargs) | |
def __setitem__(self, key, value): | |
self.reverse[value] = key | |
UserDict.__setitem__(self, key, value) | |
def __delitem__(self, key): | |
value = self.data[key] | |
del self.reverse[value] | |
UserDict.__delitem__(self, key) | |
def pop(self, key, *args): | |
value = UserDict.pop(self, key, *args) | |
del self.reverse[value] | |
return value | |
def popitem(self): | |
value = UserDict.popitem(self) | |
del self.reverse[value] | |
return value | |
def update(self, dict=None, **kwargs): | |
if dict is None: | |
pass | |
elif isinstance(dict, OneToOneDict): | |
self.reverse.update(dict.reverse) | |
else: | |
for k, v in dict.items(): | |
self.reverse[v] = k | |
if len(kwargs): | |
self.reverse.update(dict(map(lambda i: (i[1], i[0]), | |
kwargs.items()))) | |
UserDict.update(self, dict, **kwargs) | |
def inverse_get(self, key, default=None): | |
return self.reverse.get(key, default) | |
from django.db.models.sql import compiler | |
def get_default_columns(self, with_aliases=False, col_aliases=None, | |
start_alias=None, opts=None, as_pairs=False, from_parent=None): | |
""" | |
Computes the default columns for selecting every field in the base | |
model. Will sometimes be called to pull in related models (e.g. via | |
select_related), in which case "opts" and "start_alias" will be given | |
to provide a starting point for the traversal. | |
Returns a list of strings, quoted appropriately for use in SQL | |
directly, as well as a set of aliases used in the select statement (if | |
'as_pairs' is True, returns a list of (alias, col_name) pairs instead | |
of strings as the first component and None as the second component). | |
""" | |
result = [] | |
if opts is None: | |
opts = self.query.get_meta() | |
qn = self.quote_name_unless_alias | |
qn2 = self.connection.ops.quote_name | |
aliases = set() | |
only_load = self.deferred_to_columns() | |
if not start_alias: | |
start_alias = self.query.get_initial_alias() | |
# The 'seen_models' is used to optimize checking the needed parent | |
# alias for a given field. This also includes None -> start_alias to | |
# be used by local fields. | |
seen_models = OneToOneDict({None: start_alias}) | |
for field, model in opts.get_concrete_fields_with_model(): | |
if from_parent and model is not None and issubclass(from_parent, | |
model): | |
# Avoid loading data for already loaded parents. | |
continue | |
alias = self.query.join_parent_model(opts, model, start_alias, | |
seen_models) | |
column = field.column | |
target_model = seen_models.inverse_get(alias) | |
if target_model is not None: | |
ancestor_link = target_model._meta.get_ancestor_link(model) | |
if ancestor_link: | |
column = ancestor_link.column | |
table = self.query.alias_map[alias].table_name | |
if table in only_load and column not in only_load[table]: | |
continue | |
if as_pairs: | |
result.append((alias, column)) | |
aliases.add(alias) | |
continue | |
if with_aliases and column in col_aliases: | |
c_alias = 'Col%d' % len(col_aliases) | |
result.append('%s.%s AS %s' % (qn(alias), | |
qn2(column), c_alias)) | |
col_aliases.add(c_alias) | |
aliases.add(c_alias) | |
else: | |
r = '%s.%s' % (qn(alias), qn2(column)) | |
result.append(r) | |
aliases.add(r) | |
if with_aliases: | |
col_aliases.add(column) | |
return result, aliases | |
compiler.SQLCompiler.get_default_columns = get_default_columns | |
patch_21554() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment