handle null fields in modeltranslation
[wolnelektury.git] / apps / modeltranslation / fields.py
1 # -*- coding: utf-8 -*-
2 from django.conf import settings
3 from django.db.models.fields import Field, CharField
4
5 from modeltranslation.utils import get_language, build_localized_fieldname
6
7
8 class TranslationField(Field):
9     """
10     The translation field functions as a proxy to the original field which is
11     wrapped.
12
13     For every field defined in the model's ``TranslationOptions`` localized
14     versions of that field are added to the model depending on the languages
15     given in ``settings.LANGUAGES``.
16
17     If for example there is a model ``News`` with a field ``title`` which is
18     registered for translation and the ``settings.LANGUAGES`` contains the
19     ``de`` and ``en`` languages, the fields ``title_de`` and ``title_en`` will
20     be added to the model class. These fields are realized using this
21     descriptor.
22
23     The translation field needs to know which language it contains therefore
24     that needs to be specified when the field is created.
25     """
26     def __init__(self, translated_field, language, *args, **kwargs):
27         # Store the originally wrapped field for later
28         self.translated_field = translated_field
29         self.language = language
30
31         # Update the dict of this field with the content of the original one
32         # This might be a bit radical?! Seems to work though...
33         self.__dict__.update(translated_field.__dict__)
34
35         # Translation are always optional (for now - maybe add some parameters
36         # to the translation options for configuring this)
37         self.null = True
38         self.blank = True
39
40         # Adjust the name of this field to reflect the language
41         self.attname = build_localized_fieldname(translated_field.name,
42                                                  language)
43         self.name = self.attname
44
45         # Copy the verbose name and append a language suffix (will e.g. in the
46         # admin). This might be a proxy function so we have to check that here.
47         if hasattr(translated_field.verbose_name, '_proxy____unicode_cast'):
48             verbose_name = \
49                 translated_field.verbose_name._proxy____unicode_cast()
50         else:
51             verbose_name = translated_field.verbose_name
52         self.verbose_name = '%s [%s]' % (verbose_name, language)
53
54     def pre_save(self, model_instance, add):
55         val = super(TranslationField, self).pre_save(model_instance, add)
56         if get_language() == self.language and not add:
57             # Rule is: 3. Assigning a value to a translation field of the
58             # default language also updates the original field
59             model_instance.__dict__[self.translated_field.name] = val
60         return val
61
62     def get_internal_type(self):
63         return self.translated_field.get_internal_type()
64
65     #def contribute_to_class(self, cls, name):
66         #super(TranslationField, self).contribute_to_class(cls, name)
67         ##setattr(cls, 'get_%s_display' % self.name,
68                 ##curry(cls._get_FIELD_display, field=self))
69
70     def south_field_triple(self):
71         """Returns a suitable description of this field for South."""
72         # We'll just introspect the _actual_ field.
73         from south.modelsinspector import introspector
74         field_class = '%s.%s' % (self.translated_field.__class__.__module__,
75                                  self.translated_field.__class__.__name__)
76         args, kwargs = introspector(self.translated_field)
77
78         # This is patched in init and so should be here! -- lqc
79         kwargs['blank'], kwargs['null'] = True, True
80
81         # That's our definition!
82         return (field_class, args, kwargs)
83
84     def formfield(self, *args, **kwargs):
85         """Preserves the widget of the translated field."""
86         trans_formfield = self.translated_field.formfield(*args, **kwargs)
87         defaults = {'widget': type(trans_formfield.widget)}
88         defaults.update(kwargs)
89         return super(TranslationField, self).formfield(*args, **defaults)
90
91
92 #class CurrentLanguageField(CharField):
93     #def __init__(self, **kwargs):
94         #super(CurrentLanguageField, self).__init__(null=True, max_length=5,
95               #**kwargs)
96
97     #def contribute_to_class(self, cls, name):
98         #super(CurrentLanguageField, self).contribute_to_class(cls, name)
99         #registry = CurrentLanguageFieldRegistry()
100         #registry.add_field(cls, self)
101
102
103 #class CurrentLanguageFieldRegistry(object):
104     #_registry = {}
105
106     #def add_field(self, model, field):
107         #reg = self.__class__._registry.setdefault(model, [])
108         #reg.append(field)
109
110     #def get_fields(self, model):
111         #return self.__class__._registry.get(model, [])
112
113     #def __contains__(self, model):
114         #return model in self.__class__._registry