Handle related fields in field descriptor (work in progress, issue 36).

This commit is contained in:
Dirk Eschler 2010-06-22 22:02:16 +00:00
parent 006239a68e
commit 5d5bf067ad
2 changed files with 56 additions and 22 deletions

View file

@ -11,12 +11,11 @@ from modeltranslation.fields import (TranslationField,
OneToOneTranslationField,
ManyToManyTranslationField)
from modeltranslation.utils import (TranslationFieldDescriptor,
RelatedTranslationFieldDescriptor,
ManyToManyTranslationFieldDescriptor,
build_localized_fieldname)
RELATED_CLASSES = ('ManyToOneRel', 'OneToOneRel', 'ManyToManyRel',)
class AlreadyRegistered(Exception):
pass
@ -68,7 +67,8 @@ def add_localized_fields(model):
# django model fields and therefore adds them via add_to_class
field = model._meta.get_field(field_name)
field_class_name = field.rel.__class__.__name__
if field_class_name in RELATED_CLASSES:
if field_class_name in ('ManyToOneRel', 'OneToOneRel',
'ManyToManyRel',):
to = field.rel.to._meta.object_name
if field_class_name == 'ManyToOneRel':
translation_field = ForeignKeyTranslationField(\
@ -176,11 +176,11 @@ class Translator(object):
rev_dict[ln] = orig_name
translation_opts.localized_fieldnames_rev = rev_dict
# TODO: Check if fallback_value is set to a type that the field
# expects and raise ImproperlyConfigured in case it doesn't.
model_fallback_values = getattr(translation_opts, 'fallback_values',
None)
for field_name in translation_opts.fields:
# TODO: Check if fallback_value is set to a type that the field
# expects and raise ImproperlyConfigured in case it doesn't.
if model_fallback_values is None:
field_fallback_value = None
elif isinstance(model_fallback_values, dict):
@ -188,8 +188,19 @@ class Translator(object):
None)
else:
field_fallback_value = model_fallback_values
setattr(model, field_name, TranslationFieldDescriptor(field_name,
fallback_value=field_fallback_value))
field = model._meta.get_field(field_name)
field_class_name = field.rel.__class__.__name__
if field_class_name in ('ManyToOneRel', 'OneToOneRel'):
descriptor = RelatedTranslationFieldDescriptor(field_name,
fallback_value=field_fallback_value)
elif field_class_name == 'ManyToManyRel':
descriptor = ManyToManyTranslationFieldDescriptor(field_name,
fallback_value=field_fallback_value)
else:
descriptor = TranslationFieldDescriptor(field_name,
fallback_value=field_fallback_value)
setattr(model, field_name, descriptor)
#signals.pre_init.connect(translated_model_initializing, sender=model,
#weak=False)

View file

@ -68,6 +68,7 @@ class TranslationFieldDescriptor(object):
self.name = name
self.val = initial_val
self.fallback_value = fallback_value
self.loc_field_name = ""
def __set__(self, instance, value):
lang = get_language()
@ -80,18 +81,40 @@ class TranslationFieldDescriptor(object):
def __get__(self, instance, owner):
if not instance:
raise ValueError(u"Translation field '%s' can only be "
"accessed via an instance not via "
"a class." % self.name)
lang = get_language()
loc_field_name = build_localized_fieldname(self.name, lang)
# FIXME: KeyError raised by ForeignKeyTanslationField
# in admin list view.
try:
name = instance.__dict__[self.name]
except KeyError:
return None
if hasattr(instance, loc_field_name):
return getattr(instance, loc_field_name) or\
(name if self.fallback_value is None else\
raise ValueError(u"Translation field '%s' can only be accessed "
"via an instance not via a class." % self.name)
self.loc_field_name = build_localized_fieldname(self.name,
get_language())
if hasattr(instance, self.loc_field_name):
return getattr(instance, self.loc_field_name) or\
(self.get_default_instance(instance) if\
self.fallback_value is None else\
self.fallback_value)
def get_default_instance(self, instance):
"""
Returns default instance of the field. Supposed to be overidden by
related subclasses.
"""
return instance.__dict__[self.name]
class RelatedTranslationFieldDescriptor(TranslationFieldDescriptor):
def __init__(self, name, initial_val="", fallback_value=None):
TranslationFieldDescriptor.__init__(self, name, initial_val="",
fallback_value=None)
def get_default_instance(self, instance):
# TODO: Implement
#instance_id = instance.__dict__['%s_id' % self.name]
pass
class ManyToManyTranslationFieldDescriptor(TranslationFieldDescriptor):
def __init__(self, name, initial_val="", fallback_value=None):
TranslationFieldDescriptor.__init__(self, name, initial_val="",
fallback_value=None)
def get_default_instance(self, instance):
# TODO: Implement
pass