Skip to content

Commit

Permalink
Split code paths: django 1.8 must use the new API, while older versio…
Browse files Browse the repository at this point in the history
…ns must use the obsolete API.
  • Loading branch information
spectras committed Feb 12, 2015
1 parent 099a7a2 commit 374ebd4
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 25 deletions.
39 changes: 28 additions & 11 deletions hvad/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,15 +315,33 @@ def _add_select_related(self, language_code):

for depth, bit in enumerate(bits):
# Resolve the field
try: # lookup the field on the shared model
field = model._meta.get_field.real(bit)
translated = False
except models.FieldDoesNotExist: # nope, that's from translations
field = model._meta.translations_model._meta.get_field(bit)
translated = True
except AttributeError: # model is not translatable anyway
field = model._meta.get_field(bit)
translated = False
if django.VERSION >= (1, 8):
try: # lookup the field on the shared model
field = model._meta.get_field.real(bit)
translated = False
except models.FieldDoesNotExist: # nope, that's from translations
field = model._meta.translations_model._meta.get_field(bit)
translated = True
except AttributeError: # model is not translatable anyway
field = model._meta.get_field(bit)
translated = False
direct = (
not field.auto_created or
getattr(field, 'db_column', None) or
getattr(field, 'attname', None)
)
else:
# older versions do not retrieve reverse/m2m with get_field, we must use the obsolete api
try:
field, _, direct, _ = model._meta.get_field_by_name.real(bit)
translated = False
except models.FieldDoesNotExist:
field, _, direct, _ = model._meta.translations_model._meta.get_field_by_name(bit)
translated = True
except AttributeError:
field, _, direct, _ = model._meta.get_field_by_name(bit)
translated = False


# Adjust current path bit
if depth == 0 and not translated:
Expand All @@ -337,8 +355,7 @@ def _add_select_related(self, language_code):


# Find out target model
column = getattr(field, 'db_column', None) or getattr(field, 'attname', None)
if not field.auto_created or column: # field is on model
if direct: # field is on model
if field.rel: # field is a foreign key, follow it
if hasattr(field.rel, 'through'):
raise FieldError('Cannot select_related: %s can be multiple objects. '
Expand Down
37 changes: 25 additions & 12 deletions hvad/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,45 @@ def query_terms(model, path):
bit = model._meta.pk.name

try:
if hasattr(model._meta, 'translations_accessor'):
# current model is a shared model
try:
# is field on the shared model?
if django.VERSION >= (1, 8):
try: # is field on the shared model?
field = model._meta.get_field.real(bit)
translated = False
except FieldDoesNotExist:
# nope, get field from translations model
except FieldDoesNotExist: # nope, get field from translations model
field = model._meta.translations_model._meta.get_field(bit)
translated = True
except AttributeError: # current model is a standard model
field = model._meta.get_field(bit)
translated = False
direct = (
not field.auto_created or
getattr(field, 'db_column', None) or
getattr(field, 'attname', None)
)
else:
# current model is a standard model
field = model._meta.get_field(bit)
translated = False
# older versions do not retrieve reverse/m2m with get_field, we must use the obsolete api
try:
field, _, direct, _ = model._meta.get_field_by_name.real(bit)
translated = False
except FieldDoesNotExist:
field, _, direct, _ = model._meta.translations_model._meta.get_field_by_name(bit)
translated = True
except AttributeError:
field, _, direct, _ = model._meta.get_field_by_name(bit)
translated = False
except FieldDoesNotExist:
break


# STEP 2 -- Find out the target of the relation, if it is one
column = getattr(field, 'db_column', None) or getattr(field, 'attname', None)
if not field.auto_created or column: # field is on model
if direct: # field is on model
if field.rel: # field is a foreign key, follow it
target = field.rel.to._meta.concrete_model
else: # field is a regular field
target = None
else: # field is a m2m or reverse fk, follow it
target = field.related_model._meta.concrete_model
target = (field.related_model._meta.concrete_model if django.VERSION >= (1, 8) else
field.model._meta.concrete_model)

yield QueryTerm(
depth=depth,
Expand Down
2 changes: 1 addition & 1 deletion hvad/tests/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def test_options(self):
if django.VERSION >= (1, 8):
relmodel = Normal._meta.get_field(opts.translations_accessor).field.model
else:
relmodel = Normal._meta.get_field(opts.translations_accessor).model
relmodel = Normal._meta.get_field_by_name(opts.translations_accessor)[0].model
self.assertEqual(relmodel, opts.translations_model)


Expand Down
3 changes: 2 additions & 1 deletion hvad/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def get_translation_aware_manager(model):
manager.model = model
return manager

# remove when we drop support for django 1.8
class SmartGetFieldByName(object):
"""
Get field by name from a shared model or raise a smart exception to help the
Expand All @@ -100,7 +101,7 @@ def __call__(self, meta, name):
return self.real(name)
except FieldDoesNotExist as e:
try:
meta.translations_model._meta.get_field(name)
meta.translations_model._meta.get_field_by_name(name)
except FieldDoesNotExist:
raise e
else:
Expand Down

0 comments on commit 374ebd4

Please sign in to comment.