Skip to content

Commit

Permalink
Merge branch 'master' into UPDATE_prevent_using_i18n_virt_field_as_fo…
Browse files Browse the repository at this point in the history
…rm_field
  • Loading branch information
dfirst committed May 17, 2019
2 parents 997e4e7 + 862d4f5 commit 8a629ab
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Table of contents
:caption: Documentation

pages/getting-started
pages/working-with-models
pages/performance
pages/inner-workings
pages/known-issues
Expand Down
26 changes: 26 additions & 0 deletions docs/pages/working-with-models.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Working with models recipes.
============================

Inheritance of translation models.
----------------------------------

In case when you are working with models Inheritance and you want to change
behavior of TranslationField declared in parent model, you should use
`i18n_field_params` attribute and declare there parameters
for child model field.

Example of use: ::

class ParentModel(models.Model):
info = models.CharField(max_length=255)

i18n = TranslationField(fields=("info", ), required_languages=("en",))


class ChildModel(ParentModel):
child_info = models.CharField(max_length=255)

i18n_field_params = {
"fields": ("info", "child_info"),
"required_languages": ("nl",)
}
14 changes: 13 additions & 1 deletion modeltrans/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ def get_translated_models(app_name):
yield model


def get_i18n_field_param(Model, i18n_field, param_name):
"""
Return i18n_param from Model.i18n_field_params dict if exists
or get param from i18n_field
"""
if hasattr(Model, "i18n_field_params") and param_name in Model.i18n_field_params:
return Model.i18n_field_params[param_name]
return getattr(i18n_field, param_name)


def translate_model(Model):
i18n_field = get_i18n_field(Model)

Expand All @@ -52,7 +62,9 @@ def translate_model(Model):
validate(Model)

add_manager(Model)
add_virtual_fields(Model, i18n_field.fields, i18n_field.required_languages)
fields_to_translate = get_i18n_field_param(Model, i18n_field, "fields")
required_languages = get_i18n_field_param(Model, i18n_field, "required_languages")
add_virtual_fields(Model, fields_to_translate, required_languages)
patch_constructor(Model)

translate_meta_ordering(Model)
Expand Down
9 changes: 9 additions & 0 deletions tests/app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,12 @@ class Meta:
class Article(AbstractArticle):

pass


class ChildArticle(Article):
"""
Child Article for Django Models Inheritance testing
"""

child_title = models.CharField(max_length=255)
i18n_field_params = {"fields": ["title", "child_title"], "required_languages": ("nl",)}
29 changes: 28 additions & 1 deletion tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from django.utils.translation import override

from modeltrans.fields import TranslationField
from tests.app.models import Blog, NullableTextModel, TextModel
from tests.app.models import Article, Blog, ChildArticle, NullableTextModel, TextModel

from .utils import CreateTestModel

Expand Down Expand Up @@ -268,6 +268,33 @@ def test_defer_i18n(self):
blog.title_i18n


class TranslatedFieldInheritanceTest(TestCase):
def test_child_model_i18n_fields(self):
self.assertFalse(hasattr(Article, "child_title_nl"))
self.assertTrue(hasattr(ChildArticle, "child_title_nl"))

def test_child_model_required_languages(self):
self.assertTrue(Article._meta.get_field("title_nl").blank)
self.assertFalse(ChildArticle._meta.get_field("title_nl").blank)

def test_diff_i18n_parent_child_models_instances(self):
"""
Test different behavior of Article and ChildArticle instances
"""
article = Article(title="Title")
article.full_clean()
article.save()
child_article = ChildArticle(title="Title", child_title="Child title")
with self.assertRaises(ValidationError):
child_article.full_clean()
child_article.title_nl = "Title NL"
child_article.child_title_nl = "Child title NL"
child_article.full_clean()
child_article.save()
self.assertFalse("child_title_nl" in article.i18n)
self.assertTrue("child_title_nl" in child_article.i18n)


class RefreshFromDbTest(TestCase):
def test_refresh_from_db(self):
b = Blog.objects.create(title="Falcon", i18n={"title_nl": "Valk", "title_de": "Falk"})
Expand Down
1 change: 1 addition & 0 deletions tests/test_translating.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def test_get_translated_models(self):
expected = {
app_models.Article,
app_models.Blog,
app_models.ChildArticle,
app_models.Category,
app_models.Person,
app_models.TextModel,
Expand Down
5 changes: 5 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ basepython =
py35: python3.5
py36: python3.6
py37: python3.7

# workaround for Error installing '...django-tables2': editable mode is not supported for pyproject.toml-style projects.
# https://github.com/pypa/pip/issues/6434
install_command = python -m pip install --no-use-pep517 {opts} {packages}

usedevelop = true
pip_pre = true
setenv =
Expand Down

0 comments on commit 8a629ab

Please sign in to comment.