django-parlor

Django model translations with even less nasty hacks.
git clone https://git.ce9e.org/django-parlor.git

commit
a6309429137149d3e468b4fea43a9955c275394b
parent
6421ce00c6cd47b9062906cf5966fcc9b4a4ba5a
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2025-08-07 06:55
fix cache

Diffstat

M parlor/models.py 27 +++++++++++++++++++--------
M tests/tests.py 24 +++++++++++++++++++++++-

2 files changed, 42 insertions, 9 deletions


diff --git a/parlor/models.py b/parlor/models.py

@@ -1,6 +1,5 @@
    1     1 from django.core.exceptions import ObjectDoesNotExist
    2     2 from django.db import models
    3    -1 from django.utils.functional import cached_property
    4     3 from django.utils.translation import get_language
    5     4 
    6     5 
@@ -13,15 +12,27 @@ class TranslatableModel(models.Model):
   13    12     class Meta:
   14    13         abstract = True
   15    14 
   16    -1     @cached_property
   -1    15     @property
   17    16     def translation(self):
   -1    17         if not self.pk:
   -1    18             return TranslationFallback()
   -1    19 
   18    20         lang = get_language()
   19    -1         if self.pk:
   20    -1             try:
   21    -1                 return self.translations.get(language_code=lang)
   22    -1             except ObjectDoesNotExist:
   23    -1                 pass
   24    -1         return TranslationFallback()
   -1    21 
   -1    22         translation = self.__dict__.get('_translation')
   -1    23         if translation and translation.language_code == lang:
   -1    24             return translation
   -1    25 
   -1    26         try:
   -1    27             translation = self.translations.get(language_code=lang)
   -1    28             self.__dict__['_translation'] = translation
   -1    29             return translation
   -1    30         except ObjectDoesNotExist:
   -1    31             return TranslationFallback()
   -1    32 
   -1    33     def refresh_from_db(self, *args, **kwargs):
   -1    34         self.__dict__.pop('_translation', None)
   -1    35         return super().refresh_from_db(*args, **kwargs)
   25    36 
   26    37     def __getattr__(self, key):
   27    38         fields = self.translations.model._meta.get_fields()

diff --git a/tests/tests.py b/tests/tests.py

@@ -22,7 +22,29 @@ class TranslatableModelTests(TestCase):
   22    22         with translation.override('de'):
   23    23             self.assertEqual(animal.label, 'Frosch')
   24    24 
   25    -1     def test_fallback(self):
   -1    25     def test_refresh_from_db(self):
   -1    26         animal = MyModel.objects.create()
   -1    27         en = animal.translations.create(language_code='en', label='Frog')
   -1    28 
   -1    29         with translation.override('en'):
   -1    30             self.assertEqual(animal.label, 'Frog')
   -1    31 
   -1    32         en.label = 'Cow'
   -1    33         en.save()
   -1    34         with translation.override('en'):
   -1    35             self.assertEqual(animal.label, 'Frog')
   -1    36 
   -1    37         animal.refresh_from_db()
   -1    38         with translation.override('en'):
   -1    39             self.assertEqual(animal.label, 'Cow')
   -1    40 
   -1    41     def test_unsaved(self):
   -1    42         animal = MyModel()
   -1    43 
   -1    44         with translation.override('en'):
   -1    45             self.assertEqual(animal.label, 'not translated')
   -1    46 
   -1    47     def test_no_translation(self):
   26    48         animal = MyModel.objects.create()
   27    49 
   28    50         with translation.override('en'):