mirror of
https://github.com/Hopiu/django-modeltranslation.git
synced 2026-05-10 14:24:44 +00:00
1400 lines
54 KiB
Python
1400 lines
54 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
TODO: Merge autoregister tests from django-modeltranslation-wrapper.
|
|
|
|
NOTE: Perhaps ModeltranslationTestBase in tearDownClass should reload some modules,
|
|
so that tests for other apps are in the same environment.
|
|
|
|
"""
|
|
from __future__ import with_statement # Python 2.5 compatibility
|
|
import os
|
|
import shutil
|
|
|
|
from django import forms
|
|
from django.conf import settings as django_settings
|
|
from django.contrib.admin.sites import AdminSite
|
|
from django.contrib.auth.models import User
|
|
from django.core.exceptions import ValidationError, ImproperlyConfigured
|
|
from django.core.files.base import ContentFile
|
|
from django.db.models import Q, F
|
|
from django.db.models.loading import AppCache
|
|
from django.test import TestCase
|
|
from django.utils.datastructures import SortedDict
|
|
from django.utils.translation import get_language, trans_real
|
|
|
|
from modeltranslation import settings as mt_settings
|
|
from modeltranslation import translator
|
|
from modeltranslation.admin import (TranslationAdmin,
|
|
TranslationStackedInline)
|
|
from modeltranslation.tests.models import (
|
|
AbstractModelB, MultitableModelA, DataModel, FallbackModel, FallbackModel2,
|
|
FileFieldsModel, OtherFieldsModel, TestModel, MultitableBModelA, MultitableModelC,
|
|
MultitableDTestModel, ManagerTestModel, CustomManagerTestModel)
|
|
from modeltranslation.tests.translation import FallbackModel2TranslationOptions
|
|
from modeltranslation.tests.test_settings import TEST_SETTINGS
|
|
|
|
try:
|
|
from django.test.utils import override_settings
|
|
except ImportError:
|
|
from modeltranslation.tests.utils import override_settings
|
|
try:
|
|
from django.utils.translation import override
|
|
except ImportError:
|
|
from modeltranslation.tests.utils import override # NOQA
|
|
|
|
# None of the following tests really depend on the content of the request,
|
|
# so we'll just pass in None.
|
|
request = None
|
|
|
|
|
|
class ModeltranslationTestBase(TestCase):
|
|
urls = 'modeltranslation.tests.urls'
|
|
cache = AppCache()
|
|
synced = False
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
"""
|
|
Prepare database:
|
|
* Call syncdb to create tables for tests.models (since during
|
|
default testrunner's db creation modeltranslation.tests was not in INSTALLED_APPS
|
|
"""
|
|
super(ModeltranslationTestBase, cls).setUpClass()
|
|
if not ModeltranslationTestBase.synced:
|
|
# In odred to perform only one syncdb
|
|
ModeltranslationTestBase.synced = True
|
|
with override_settings(**TEST_SETTINGS):
|
|
import sys
|
|
|
|
# 1. Reload translation in case USE_I18N was False
|
|
from django.utils import translation
|
|
reload(translation)
|
|
|
|
# 2. Reload MT because LANGUAGES likely changed.
|
|
reload(mt_settings)
|
|
reload(translator)
|
|
from modeltranslation import admin
|
|
reload(admin)
|
|
|
|
# 3. Reset test models (because autodiscover have already run, those models
|
|
# have translation fields, but for languages previously defined. We want
|
|
# to be sure that 'de' and 'en' are available)
|
|
del cls.cache.app_models['tests']
|
|
from modeltranslation.tests import models
|
|
reload(models)
|
|
cls.cache.load_app('modeltranslation.tests')
|
|
sys.modules.pop('modeltranslation.tests.translation', None)
|
|
|
|
# 4. Autodiscover
|
|
from modeltranslation import models
|
|
reload(models)
|
|
|
|
# 5. Reload some imported classes
|
|
cls.reload_globals('modeltranslation.tests.models')
|
|
cls.reload_globals('modeltranslation.admin')
|
|
|
|
# 6. Syncdb (``migrate=False`` in case of south)
|
|
from django.db import connections, DEFAULT_DB_ALIAS
|
|
from django.core.management import call_command
|
|
call_command('syncdb', verbosity=0, migrate=False, interactive=False,
|
|
database=connections[DEFAULT_DB_ALIAS].alias, load_initial_data=False)
|
|
|
|
@staticmethod
|
|
def reload_globals(module):
|
|
"""
|
|
Very ugly method for reloading things imported from module.
|
|
|
|
It wouldn't be needed if eg. ``TestModel`` calls would be replaced by ``models.TestModel``.
|
|
"""
|
|
names = []
|
|
for name, item in globals().items():
|
|
if hasattr(item, '__module__') and item.__module__ == module:
|
|
names.append(name)
|
|
_temp = __import__(module, globals(), locals(), names, -1)
|
|
for name in names:
|
|
globals()[name] = getattr(_temp, name)
|
|
|
|
@classmethod
|
|
def clear_cache(cls):
|
|
"""
|
|
It is necessary to clear cache - otherwise model reloading won't
|
|
recreate models, but just use old ones.
|
|
"""
|
|
cls.cache.app_store = SortedDict()
|
|
cls.cache.app_models = SortedDict()
|
|
cls.cache.app_errors = {}
|
|
cls.cache.handled = {}
|
|
cls.cache.loaded = False
|
|
|
|
@classmethod
|
|
def reset_cache(cls):
|
|
"""
|
|
Rebuild whole cache, import all models again
|
|
"""
|
|
cls.clear_cache()
|
|
cls.cache._populate()
|
|
for m in cls.cache.get_apps():
|
|
reload(m)
|
|
|
|
def setUp(self):
|
|
trans_real.activate('de')
|
|
|
|
def tearDown(self):
|
|
trans_real.deactivate()
|
|
|
|
ModeltranslationTestBase = override_settings(**TEST_SETTINGS)(ModeltranslationTestBase)
|
|
|
|
|
|
class ModeltranslationTest(ModeltranslationTestBase):
|
|
"""Basic tests for the modeltranslation application."""
|
|
def test_registration(self):
|
|
langs = tuple(l[0] for l in django_settings.LANGUAGES)
|
|
self.failUnlessEqual(2, len(langs))
|
|
self.failUnless('de' in langs)
|
|
self.failUnless('en' in langs)
|
|
self.failUnless(translator.translator)
|
|
|
|
# Check that all models are registered for translation
|
|
self.failUnlessEqual(len(translator.translator._registry), 12)
|
|
|
|
# Try to unregister a model that is not registered
|
|
self.assertRaises(translator.NotRegistered,
|
|
translator.translator.unregister, User)
|
|
|
|
# Try to get options for a model that is not registered
|
|
self.assertRaises(translator.NotRegistered,
|
|
translator.translator.get_options_for_model, User)
|
|
|
|
def test_translated_models(self):
|
|
# First create an instance of the test model to play with
|
|
inst = TestModel.objects.create(title="Testtitle", text="Testtext")
|
|
field_names = dir(inst)
|
|
self.failUnless('id' in field_names)
|
|
self.failUnless('title' in field_names)
|
|
self.failUnless('title_de' in field_names)
|
|
self.failUnless('title_en' in field_names)
|
|
self.failUnless('text' in field_names)
|
|
self.failUnless('text_de' in field_names)
|
|
self.failUnless('text_en' in field_names)
|
|
self.failUnless('url' in field_names)
|
|
self.failUnless('url_de' in field_names)
|
|
self.failUnless('url_en' in field_names)
|
|
self.failUnless('email' in field_names)
|
|
self.failUnless('email_de' in field_names)
|
|
self.failUnless('email_en' in field_names)
|
|
inst.delete()
|
|
|
|
def test_verbose_name(self):
|
|
inst = TestModel.objects.create(title="Testtitle", text="Testtext")
|
|
self.assertEquals(unicode(
|
|
inst._meta.get_field('title_de').verbose_name), u'title [de]')
|
|
inst.delete()
|
|
|
|
def test_set_translation(self):
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
# First create an instance of the test model to play with
|
|
title1_de = "title de"
|
|
title1_en = "title en"
|
|
title2_de = "title2 de"
|
|
inst1 = TestModel(title_en=title1_en, text="Testtext")
|
|
inst1.title = title1_de
|
|
inst2 = TestModel(title=title2_de, text="Testtext")
|
|
inst1.save()
|
|
inst2.save()
|
|
|
|
self.failUnlessEqual(inst1.title, title1_de)
|
|
self.failUnlessEqual(inst1.title_en, title1_en)
|
|
|
|
self.failUnlessEqual(inst2.title, title2_de)
|
|
self.failUnlessEqual(inst2.title_en, None)
|
|
|
|
del inst1
|
|
del inst2
|
|
|
|
# Check that the translation fields are correctly saved and provide the
|
|
# correct value when retrieving them again.
|
|
n = TestModel.objects.get(title=title1_de)
|
|
self.failUnlessEqual(n.title, title1_de)
|
|
self.failUnlessEqual(n.title_en, title1_en)
|
|
|
|
def test_titleonly(self):
|
|
title1_de = "title de"
|
|
n = TestModel(title=title1_de)
|
|
# The original field "title" passed in the constructor is also
|
|
# populated for the current language field: "title_de".
|
|
self.failUnlessEqual(n.title, title1_de)
|
|
self.failUnlessEqual(n.title_de, title1_de)
|
|
self.failUnlessEqual(n.title_en, None)
|
|
|
|
def test_fallback_values_1(self):
|
|
"""
|
|
If ``fallback_values`` is set to string, all untranslated fields would
|
|
return this string.
|
|
"""
|
|
title1_de = "title de"
|
|
n = FallbackModel()
|
|
n.title = title1_de
|
|
n.save()
|
|
del n
|
|
n = FallbackModel.objects.get(title=title1_de)
|
|
self.failUnlessEqual(n.title, title1_de)
|
|
trans_real.activate("en")
|
|
self.failUnlessEqual(n.title, "")
|
|
|
|
def test_fallback_values_2(self):
|
|
"""
|
|
If ``fallback_values`` is set to ``dict``, all untranslated fields in
|
|
``dict`` would return this mapped value. Fields not in ``dict`` would
|
|
return default translation.
|
|
"""
|
|
title1_de = "title de"
|
|
text1_de = "text in german"
|
|
n = FallbackModel2()
|
|
n.title = title1_de
|
|
n.text = text1_de
|
|
n.save()
|
|
del n
|
|
n = FallbackModel2.objects.get(title=title1_de)
|
|
trans_real.activate("en")
|
|
self.failUnlessEqual(n.title, '') # Falling back to default field value
|
|
self.failUnlessEqual(
|
|
n.text,
|
|
FallbackModel2TranslationOptions.fallback_values['text'])
|
|
|
|
def _compare_instances(self, x, y, field):
|
|
self.assertEqual(getattr(x, field), getattr(y, field),
|
|
"Constructor diff on field %s." % field)
|
|
|
|
def _test_constructor(self, keywords):
|
|
n = TestModel(**keywords)
|
|
m = TestModel.objects.create(**keywords)
|
|
fields = translator.translator.get_options_for_model(TestModel).localized_fieldnames
|
|
for base_field, trans_fields in fields.iteritems():
|
|
self._compare_instances(n, m, base_field)
|
|
for lang_field in trans_fields:
|
|
self._compare_instances(n, m, lang_field)
|
|
|
|
def test_constructor(self):
|
|
"""
|
|
Ensure that model constructor behaves exactly the same as objects.create
|
|
"""
|
|
# test different arguments compositions
|
|
keywords = dict(
|
|
# original only
|
|
title='title',
|
|
# both languages + original
|
|
email='q@q.qq', email_de='d@d.dd', email_en='e@e.ee',
|
|
# both languages without original
|
|
text_en='text en', text_de='text de',
|
|
)
|
|
self._test_constructor(keywords)
|
|
|
|
keywords = dict(
|
|
# only current language
|
|
title_de='title',
|
|
# only not current language
|
|
url_en='http://www.google.com',
|
|
# original + current
|
|
text='text def', text_de='text de',
|
|
# original + not current
|
|
email='q@q.qq', email_en='e@e.ee',
|
|
)
|
|
self._test_constructor(keywords)
|
|
|
|
|
|
class FallbackTests(ModeltranslationTestBase):
|
|
test_fallback = {
|
|
'default': ('de',),
|
|
'de': ('en',)
|
|
}
|
|
|
|
def tearDown(self):
|
|
trans_real.deactivate()
|
|
reload(mt_settings) # Return to previous state
|
|
|
|
def test_settings(self):
|
|
# Initial
|
|
self.assertEqual(mt_settings.FALLBACK_LANGUAGES, {'default': ()})
|
|
# Tuple/list
|
|
with override_settings(MODELTRANSLATION_FALLBACK_LANGUAGES=('de',)):
|
|
reload(mt_settings)
|
|
self.assertEqual(mt_settings.FALLBACK_LANGUAGES, {'default': ('de',)})
|
|
# Whole dict
|
|
with override_settings(MODELTRANSLATION_FALLBACK_LANGUAGES=self.test_fallback):
|
|
reload(mt_settings)
|
|
self.assertEqual(mt_settings.FALLBACK_LANGUAGES, self.test_fallback)
|
|
# Improper language raises error
|
|
config = {'default': (), 'fr': ('en',)}
|
|
with override_settings(MODELTRANSLATION_FALLBACK_LANGUAGES=config):
|
|
self.assertRaises(ImproperlyConfigured, lambda: reload(mt_settings))
|
|
|
|
def test_resolution_order(self):
|
|
from modeltranslation.utils import resolution_order
|
|
with override_settings(MODELTRANSLATION_FALLBACK_LANGUAGES=self.test_fallback):
|
|
reload(mt_settings)
|
|
self.assertEqual(('en', 'de'), resolution_order('en'))
|
|
self.assertEqual(('de', 'en'), resolution_order('de'))
|
|
# Overriding
|
|
config = {'default': ()}
|
|
self.assertEqual(('en',), resolution_order('en', config))
|
|
self.assertEqual(('de', 'en'), resolution_order('de', config))
|
|
# Uniqueness
|
|
config = {'de': ('en', 'de')}
|
|
self.assertEqual(('en', 'de'), resolution_order('en', config))
|
|
self.assertEqual(('de', 'en'), resolution_order('de', config))
|
|
|
|
# Default fallbacks are always used at the end
|
|
# That's it: fallbacks specified for a language don't replace defaults,
|
|
# but just are prepended
|
|
config = {'default': ('en', 'de'), 'de': ()}
|
|
self.assertEqual(('en', 'de'), resolution_order('en', config))
|
|
self.assertEqual(('de', 'en'), resolution_order('de', config))
|
|
# What one may have expected
|
|
self.assertNotEqual(('de',), resolution_order('de', config))
|
|
|
|
# To completely override settings, one should override all keys
|
|
config = {'default': (), 'de': ()}
|
|
self.assertEqual(('en',), resolution_order('en', config))
|
|
self.assertEqual(('de',), resolution_order('de', config))
|
|
|
|
def test_fallback_languages(self):
|
|
with override_settings(MODELTRANSLATION_FALLBACK_LANGUAGES=self.test_fallback):
|
|
reload(mt_settings)
|
|
title_de = 'title de'
|
|
title_en = 'title en'
|
|
n = TestModel(title=title_de)
|
|
self.assertEqual(n.title_de, title_de)
|
|
self.assertEqual(n.title_en, None)
|
|
self.assertEqual(n.title, title_de)
|
|
trans_real.activate('en')
|
|
self.assertEqual(n.title, title_de) # since default fallback is de
|
|
|
|
n = TestModel(title=title_en)
|
|
self.assertEqual(n.title_de, None)
|
|
self.assertEqual(n.title_en, title_en)
|
|
self.assertEqual(n.title, title_en)
|
|
trans_real.activate('de')
|
|
self.assertEqual(n.title, title_en) # since fallback for de is en
|
|
|
|
n.title_en = None
|
|
self.assertEqual(n.title, '') # if all fallbacks fail, return field.get_default()
|
|
|
|
|
|
class FileFieldsTest(ModeltranslationTestBase):
|
|
test_media_root = os.path.join(
|
|
os.path.dirname(os.path.realpath(__file__)), 'media')
|
|
|
|
def tearDown(self):
|
|
# File tests create a temporary media directory structure. While the
|
|
# files are automatically deleted by the storage, the directories will
|
|
# stay. So we clean up a bit...
|
|
if os.path.isdir(self.test_media_root):
|
|
shutil.rmtree(self.test_media_root)
|
|
trans_real.deactivate()
|
|
|
|
def test_translated_models(self):
|
|
# First create an instance of the test model to play with
|
|
inst = FileFieldsModel.objects.create(
|
|
title="Testtitle", file=None)
|
|
field_names = dir(inst)
|
|
self.failUnless('id' in field_names)
|
|
self.failUnless('title' in field_names)
|
|
self.failUnless('title_de' in field_names)
|
|
self.failUnless('title_en' in field_names)
|
|
self.failUnless('file' in field_names)
|
|
self.failUnless('file_de' in field_names)
|
|
self.failUnless('file_en' in field_names)
|
|
inst.delete()
|
|
|
|
def test_translated_models_instance(self):
|
|
#f_en = ContentFile("Just a really good file")
|
|
inst = FileFieldsModel(title="Testtitle", file=None)
|
|
|
|
trans_real.activate("en")
|
|
inst.title = 'title_en'
|
|
|
|
inst.file = 'a_en'
|
|
inst.file.save('b_en', ContentFile('file in english'))
|
|
|
|
inst.image = 'i_en.jpg'
|
|
inst.image.save('i_en.jpg', ContentFile('image in english'))
|
|
|
|
trans_real.activate("de")
|
|
inst.title = 'title_de'
|
|
|
|
inst.file = 'a_de'
|
|
inst.file.save('b_de', ContentFile('file in german'))
|
|
|
|
inst.image = 'i_de.jpg'
|
|
inst.image.save('i_de.jpg', ContentFile('image in germany'))
|
|
|
|
inst.save()
|
|
|
|
trans_real.activate("en")
|
|
|
|
self.failUnlessEqual(inst.title, 'title_en')
|
|
self.failUnless(inst.file.name.count('b_en') > 0)
|
|
self.failUnless(inst.image.name.count('i_en') > 0)
|
|
|
|
trans_real.activate("de")
|
|
self.failUnlessEqual(inst.title, 'title_de')
|
|
self.failUnless(inst.file.name.count('b_de') > 0)
|
|
self.failUnless(inst.image.name.count('i_de') > 0)
|
|
|
|
inst.file_en.delete()
|
|
inst.image_en.delete()
|
|
inst.file_de.delete()
|
|
inst.image_de.delete()
|
|
|
|
inst.delete()
|
|
|
|
|
|
class OtherFieldsTest(ModeltranslationTestBase):
|
|
def test_translated_models(self):
|
|
inst = OtherFieldsModel.objects.create()
|
|
field_names = dir(inst)
|
|
self.failUnless('id' in field_names)
|
|
self.failUnless('int' in field_names)
|
|
self.failUnless('int_de' in field_names)
|
|
self.failUnless('int_en' in field_names)
|
|
inst.delete()
|
|
|
|
def test_translated_models_instance(self):
|
|
inst = OtherFieldsModel()
|
|
inst.int = 7
|
|
self.assertEqual('de', get_language())
|
|
self.assertEqual(7, inst.int)
|
|
self.assertEqual(7, inst.int_de)
|
|
self.assertEqual(42, inst.int_en) # default value is honored
|
|
|
|
inst.int += 2
|
|
inst.save()
|
|
self.assertEqual(9, inst.int)
|
|
self.assertEqual(9, inst.int_de)
|
|
self.assertEqual(42, inst.int_en)
|
|
|
|
trans_real.activate('en')
|
|
inst.int -= 1
|
|
self.assertEqual(41, inst.int)
|
|
self.assertEqual(9, inst.int_de)
|
|
self.assertEqual(41, inst.int_en)
|
|
|
|
# this field has validator - let's try to make it below 0!
|
|
inst.int -= 50
|
|
self.assertRaises(ValidationError, inst.full_clean)
|
|
|
|
|
|
class ModeltranslationTestRule1(ModeltranslationTestBase):
|
|
"""
|
|
Rule 1: Reading the value from the original field returns the value in
|
|
translated to the current language.
|
|
"""
|
|
def _test_field(self, field_name, value_de, value_en, deactivate=True):
|
|
field_name_de = '%s_de' % field_name
|
|
field_name_en = '%s_en' % field_name
|
|
params = {'title_de': 'title de', 'title_en': 'title en',
|
|
field_name_de: value_de, field_name_en: value_en}
|
|
|
|
n = TestModel.objects.create(**params)
|
|
# Language is set to 'de' at this point
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
self.failUnlessEqual(getattr(n, field_name), value_de)
|
|
self.failUnlessEqual(getattr(n, field_name_de), value_de)
|
|
self.failUnlessEqual(getattr(n, field_name_en), value_en)
|
|
# Now switch to "en"
|
|
trans_real.activate("en")
|
|
self.failUnlessEqual(get_language(), "en")
|
|
# Should now be return the english one (just by switching the language)
|
|
self.failUnlessEqual(getattr(n, field_name), value_en)
|
|
|
|
n = TestModel.objects.create(**params)
|
|
n.save()
|
|
# Language is set to "en" at this point
|
|
self.failUnlessEqual(getattr(n, field_name), value_en)
|
|
self.failUnlessEqual(getattr(n, field_name_de), value_de)
|
|
self.failUnlessEqual(getattr(n, field_name_en), value_en)
|
|
trans_real.activate('de')
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
self.failUnlessEqual(getattr(n, field_name), value_de)
|
|
|
|
if deactivate:
|
|
trans_real.deactivate()
|
|
|
|
def test_rule1(self):
|
|
"""
|
|
Basic CharField/TextField test.
|
|
Could as well call _test_field, just kept for reference.
|
|
"""
|
|
title1_de = "title de"
|
|
title1_en = "title en"
|
|
text_de = "Dies ist ein deutscher Satz"
|
|
text_en = "This is an english sentence"
|
|
|
|
n = TestModel.objects.create(title_de=title1_de, title_en=title1_en,
|
|
text_de=text_de, text_en=text_en)
|
|
n.save()
|
|
|
|
# Language is set to 'de' at this point
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
self.failUnlessEqual(n.title, title1_de)
|
|
self.failUnlessEqual(n.title_de, title1_de)
|
|
self.failUnlessEqual(n.title_en, title1_en)
|
|
self.failUnlessEqual(n.text, text_de)
|
|
self.failUnlessEqual(n.text_de, text_de)
|
|
self.failUnlessEqual(n.text_en, text_en)
|
|
# Now switch to "en"
|
|
trans_real.activate("en")
|
|
self.failUnlessEqual(get_language(), "en")
|
|
# Title should now be return the english one (just by switching the
|
|
# language)
|
|
self.failUnlessEqual(n.title, title1_en)
|
|
self.failUnlessEqual(n.text, text_en)
|
|
|
|
n = TestModel.objects.create(title_de=title1_de, title_en=title1_en,
|
|
text_de=text_de, text_en=text_en)
|
|
n.save()
|
|
# Language is set to "en" at this point
|
|
self.failUnlessEqual(n.title, title1_en)
|
|
self.failUnlessEqual(n.title_de, title1_de)
|
|
self.failUnlessEqual(n.title_en, title1_en)
|
|
self.failUnlessEqual(n.text, text_en)
|
|
self.failUnlessEqual(n.text_de, text_de)
|
|
self.failUnlessEqual(n.text_en, text_en)
|
|
trans_real.activate('de')
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
self.failUnlessEqual(n.title, title1_de)
|
|
self.failUnlessEqual(n.text, text_de)
|
|
|
|
trans_real.deactivate()
|
|
|
|
def test_rule1_url_field(self):
|
|
self._test_field(field_name='url',
|
|
value_de='http://www.google.de',
|
|
value_en='http://www.google.com')
|
|
|
|
def test_rule1_email_field(self):
|
|
self._test_field(field_name='email',
|
|
value_de='django-modeltranslation@googlecode.de',
|
|
value_en='django-modeltranslation@googlecode.com')
|
|
|
|
|
|
class ModeltranslationTestRule2(ModeltranslationTestBase):
|
|
"""
|
|
Rule 2: Assigning a value to the original field also updates the value
|
|
in the associated translation field of the default language
|
|
"""
|
|
def _test_field(self, field_name, value1_de, value1_en, value2, value3,
|
|
deactivate=True):
|
|
field_name_de = '%s_de' % field_name
|
|
field_name_en = '%s_en' % field_name
|
|
params = {'title_de': 'title de', 'title_en': 'title en',
|
|
field_name_de: value1_de, field_name_en: value1_en}
|
|
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
n = TestModel.objects.create(**params)
|
|
self.failUnlessEqual(getattr(n, field_name), value1_de)
|
|
self.failUnlessEqual(getattr(n, field_name_de), value1_de)
|
|
self.failUnlessEqual(getattr(n, field_name_en), value1_en)
|
|
|
|
setattr(n, field_name, value2)
|
|
n.save()
|
|
self.failUnlessEqual(getattr(n, field_name), value2)
|
|
self.failUnlessEqual(getattr(n, field_name), getattr(n, field_name_de))
|
|
|
|
trans_real.activate("en")
|
|
self.failUnlessEqual(get_language(), "en")
|
|
|
|
setattr(n, field_name, value3)
|
|
setattr(n, field_name_de, value1_de)
|
|
n.save()
|
|
self.failUnlessEqual(getattr(n, field_name), value3)
|
|
self.failUnlessEqual(getattr(n, field_name), getattr(n, field_name_en))
|
|
self.failUnlessEqual(value1_de, getattr(n, field_name_de))
|
|
|
|
if deactivate:
|
|
trans_real.deactivate()
|
|
|
|
def test_rule2(self):
|
|
"""
|
|
Basic CharField/TextField test.
|
|
Could as well call _test_field, just kept for reference.
|
|
"""
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
title1_de = "title de"
|
|
title1_en = "title en"
|
|
n = TestModel.objects.create(title_de=title1_de, title_en=title1_en)
|
|
self.failUnlessEqual(n.title, title1_de)
|
|
self.failUnlessEqual(n.title_de, title1_de)
|
|
self.failUnlessEqual(n.title_en, title1_en)
|
|
|
|
title2 = "Neuer Titel"
|
|
n.title = title2
|
|
n.save()
|
|
self.failUnlessEqual(n.title, title2)
|
|
self.failUnlessEqual(n.title, n.title_de)
|
|
|
|
trans_real.activate("en")
|
|
self.failUnlessEqual(get_language(), "en")
|
|
title3 = "new title"
|
|
|
|
n.title = title3
|
|
n.title_de = title1_de
|
|
n.save()
|
|
self.failUnlessEqual(n.title, title3)
|
|
self.failUnlessEqual(n.title, n.title_en)
|
|
self.failUnlessEqual(title1_de, n.title_de)
|
|
|
|
trans_real.deactivate()
|
|
|
|
def test_rule2_url_field(self):
|
|
self._test_field(field_name='url',
|
|
value1_de='http://www.google.de',
|
|
value1_en='http://www.google.com',
|
|
value2='http://www.google.at',
|
|
value3='http://www.google.co.uk')
|
|
|
|
def test_rule2_email_field(self):
|
|
self._test_field(field_name='email',
|
|
value1_de='django-modeltranslation@googlecode.de',
|
|
value1_en='django-modeltranslation@googlecode.com',
|
|
value2='django-modeltranslation@googlecode.at',
|
|
value3='django-modeltranslation@googlecode.co.uk')
|
|
|
|
|
|
class ModeltranslationTestRule3(ModeltranslationTestBase):
|
|
"""
|
|
Rule 3: Assigning a value to a translation field of the default
|
|
language also updates the original field - note that the value of the
|
|
original field will not be updated until the model instance is saved.
|
|
"""
|
|
def _test_field(self, field_name, value1_de, value1_en, value2, value3,
|
|
deactivate=True):
|
|
field_name_de = '%s_de' % field_name
|
|
field_name_en = '%s_en' % field_name
|
|
params = {'title_de': 'title de', 'title_en': 'title en',
|
|
field_name_de: value1_de, field_name_en: value1_en}
|
|
|
|
n = TestModel.objects.create(**params)
|
|
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
self.failUnlessEqual(getattr(n, field_name), value1_de)
|
|
self.failUnlessEqual(getattr(n, field_name_de), value1_de)
|
|
self.failUnlessEqual(getattr(n, field_name_en), value1_en)
|
|
|
|
setattr(n, field_name, value2)
|
|
n.save()
|
|
self.failUnlessEqual(getattr(n, field_name), getattr(n, field_name_de))
|
|
|
|
# Now switch to "en"
|
|
trans_real.activate("en")
|
|
self.failUnlessEqual(get_language(), "en")
|
|
setattr(n, field_name_en, value3)
|
|
# the n.title field is not updated before the instance is saved
|
|
n.save()
|
|
self.failUnlessEqual(getattr(n, field_name), getattr(n, field_name_en))
|
|
|
|
if deactivate:
|
|
trans_real.deactivate()
|
|
|
|
def test_rule3(self):
|
|
"""
|
|
Basic CharField/TextField test.
|
|
Could as well call _test_field, just kept for reference.
|
|
"""
|
|
title1_de = "title de"
|
|
title1_en = "title en"
|
|
n = TestModel.objects.create(title_de=title1_de, title_en=title1_en)
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
self.failUnlessEqual(mt_settings.DEFAULT_LANGUAGE, 'de')
|
|
self.failUnlessEqual(n.title, title1_de)
|
|
self.failUnlessEqual(n.title_de, title1_de)
|
|
self.failUnlessEqual(n.title_en, title1_en)
|
|
|
|
n.title_de = "Neuer Titel"
|
|
n.save()
|
|
# We expect that the original field holds the same value as the german
|
|
# one (german is the default language).
|
|
self.failUnlessEqual(n.title, n.title_de)
|
|
|
|
# Fetch the updated object and verify all fields
|
|
updated_obj = TestModel.objects.get(id=n.id)
|
|
self.failUnlessEqual(updated_obj.title, 'Neuer Titel')
|
|
self.failUnlessEqual(updated_obj.title_de, 'Neuer Titel')
|
|
self.failUnlessEqual(updated_obj.title_en, 'title en')
|
|
|
|
# Now switch to "en"
|
|
trans_real.activate("en")
|
|
self.failUnlessEqual(get_language(), "en")
|
|
n.title_en = "New title"
|
|
# the n.title field is not updated before the instance is saved
|
|
n.save()
|
|
|
|
# We expect that the original field has *not* been changed as german
|
|
# is the default language and we only changed the value of the english
|
|
# field.
|
|
# FIXME: Demonstrates a wrong behaviour of save when the current
|
|
# language is different than the default language. In this case the
|
|
# original field is set to value of the current language's field.
|
|
# See issue 33 for details.
|
|
|
|
# TODO: Reactivate, temporarily deactivated for a full run of travis ci
|
|
#self.failUnlessEqual(n.title, n.title_de)
|
|
|
|
# Fetch the updated object and verify all fields
|
|
#updated_obj = TestModel.objects.get(id=n.id)
|
|
#self.failUnlessEqual(updated_obj.title, 'Neuer Titel')
|
|
#self.failUnlessEqual(updated_obj.title_de, 'Neuer Titel')
|
|
#self.failUnlessEqual(updated_obj.title_en, 'New title')
|
|
|
|
trans_real.deactivate()
|
|
|
|
def test_rule3_url_field(self):
|
|
self._test_field(field_name='url',
|
|
value1_de='http://www.google.de',
|
|
value1_en='http://www.google.com',
|
|
value2='http://www.google.at',
|
|
value3='http://www.google.co.uk')
|
|
|
|
def test_rule3_email_field(self):
|
|
self._test_field(field_name='email',
|
|
value1_de='django-modeltranslation@googlecode.de',
|
|
value1_en='django-modeltranslation@googlecode.com',
|
|
value2='django-modeltranslation@googlecode.at',
|
|
value3='django-modeltranslation@googlecode.co.uk')
|
|
|
|
|
|
class ModeltranslationTestRule4(ModeltranslationTestBase):
|
|
"""
|
|
Rule 4: If both fields - the original and the translation field of the
|
|
default language - are updated at the same time, the translation field
|
|
wins.
|
|
"""
|
|
def _test_field(self, field_name, value1_de, value1_en, value2_de,
|
|
value2_en, value3, deactivate=True):
|
|
field_name_de = '%s_de' % field_name
|
|
field_name_en = '%s_en' % field_name
|
|
params = {'title_de': 'title de', 'title_en': 'title en',
|
|
field_name_de: value1_de, field_name_en: value1_en}
|
|
|
|
n = TestModel.objects.create(**params)
|
|
|
|
self.failUnlessEqual(getattr(n, field_name), value1_de)
|
|
self.failUnlessEqual(getattr(n, field_name_de), value1_de)
|
|
self.failUnlessEqual(getattr(n, field_name_en), value1_en)
|
|
|
|
setattr(n, field_name, value3)
|
|
setattr(n, field_name_de, value2_de)
|
|
setattr(n, field_name_en, value2_en)
|
|
n.save()
|
|
self.failUnlessEqual(getattr(n, field_name), value2_de)
|
|
self.failUnlessEqual(getattr(n, field_name_de), value2_de)
|
|
self.failUnlessEqual(getattr(n, field_name_en), value2_en)
|
|
|
|
setattr(n, field_name, value3)
|
|
n.save()
|
|
self.failUnlessEqual(getattr(n, field_name), value3)
|
|
self.failUnlessEqual(getattr(n, field_name_de), value3)
|
|
self.failUnlessEqual(getattr(n, field_name_en), value2_en)
|
|
|
|
if deactivate:
|
|
trans_real.deactivate()
|
|
|
|
def test_rule4(self):
|
|
"""
|
|
Basic CharField/TextField test.
|
|
Could as well call _test_field, just kept for reference.
|
|
"""
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
title1_de = "title de"
|
|
title1_en = "title en"
|
|
n = TestModel.objects.create(title_de=title1_de, title_en=title1_en)
|
|
self.failUnlessEqual(n.title, title1_de)
|
|
self.failUnlessEqual(n.title_de, title1_de)
|
|
self.failUnlessEqual(n.title_en, title1_en)
|
|
|
|
title2_de = "neu de"
|
|
title2_en = "new en"
|
|
title_foo = "foo"
|
|
n.title = title_foo
|
|
n.title_de = title2_de
|
|
n.title_en = title2_en
|
|
n.save()
|
|
self.failUnlessEqual(n.title, title2_de)
|
|
self.failUnlessEqual(n.title_de, title2_de)
|
|
self.failUnlessEqual(n.title_en, title2_en)
|
|
|
|
n.title = title_foo
|
|
n.save()
|
|
self.failUnlessEqual(n.title, title_foo)
|
|
self.failUnlessEqual(n.title_de, title_foo)
|
|
self.failUnlessEqual(n.title_en, title2_en)
|
|
|
|
def test_rule4_url_field(self):
|
|
self._test_field(field_name='url',
|
|
value1_de='http://www.google.de',
|
|
value1_en='http://www.google.com',
|
|
value2_de='http://www.google.at',
|
|
value2_en='http://www.google.co.uk',
|
|
value3='http://www.google.net')
|
|
|
|
def test_rule4_email_field(self):
|
|
self._test_field(field_name='email',
|
|
value1_de='django-modeltranslation@googlecode.de',
|
|
value1_en='django-modeltranslation@googlecode.com',
|
|
value2_de='django-modeltranslation@googlecode.at',
|
|
value2_en='django-modeltranslation@googlecode.co.uk',
|
|
value3='django-modeltranslation@googlecode.net')
|
|
|
|
|
|
class ModelValidationTest(ModeltranslationTestBase):
|
|
"""
|
|
Tests if a translation model field validates correctly.
|
|
"""
|
|
def _test_model_validation(self, field_name, invalid_value, valid_value,
|
|
invalid_value_de):
|
|
"""
|
|
Generic model field validation test.
|
|
"""
|
|
field_name_de = '%s_de' % field_name
|
|
params = {'title_de': 'title de', 'title_en': 'title en',
|
|
field_name: invalid_value}
|
|
|
|
has_error_key = False
|
|
# Create an object with an invalid url
|
|
#n = TestModel.objects.create(title='Title', url='foo')
|
|
n = TestModel.objects.create(**params)
|
|
|
|
# First check the original field
|
|
# Expect that the validation object contains an error for url
|
|
try:
|
|
n.full_clean()
|
|
except ValidationError, e:
|
|
if field_name in e.message_dict:
|
|
has_error_key = True
|
|
self.assertTrue(has_error_key)
|
|
|
|
# Check the translation field
|
|
# Language is set to 'de' at this point
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
# Set translation field to a valid url
|
|
#n.url_de = 'http://code.google.com/p/django-modeltranslation/'
|
|
setattr(n, field_name_de, valid_value)
|
|
has_error_key = False
|
|
# Expect that the validation object contains no error for url
|
|
try:
|
|
n.full_clean()
|
|
except ValidationError, e:
|
|
if field_name_de in e.message_dict:
|
|
has_error_key = True
|
|
self.assertFalse(has_error_key)
|
|
|
|
# Set translation field to an invalid url
|
|
#n.url_de = 'foo'
|
|
setattr(n, field_name_de, invalid_value)
|
|
has_error_key = False
|
|
# Expect that the validation object contains an error for url_de
|
|
try:
|
|
n.full_clean()
|
|
except ValidationError, e:
|
|
#if 'url_de' in e.message_dict:
|
|
if field_name_de in e.message_dict:
|
|
has_error_key = True
|
|
self.assertTrue(has_error_key)
|
|
|
|
def test_model_validation(self):
|
|
"""
|
|
General test for CharField and TextField.
|
|
"""
|
|
has_error_key = False
|
|
# Create an object without title (which is required)
|
|
n = TestModel.objects.create(text='Testtext')
|
|
|
|
# First check the original field
|
|
# Expect that the validation object contains an error for title
|
|
try:
|
|
n.full_clean()
|
|
except ValidationError, e:
|
|
if 'title' in e.message_dict:
|
|
has_error_key = True
|
|
self.assertTrue(has_error_key)
|
|
n.save()
|
|
|
|
# Check the translation field
|
|
# Language is set to 'de' at this point
|
|
self.failUnlessEqual(get_language(), 'de')
|
|
# Set translation field to a valid title
|
|
n.title_de = 'Title'
|
|
has_error_key = False
|
|
# Expect that the validation object contains no error for title
|
|
try:
|
|
n.full_clean()
|
|
except ValidationError, e:
|
|
if 'title_de' in e.message_dict:
|
|
has_error_key = True
|
|
self.assertFalse(has_error_key)
|
|
|
|
# Set translation field to an empty title
|
|
n.title_de = None
|
|
has_error_key = False
|
|
# Even though the original field isn't optional, translation fields are
|
|
# per definition always optional. So we expect that the validation
|
|
# object contains no error for title_de.
|
|
try:
|
|
n.full_clean()
|
|
except ValidationError, e:
|
|
if 'title_de' in e.message_dict:
|
|
has_error_key = True
|
|
self.assertFalse(has_error_key)
|
|
|
|
def test_model_validation_url_field(self):
|
|
#has_error_key = False
|
|
## Create an object with an invalid url
|
|
#n = TestModel.objects.create(title='Title', url='foo')
|
|
|
|
## First check the original field
|
|
## Expect that the validation object contains an error for url
|
|
#try:
|
|
#n.full_clean()
|
|
#except ValidationError, e:
|
|
#if 'url' in e.message_dict:
|
|
#has_error_key = True
|
|
#self.assertTrue(has_error_key)
|
|
|
|
## Check the translation field
|
|
## Language is set to 'de' at this point
|
|
#self.failUnlessEqual(get_language(), 'de')
|
|
## Set translation field to a valid url
|
|
#n.url_de = 'http://code.google.com/p/django-modeltranslation/'
|
|
#has_error_key = False
|
|
## Expect that the validation object contains no error for url
|
|
#try:
|
|
#n.full_clean()
|
|
#except ValidationError, e:
|
|
#if 'url_de' in e.message_dict:
|
|
#has_error_key = True
|
|
#self.assertFalse(has_error_key)
|
|
|
|
## Set translation field to an invalid url
|
|
#n.url_de = 'foo'
|
|
#has_error_key = False
|
|
## Expect that the validation object contains an error for url_de
|
|
#try:
|
|
#n.full_clean()
|
|
#except ValidationError, e:
|
|
#if 'url_de' in e.message_dict:
|
|
#has_error_key = True
|
|
#self.assertTrue(has_error_key)
|
|
|
|
self._test_model_validation(
|
|
field_name='url',
|
|
invalid_value='foo en',
|
|
valid_value='http://code.google.com/p/django-modeltranslation/',
|
|
invalid_value_de='foo de')
|
|
|
|
def test_model_validation_email_field(self):
|
|
self._test_model_validation(
|
|
field_name='email', invalid_value='foo en',
|
|
valid_value='django-modeltranslation@googlecode.com',
|
|
invalid_value_de='foo de')
|
|
|
|
|
|
class ModelInheritanceTest(ModeltranslationTestBase):
|
|
"""Tests for inheritance support in modeltranslation."""
|
|
def test_abstract_inheritance(self):
|
|
field_names_b = AbstractModelB._meta.get_all_field_names()
|
|
self.failIf('titled' in field_names_b)
|
|
self.failIf('titled_de' in field_names_b)
|
|
self.failIf('titled_en' in field_names_b)
|
|
|
|
def test_multitable_inheritance(self):
|
|
field_names_a = MultitableModelA._meta.get_all_field_names()
|
|
self.failUnless('titlea' in field_names_a)
|
|
self.failUnless('titlea_de' in field_names_a)
|
|
self.failUnless('titlea_en' in field_names_a)
|
|
|
|
field_names_b = MultitableBModelA._meta.get_all_field_names()
|
|
self.failUnless('titlea' in field_names_b)
|
|
self.failUnless('titlea_de' in field_names_b)
|
|
self.failUnless('titlea_en' in field_names_b)
|
|
self.failUnless('titleb' in field_names_b)
|
|
self.failUnless('titleb_de' in field_names_b)
|
|
self.failUnless('titleb_en' in field_names_b)
|
|
|
|
field_names_c = MultitableModelC._meta.get_all_field_names()
|
|
self.failUnless('titlea' in field_names_c)
|
|
self.failUnless('titlea_de' in field_names_c)
|
|
self.failUnless('titlea_en' in field_names_c)
|
|
self.failUnless('titleb' in field_names_c)
|
|
self.failUnless('titleb_de' in field_names_c)
|
|
self.failUnless('titleb_en' in field_names_c)
|
|
self.failUnless('titlec' in field_names_c)
|
|
self.failUnless('titlec_de' in field_names_c)
|
|
self.failUnless('titlec_en' in field_names_c)
|
|
|
|
field_names_d = MultitableDTestModel._meta.get_all_field_names()
|
|
self.failUnless('titlea' in field_names_d)
|
|
self.failUnless('titlea_de' in field_names_d)
|
|
self.failUnless('titlea_en' in field_names_d)
|
|
self.failUnless('titleb' in field_names_d)
|
|
self.failUnless('titleb_de' in field_names_d)
|
|
self.failUnless('titleb_en' in field_names_d)
|
|
self.failUnless('titled' in field_names_d)
|
|
|
|
|
|
class TranslationAdminTest(ModeltranslationTestBase):
|
|
def setUp(self):
|
|
trans_real.activate('de')
|
|
self.test_obj = TestModel.objects.create(
|
|
title='Testtitle', text='Testtext')
|
|
self.site = AdminSite()
|
|
|
|
def tearDown(self):
|
|
trans_real.deactivate()
|
|
self.test_obj.delete()
|
|
|
|
def test_default_fields(self):
|
|
class TestModelAdmin(TranslationAdmin):
|
|
pass
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
self.assertEqual(
|
|
ma.get_form(request).base_fields.keys(),
|
|
['title_de', 'title_en', 'text_de', 'text_en', 'url_de', 'url_en',
|
|
'email_de', 'email_en'])
|
|
|
|
def test_default_fieldsets(self):
|
|
class TestModelAdmin(TranslationAdmin):
|
|
pass
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
# We expect that the original field is excluded and only the
|
|
# translation fields are included in fields
|
|
fields = ['title_de', 'title_en', 'text_de', 'text_en',
|
|
'url_de', 'url_en', 'email_de', 'email_en']
|
|
self.assertEqual(
|
|
ma.get_fieldsets(request), [(None, {'fields': fields})])
|
|
self.assertEqual(
|
|
ma.get_fieldsets(request, self.test_obj),
|
|
[(None, {'fields': fields})])
|
|
|
|
def test_field_arguments(self):
|
|
class TestModelAdmin(TranslationAdmin):
|
|
fields = ['title']
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
fields = ['title_de', 'title_en']
|
|
self.assertEqual(ma.get_form(request).base_fields.keys(), fields)
|
|
self.assertEqual(
|
|
ma.get_form(request, self.test_obj).base_fields.keys(), fields)
|
|
|
|
def test_field_arguments_restricted_on_form(self):
|
|
# Using `fields`.
|
|
class TestModelAdmin(TranslationAdmin):
|
|
fields = ['title']
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
fields = ['title_de', 'title_en']
|
|
self.assertEqual(ma.get_form(request).base_fields.keys(), fields)
|
|
self.assertEqual(
|
|
ma.get_form(request, self.test_obj).base_fields.keys(), fields)
|
|
|
|
# Using `fieldsets`.
|
|
class TestModelAdmin(TranslationAdmin):
|
|
fieldsets = [(None, {'fields': ['title']})]
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
self.assertEqual(ma.get_form(request).base_fields.keys(), fields)
|
|
self.assertEqual(
|
|
ma.get_form(request, self.test_obj).base_fields.keys(), fields)
|
|
|
|
# Using `exclude`.
|
|
class TestModelAdmin(TranslationAdmin):
|
|
exclude = ['url', 'email']
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
fields = ['title_de', 'title_en', 'text_de', 'text_en']
|
|
self.assertEqual(
|
|
ma.get_form(request).base_fields.keys(), fields)
|
|
|
|
# You can also pass a tuple to `exclude`.
|
|
class TestModelAdmin(TranslationAdmin):
|
|
exclude = ('url', 'email')
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
self.assertEqual(
|
|
ma.get_form(request).base_fields.keys(), fields)
|
|
self.assertEqual(
|
|
ma.get_form(request, self.test_obj).base_fields.keys(), fields)
|
|
|
|
# Using `fields` and `exclude`.
|
|
class TestModelAdmin(TranslationAdmin):
|
|
fields = ['title', 'url']
|
|
exclude = ['url']
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
self.assertEqual(
|
|
ma.get_form(request).base_fields.keys(), ['title_de', 'title_en'])
|
|
|
|
def test_field_arguments_restricted_on_custom_form(self):
|
|
# Using `fields`.
|
|
class TestModelForm(forms.ModelForm):
|
|
class Meta:
|
|
model = TestModel
|
|
fields = ['url', 'email']
|
|
|
|
class TestModelAdmin(TranslationAdmin):
|
|
form = TestModelForm
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
fields = ['url_de', 'url_en', 'email_de', 'email_en']
|
|
self.assertEqual(
|
|
ma.get_form(request).base_fields.keys(), fields)
|
|
self.assertEqual(
|
|
ma.get_form(request, self.test_obj).base_fields.keys(), fields)
|
|
|
|
# Using `exclude`.
|
|
class TestModelForm(forms.ModelForm):
|
|
class Meta:
|
|
model = TestModel
|
|
exclude = ['url', 'email']
|
|
|
|
class TestModelAdmin(TranslationAdmin):
|
|
form = TestModelForm
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
fields = ['title_de', 'title_en', 'text_de', 'text_en']
|
|
self.assertEqual(
|
|
ma.get_form(request).base_fields.keys(), fields)
|
|
self.assertEqual(
|
|
ma.get_form(request, self.test_obj).base_fields.keys(), fields)
|
|
|
|
# If both, the custom form an the ModelAdmin define an `exclude`
|
|
# option, the ModelAdmin wins. This is Django behaviour.
|
|
class TestModelAdmin(TranslationAdmin):
|
|
form = TestModelForm
|
|
exclude = ['url']
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
fields = ['title_de', 'title_en', 'text_de', 'text_en', 'email_de',
|
|
'email_en']
|
|
self.assertEqual(
|
|
ma.get_form(request).base_fields.keys(), fields)
|
|
self.assertEqual(
|
|
ma.get_form(request, self.test_obj).base_fields.keys(), fields)
|
|
|
|
# Same for `fields`.
|
|
class TestModelForm(forms.ModelForm):
|
|
class Meta:
|
|
model = TestModel
|
|
fields = ['text', 'title']
|
|
|
|
class TestModelAdmin(TranslationAdmin):
|
|
form = TestModelForm
|
|
fields = ['email']
|
|
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
fields = ['email_de', 'email_en']
|
|
self.assertEqual(
|
|
ma.get_form(request).base_fields.keys(), fields)
|
|
self.assertEqual(
|
|
ma.get_form(request, self.test_obj).base_fields.keys(), fields)
|
|
|
|
def test_inline_fieldsets(self):
|
|
class DataInline(TranslationStackedInline):
|
|
model = DataModel
|
|
fieldsets = [
|
|
('Test', {'fields': ('data',)})
|
|
]
|
|
|
|
class TestModelAdmin(TranslationAdmin):
|
|
exclude = ('title', 'text',)
|
|
inlines = [DataInline]
|
|
|
|
class DataTranslationOptions(translator.TranslationOptions):
|
|
fields = ('data',)
|
|
|
|
translator.translator.register(DataModel,
|
|
DataTranslationOptions)
|
|
ma = TestModelAdmin(TestModel, self.site)
|
|
|
|
fieldsets = [('Test', {'fields': ['data_de', 'data_en']})]
|
|
|
|
try:
|
|
ma_fieldsets = ma.get_inline_instances(
|
|
request)[0].get_fieldsets(request)
|
|
except AttributeError: # Django 1.3 fallback
|
|
ma_fieldsets = ma.inlines[0](
|
|
TestModel, self.site).get_fieldsets(request)
|
|
self.assertEqual(ma_fieldsets, fieldsets)
|
|
|
|
try:
|
|
ma_fieldsets = ma.get_inline_instances(
|
|
request)[0].get_fieldsets(request, self.test_obj)
|
|
except AttributeError: # Django 1.3 fallback
|
|
ma_fieldsets = ma.inlines[0](
|
|
TestModel, self.site).get_fieldsets(request, self.test_obj)
|
|
self.assertEqual(ma_fieldsets, fieldsets)
|
|
|
|
|
|
class TestManager(ModeltranslationTestBase):
|
|
def setUp(self):
|
|
# In this test case the default language is en, not de.
|
|
trans_real.activate('en')
|
|
|
|
def test_filter_update(self):
|
|
"""Test if filtering and updating is language-aware."""
|
|
n = ManagerTestModel(title='')
|
|
n.title_en = 'en'
|
|
n.title_de = 'de'
|
|
n.save()
|
|
|
|
m = ManagerTestModel(title='')
|
|
m.title_en = 'title en'
|
|
m.title_de = 'de'
|
|
m.save()
|
|
|
|
self.assertEqual('en', get_language())
|
|
|
|
self.assertEqual(0, ManagerTestModel.objects.filter(title='de').count())
|
|
self.assertEqual(1, ManagerTestModel.objects.filter(title='en').count())
|
|
# Spanning works
|
|
self.assertEqual(2, ManagerTestModel.objects.filter(title__contains='en').count())
|
|
|
|
with override('de'):
|
|
self.assertEqual(2, ManagerTestModel.objects.filter(title='de').count())
|
|
self.assertEqual(0, ManagerTestModel.objects.filter(title='en').count())
|
|
# Spanning works
|
|
self.assertEqual(2, ManagerTestModel.objects.filter(title__endswith='e').count())
|
|
|
|
# Still possible to use explicit language version
|
|
self.assertEqual(1, ManagerTestModel.objects.filter(title_en='en').count())
|
|
self.assertEqual(2, ManagerTestModel.objects.filter(title_en__contains='en').count())
|
|
|
|
ManagerTestModel.objects.update(title='new')
|
|
self.assertEqual(2, ManagerTestModel.objects.filter(title='new').count())
|
|
n = ManagerTestModel.objects.get(pk=n.pk)
|
|
m = ManagerTestModel.objects.get(pk=m.pk)
|
|
self.assertEqual('en', n.title_en)
|
|
self.assertEqual('new', n.title_de)
|
|
self.assertEqual('title en', m.title_en)
|
|
self.assertEqual('new', m.title_de)
|
|
|
|
def test_q(self):
|
|
"""Test if Q queries are rewritten."""
|
|
n = ManagerTestModel(title='')
|
|
n.title_en = 'en'
|
|
n.title_de = 'de'
|
|
n.save()
|
|
|
|
self.assertEqual('en', get_language())
|
|
self.assertEqual(0, ManagerTestModel.objects.filter(Q(title='de') | Q(pk=42)).count())
|
|
self.assertEqual(1, ManagerTestModel.objects.filter(Q(title='en') | Q(pk=42)).count())
|
|
|
|
with override('de'):
|
|
self.assertEqual(1, ManagerTestModel.objects.filter(Q(title='de') | Q(pk=42)).count())
|
|
self.assertEqual(0, ManagerTestModel.objects.filter(Q(title='en') | Q(pk=42)).count())
|
|
|
|
def test_f(self):
|
|
"""Test if F queries are rewritten."""
|
|
n = ManagerTestModel.objects.create(visits_en=1, visits_de=2)
|
|
|
|
self.assertEqual('en', get_language())
|
|
ManagerTestModel.objects.update(visits=F('visits') + 10)
|
|
n = ManagerTestModel.objects.all()[0]
|
|
self.assertEqual(n.visits_en, 11)
|
|
self.assertEqual(n.visits_de, 2)
|
|
|
|
with override('de'):
|
|
ManagerTestModel.objects.update(visits=F('visits') + 20)
|
|
n = ManagerTestModel.objects.all()[0]
|
|
self.assertEqual(n.visits_en, 11)
|
|
self.assertEqual(n.visits_de, 22)
|
|
|
|
def test_custom_manager(self):
|
|
"""Test if user-defined manager is still working"""
|
|
n = CustomManagerTestModel(title='')
|
|
n.title_en = 'enigma'
|
|
n.title_de = 'foo'
|
|
n.save()
|
|
|
|
m = CustomManagerTestModel(title='')
|
|
m.title_en = 'enigma'
|
|
m.title_de = 'bar'
|
|
m.save()
|
|
|
|
# Custom method
|
|
self.assertEqual('bar', CustomManagerTestModel.objects.foo())
|
|
|
|
# Ensure that get_query_set is working - filter objects to those with 'a' in title
|
|
self.assertEqual('en', get_language())
|
|
self.assertEqual(2, CustomManagerTestModel.objects.count())
|
|
with override('de'):
|
|
self.assertEqual(1, CustomManagerTestModel.objects.count())
|
|
|
|
def test_creation(self):
|
|
"""Test if field are rewritten in create."""
|
|
self.assertEqual('en', get_language())
|
|
n = ManagerTestModel.objects.create(title='foo')
|
|
self.assertEqual('foo', n.title_en)
|
|
self.assertEqual(None, n.title_de)
|
|
self.assertEqual('foo', n.title)
|
|
|
|
# The same result
|
|
n = ManagerTestModel.objects.create(title_en='foo')
|
|
self.assertEqual('foo', n.title_en)
|
|
self.assertEqual(None, n.title_de)
|
|
self.assertEqual('foo', n.title)
|
|
|
|
# Language suffixed version wins
|
|
n = ManagerTestModel.objects.create(title='bar', title_en='foo')
|
|
self.assertEqual('foo', n.title_en)
|
|
self.assertEqual(None, n.title_de)
|
|
self.assertEqual('foo', n.title)
|
|
|
|
def test_creation_population(self):
|
|
"""Test if language fields are populated with default value on creation."""
|
|
n = ManagerTestModel.objects.create(title='foo', _populate=True)
|
|
self.assertEqual('foo', n.title_en)
|
|
self.assertEqual('foo', n.title_de)
|
|
self.assertEqual('foo', n.title)
|
|
|
|
# You can specify some language...
|
|
n = ManagerTestModel.objects.create(title='foo', title_de='bar', _populate=True)
|
|
self.assertEqual('foo', n.title_en)
|
|
self.assertEqual('bar', n.title_de)
|
|
self.assertEqual('foo', n.title)
|
|
|
|
# ... but remember that still original attribute points to current language
|
|
self.assertEqual('en', get_language())
|
|
n = ManagerTestModel.objects.create(title='foo', title_en='bar', _populate=True)
|
|
self.assertEqual('bar', n.title_en)
|
|
self.assertEqual('foo', n.title_de)
|
|
self.assertEqual('bar', n.title) # points to en
|
|
with override('de'):
|
|
self.assertEqual('foo', n.title) # points to de
|
|
self.assertEqual('en', get_language())
|
|
|
|
# This feature (for backward-compatibility) require _populate keyword...
|
|
n = ManagerTestModel.objects.create(title='foo')
|
|
self.assertEqual('foo', n.title_en)
|
|
self.assertEqual(None, n.title_de)
|
|
self.assertEqual('foo', n.title)
|
|
|
|
# ... or MODELTRANSLATION_AUTO_POPULATE setting
|
|
with override_settings(MODELTRANSLATION_AUTO_POPULATE=True):
|
|
reload(mt_settings)
|
|
self.assertEqual(True, mt_settings.AUTO_POPULATE)
|
|
n = ManagerTestModel.objects.create(title='foo')
|
|
self.assertEqual('foo', n.title_en)
|
|
self.assertEqual('foo', n.title_de)
|
|
self.assertEqual('foo', n.title)
|
|
|
|
# _populate keyword has highest priority
|
|
n = ManagerTestModel.objects.create(title='foo', _populate=False)
|
|
self.assertEqual('foo', n.title_en)
|
|
self.assertEqual(None, n.title_de)
|
|
self.assertEqual('foo', n.title)
|
|
|
|
# Restore previous state
|
|
reload(mt_settings)
|
|
self.assertEqual(False, mt_settings.AUTO_POPULATE)
|