Fix empty FileField handling (close #215).

This commit is contained in:
Jacek Tomaszewski 2013-11-13 19:04:42 +01:00
parent 26e6c1111b
commit 9a5fe20140
4 changed files with 49 additions and 2 deletions

View file

@ -270,6 +270,15 @@ class TranslationFieldDescriptor(object):
loc_field_name = build_localized_fieldname(self.field.name, get_language())
setattr(instance, loc_field_name, value)
def meaningful_value(self, val, undefined):
"""
Check if val is considered non-empty.
"""
if isinstance(val, fields.files.FieldFile):
return val.name and not (
isinstance(undefined, fields.files.FieldFile) and val == undefined)
return val is not None and val != undefined
def __get__(self, instance, owner):
"""
Returns value from the translation field for the current language, or
@ -287,13 +296,20 @@ class TranslationFieldDescriptor(object):
for lang in langs:
loc_field_name = build_localized_fieldname(self.field.name, lang)
val = getattr(instance, loc_field_name, None)
if val is not None and val != undefined:
if self.meaningful_value(val, undefined):
return val
if mt_settings.ENABLE_FALLBACKS and self.fallback_value is not NONE:
return self.fallback_value
else:
if default is NONE:
default = self.field.get_default()
# Some fields like FileField behave strange, as their get_default() doesn't return
# instance of attr_class, but rather None or ''.
# Normally this case is handled in the descriptor, but since we have overridden it, we
# must mock it up.
if (isinstance(self.field, fields.files.FileField) and
not isinstance(default, self.field.attr_class)):
return self.field.attr_class(instance, self.field, default)
return default

View file

@ -671,6 +671,36 @@ class FileFieldsTest(ModeltranslationTestBase):
inst.file_de.delete()
inst.image_de.delete()
def test_empty_field(self):
from django.db.models.fields.files import FieldFile
inst = models.FileFieldsModel()
self.assertIsInstance(inst.file, FieldFile)
self.assertIsInstance(inst.file2, FieldFile)
inst.save()
inst = models.FileFieldsModel.objects.all()[0]
self.assertIsInstance(inst.file, FieldFile)
self.assertIsInstance(inst.file2, FieldFile)
def test_fallback(self):
from django.db.models.fields.files import FieldFile
with reload_override_settings(MODELTRANSLATION_FALLBACK_LANGUAGES=('en',)):
self.assertEqual(get_language(), 'de')
inst = models.FileFieldsModel()
inst.file_de = ''
inst.file_en = 'foo'
inst.file2_de = ''
inst.file2_en = 'bar'
self.assertIsInstance(inst.file, FieldFile)
self.assertIsInstance(inst.file2, FieldFile)
self.assertEqual(inst.file.name, 'foo')
self.assertEqual(inst.file2.name, 'bar')
inst.save()
inst = models.FileFieldsModel.objects.all()[0]
self.assertIsInstance(inst.file, FieldFile)
self.assertIsInstance(inst.file2, FieldFile)
self.assertEqual(inst.file.name, 'foo')
self.assertEqual(inst.file2.name, 'bar')
class ForeignKeyFieldsTest(ModeltranslationTestBase):
@classmethod

View file

@ -52,6 +52,7 @@ class FallbackModel2(models.Model):
class FileFieldsModel(models.Model):
title = models.CharField(ugettext_lazy('title'), max_length=255)
file = models.FileField(upload_to='modeltranslation_tests', null=True, blank=True)
file2 = models.FileField(upload_to='modeltranslation_tests')
image = models.ImageField(upload_to='modeltranslation_tests', null=True, blank=True)

View file

@ -46,7 +46,7 @@ translator.register(FallbackModel2, FallbackModel2TranslationOptions)
########## File fields testing
class FileFieldsModelTranslationOptions(TranslationOptions):
fields = ('title', 'file', 'image',)
fields = ('title', 'file', 'file2', 'image',)
translator.register(FileFieldsModel, FileFieldsModelTranslationOptions)