Permalink
Browse files

Merge branch 'master' into test-refactor

Conflicts:
	testproject/alternate_models_app/models/__init__.py
  • Loading branch information...
2 parents d0bd563 + 9050c46 commit 30b0df3e3a6dfc07332250139d267cd3055df7b0 @ojii committed Sep 25, 2012
Showing with 91 additions and 9 deletions.
  1. +2 −1 AUTHORS
  2. +2 −2 hvad/forms.py
  3. +2 −2 hvad/manager.py
  4. +13 −2 hvad/models.py
  5. +18 −0 hvad/test_utils/project/app/models.py
  6. +1 −0 hvad/tests/__init__.py
  7. +47 −0 hvad/tests/proxy.py
  8. +6 −2 hvad/utils.py
View
3 AUTHORS
@@ -4,6 +4,7 @@ Alphabetical list of contributors:
* Angelo Dini
* Daniele Procida
* Ian Clelland
+* Iván Raskovsky
* Jonas Obrist
* Kristian Øllegaard
-* Stefan Foulis
+* Stefan Foulis
View
4 hvad/forms.py
@@ -174,14 +174,14 @@ def save(self, commit=True):
trans.master = self.instance
trans = save_instance(self, trans, self._meta.fields, fail_message,
commit, construct=True)
- return combine(trans)
+ return combine(trans, self.Meta.model)
def _post_clean(self):
if self.instance.pk:
try:
trans = trans = get_translation(self.instance, self.instance.language_code)
trans.master = self.instance
- self.instance = combine(trans)
+ self.instance = combine(trans, self.Meta.model)
except self.instance._meta.translations_model.DoesNotExist:
language_code = self.cleaned_data.get('language_code', get_language())
self.instance = self.instance.translate(language_code)
View
4 hvad/manager.py
@@ -463,7 +463,7 @@ def iterator(self):
if not obj.master:
yield obj
else:
- yield combine(obj)
+ yield combine(obj, self.shared_model)
class TranslationManager(models.Manager):
@@ -566,7 +566,7 @@ def _get_real_instances(self, base_results):
break
# if we found a translation, yield the combined result
if translation:
- yield combine(translation)
+ yield combine(translation, self.model)
else:
# otherwise yield the shared instance only
logger.error("no translation for %s, type %s" % (instance, type(instance)))
View
15 hvad/models.py
@@ -114,8 +114,19 @@ def __new__(cls, name, bases, attrs):
if opts.abstract:
return new_model
+ concrete_model = new_model
+
+ # Check if it's a proxy model
+ if new_model._meta.proxy:
+ if hasattr(new_model._meta, 'concrete_model'):
+ concrete_model = new_model._meta.concrete_model
+ else:
+ # We need this prior to Django 1.4
+ while concrete_model._meta.proxy:
+ concrete_model = concrete_model._meta.proxy_for_model
+
found = False
- for relation in new_model.__dict__.keys():
+ for relation in concrete_model.__dict__.keys():
try:
obj = getattr(new_model, relation)
except AttributeError:
@@ -124,7 +135,7 @@ def __new__(cls, name, bases, attrs):
continue
if not hasattr(obj.related, 'model'):
continue
- if getattr(obj.related.model._meta, 'shared_model', None) is new_model:
+ if getattr(obj.related.model._meta, 'shared_model', None) is concrete_model:
if found:
raise ImproperlyConfigured(
"A TranslatableModel can only define one set of "
View
18 hvad/test_utils/project/app/models.py
@@ -11,6 +11,24 @@ class Normal(TranslatableModel):
def __unicode__(self):
return self.safe_translation_getter('translated_field', self.shared_field)
+
+class NormalProxy(Normal):
+
+ def __unicode__(self):
+ return u'proxied %s' % self.safe_translation_getter('translated_field', self.shared_field)
+
+ class Meta:
+ proxy = True
+
+
+class NormalProxyProxy(NormalProxy):
+
+ def __unicode__(self):
+ return u'proxied^2 %s' % self.safe_translation_getter('translated_field', self.shared_field)
+
+ class Meta:
+ proxy = True
+
class Related(TranslatableModel):
normal = models.ForeignKey(Normal, related_name='rel1', null=True)
View
1 hvad/tests/__init__.py
@@ -19,3 +19,4 @@
from hvad.tests.views import ViewsTest
from hvad.tests.limit_choices_to import LimitChoicesToTests
from hvad.tests.serialization import PicklingTest
+from hvad.tests.proxy import ProxyTests
View
47 hvad/tests/proxy.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+from hvad.test_utils.testcase import NaniTestCase
+from testproject.app.models import Normal, NormalProxy, NormalProxyProxy
+
+
+class ProxyTests(NaniTestCase):
+ def test_proxy(self):
+ self.assertEqual(NormalProxy.objects.count(), 0)
+ self.assertEqual(NormalProxy.objects.language('en').count(), 0)
+
+ # creation
+ Normal.objects.language('en').create(shared_field='SHARED', translated_field='English')
+ self.assertEqual(NormalProxy.objects.language('en').count(), 1)
+
+ NormalProxy.objects.language('en').create(shared_field='SHARED2', translated_field='English2')
+ self.assertEqual(NormalProxy.objects.language('en').count(), 2)
+
+ NormalProxy.objects.language('jp').create(shared_field='JPSHARED3', translated_field='Japanese')
+ self.assertEqual(NormalProxy.objects.language('jp').count(), 1)
+
+ # filter
+ self.assertEqual(NormalProxy.objects.filter(shared_field__startswith='SHARED').count(), 2)
+ self.assertEqual(NormalProxy.objects.language('en').filter(translated_field__startswith='English').count(), 2)
+ self.assertEqual(NormalProxy.objects.language('en').filter(translated_field='English').count(), 1)
+
+ def test_proxy_proxy(self):
+ self.assertEqual(NormalProxyProxy.objects.language('en').count(), 0)
+
+ # creation
+ NormalProxyProxy.objects.language('en').create(shared_field='SHARED', translated_field='English')
+ self.assertEqual(NormalProxyProxy.objects.language('en').count(), 1)
+
+ def test_translation_queryset(self):
+ NormalProxy.objects.language('en').create(shared_field='SHARED2', translated_field='English2')
+ self.assertTrue(isinstance(Normal.objects.language('en').get(), Normal))
+ self.assertFalse(isinstance(Normal.objects.language('en').get(), NormalProxy))
+ self.assertTrue(isinstance(NormalProxy.objects.language('en').get(), NormalProxy))
+ self.assertFalse(isinstance(NormalProxy.objects.language('en').get(), NormalProxyProxy))
+ self.assertTrue(isinstance(NormalProxyProxy.objects.language('en').get(), NormalProxyProxy))
+
+ def test_fallback_queryset(self):
+ NormalProxyProxy.objects.language('en').create(shared_field='SHARED2', translated_field='English2')
+ self.assertTrue(isinstance(Normal.objects.untranslated().use_fallbacks().get(), Normal))
+ self.assertFalse(isinstance(Normal.objects.untranslated().use_fallbacks().get(), NormalProxy))
+ self.assertTrue(isinstance(NormalProxy.objects.untranslated().use_fallbacks().get(), NormalProxy))
+ self.assertFalse(isinstance(NormalProxy.objects.untranslated().use_fallbacks().get(), NormalProxyProxy))
+ self.assertTrue(isinstance(NormalProxyProxy.objects.untranslated().use_fallbacks().get(), NormalProxyProxy))
View
8 hvad/utils.py
@@ -4,13 +4,17 @@
from django.db.models.loading import get_models
from django.db.models.fields.related import RelatedObject
-def combine(trans):
+def combine(trans, klass):
"""
'Combine' the shared and translated instances by setting the translation
on the 'translations_cache' attribute of the shared instance and returning
the shared instance.
+
+ The result is casted to klass (needed for proxy models).
"""
combined = trans.master
+ if klass._meta.proxy:
+ combined.__class__ = klass
opts = combined._meta
setattr(combined, opts.translations_cache, trans)
return combined
@@ -77,4 +81,4 @@ def get_context_data(self, **kwargs):
if (thing.startswith('context_modifier_') or thing in include) and \
not thing in exclude:
context.update(getattr(instance, thing, lambda x:x)(**extra_kwargs))
- return context
+ return context

0 comments on commit 30b0df3

Please sign in to comment.