Skip to content

Commit

Permalink
Add experimental support for using select_related and language('all')…
Browse files Browse the repository at this point in the history
… together.
  • Loading branch information
spectras committed Dec 11, 2015
1 parent ace733a commit e7e09e8
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 13 deletions.
7 changes: 4 additions & 3 deletions docs/internal/manager.rst
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,10 @@ TranslationQueryset

Returns a queryset.

.. note:: Using ``language('all')`` and :meth:`select_related` on the
same queryset is not supported and will raise a
:exc:`~exceptions.NotImplementedError`.
.. note:: Support for using ``language('all')`` and :meth:`select_related`
on the same queryset is experimental. Please check the generated
queries and open an issue if you have any problem. Feedback
is appreciated as well.

.. method:: fallbacks(self, *languages)

Expand Down
15 changes: 13 additions & 2 deletions docs/public/queryset.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ language
This filters out all instances that are not translated in the given language,
and makes translatable fields available on the query results.

The special value ``'all'`` disables language filtering. This means that objects
will be returned once per language in which they match the query, with
the appropriate translation loaded.

.. note:: support for :ref:`select_related() <select_related-public>` in combination
with ``language('all')`` is experimental. Please check the generated
queries and open an issue if you have any problem. Feedback
is appreciated as well.

fallbacks
---------

Expand Down Expand Up @@ -96,8 +105,10 @@ select_related
The ``select_related`` method also selects translations of translatable
models when it encounters some.

.. note:: ``select_related`` is not supported in combination with
``language('all')``.
.. note:: support for ``select_related`` in combination with
``language('all')`` is experimental. Please check the generated
queries and open an issue if you have any problem. Feedback
is appreciated as well.


Not implemented public queryset methods
Expand Down
3 changes: 3 additions & 0 deletions docs/public/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ New features:
- Translated model's :meth:`~django.db.models.Model.save` method now accepts translated field
names in ``update_fields``. Also, if only translated fields, or only untranslated fields
are specified in ``update_fields``, the extra query will be skipped.
- Experimental support for using :ref:`language('all') <language-public>` together with
:meth:`~django.db.models.query.QuerySet.select_related` is being introduced. Please
check the generated queries if you use it. Feedback is appreciated.

Compatibility Warnings:

Expand Down
7 changes: 1 addition & 6 deletions hvad/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,7 @@ def _add_language_filter(self):
self._language_filter_tag = True

if self._language_code == 'all':
if self._raw_select_related:
raise NotImplementedError('Using select_related along with '
'language(\'all\') is not supported')

if not self._skip_master_select and getattr(self, '_fields', None) is None:
self.query.add_select_related(('master',))
self._add_select_related(F('language_code'))

elif self._language_fallbacks:
if self._raw_select_related:
Expand Down
2 changes: 0 additions & 2 deletions hvad/tests/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,8 +598,6 @@ def test_notimplemented(self):
self.assertRaises(NotImplementedError, baseqs.bulk_create, [])
# select_related with no field is not implemented
self.assertRaises(NotImplementedError, baseqs.select_related)
# select_related with language('all') is not implemented
self.assertRaises(NotImplementedError, len, baseqs.language('all').select_related('normal'))
if django.VERSION >= (1, 7):
self.assertRaises(NotImplementedError, baseqs.update_or_create)

Expand Down
38 changes: 38 additions & 0 deletions hvad/tests/related.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,26 @@ def test_select_related_with_null_relation(self):
else:
self.fail("Invalid Related object; ID is %s" % r.id)

def test_select_related_language_all(self):
with translation.override('en'):
obj = SimpleRelated.objects.language().create(normal=self.normal2, translated_field="test2_en")
obj.translate('ja')
obj.translated_field = 'test2_ja'
obj.save()

with self.assertNumQueries(1):
objs = (SimpleRelated.objects.language('all')
.filter(pk=obj.pk).order_by('language_code')
.select_related('normal'))
check = [
(NORMAL[2].shared_field, NORMAL[2].translated_field['en']),
(NORMAL[2].shared_field, NORMAL[2].translated_field['ja']),
]
self.assertEqual(list((obj.normal.shared_field, obj.normal.translated_field)
for obj in objs),
check)


class DeepSelectRelatedTests(HvadTestCase, StandardFixture, NormalFixture):
normal_count = 2
standard_count = 1
Expand Down Expand Up @@ -643,3 +663,21 @@ def test_deep_select_related_from_translated_field(self):
self.assertEqual(obj.trans_simple.normal.pk, self.normal_id[1])
self.assertEqual(obj.trans_simple.normal.translated_field,
NORMAL[1].translated_field['en'])

def test_deep_select_related_language_all(self):
with translation.override('en'):
with self.assertNumQueries(1):
obj = (RelatedRelated.objects.language('all')
.select_related('related__normal', 'simple__normal')
.filter(pk=self.relrel1.pk).get())
with self.assertNumQueries(0):
self.assertEqual(obj.related.pk, self.related1.pk)
self.assertEqual(obj.related.normal.pk, self.normal_id[1])
self.assertEqual(obj.related.normal.translated_field,
NORMAL[1].translated_field['en'])
self.assertEqual(obj.simple.pk, self.simplerel.pk)
self.assertEqual(obj.simple.translated_field,
self.simplerel.translated_field)
self.assertEqual(obj.simple.normal.pk, self.normal_id[1])
self.assertEqual(obj.simple.normal.translated_field,
NORMAL[1].translated_field['en'])

0 comments on commit e7e09e8

Please sign in to comment.