1 # -*- coding: utf-8 -*-
2 from django.db import models
3 from django.conf import settings
4 from django.core.exceptions import ValidationError
5 from django.contrib.contenttypes.models import ContentType
6 from django.utils.translation import get_language as _get_language
11 Return an active language code that is guaranteed to be in
12 settings.LANGUAGES (Django does not seem to guarantee this for us.)
15 lang = _get_language()
16 available_languages = [l[0] for l in settings.LANGUAGES]
17 if lang not in available_languages and '-' in lang:
18 lang = lang.split('-')[0]
19 if lang in available_languages:
21 return available_languages[0]
24 def get_translation_fields(field):
25 """Returns a list of localized fieldnames for a given field."""
26 return [build_localized_fieldname(field, l[0]) for l in settings.LANGUAGES]
29 def build_localized_fieldname(field_name, lang):
30 return '%s_%s' % (field_name, lang.replace('-', '_'))
33 class TranslationFieldDescriptor(object):
34 """A descriptor used for the original translated field."""
35 def __init__(self, name, initial_val=""):
37 The ``name`` is the name of the field (which is not available in the
38 descriptor by default - this is Python behaviour).
41 self.val = initial_val
43 def __set__(self, instance, value):
45 loc_field_name = build_localized_fieldname(self.name, lang)
46 # also update the translation field of the current language
47 setattr(instance, loc_field_name, value)
48 # update the original field via the __dict__ to prevent calling the
50 instance.__dict__[self.name] = value
52 def __get__(self, instance, owner):
54 raise ValueError(u"Translation field '%s' can only be "
55 "accessed via an instance not via "
56 "a class." % self.name)
58 loc_field_name = build_localized_fieldname(self.name, lang)
59 if hasattr(instance, loc_field_name):
60 return getattr(instance, loc_field_name) or \
61 instance.__dict__[self.name]
62 return instance.__dict__[self.name]
65 #def create_model(name, fields=None, app_label='', module='', options=None,
68 #Create specified model.
69 #This is taken from http://code.djangoproject.com/wiki/DynamicModels
72 ## Using type('Meta', ...) gives a dictproxy error during model
77 ## app_label must be set using the Meta inner class
78 #setattr(Meta, 'app_label', app_label)
80 ## Update Meta with any options that were provided
81 #if options is not None:
82 #for key, value in options.iteritems():
83 #setattr(Meta, key, value)
85 ## Set up a dictionary to simulate declarations within a class
86 #attrs = {'__module__': module, 'Meta': Meta}
88 ## Add in any fields that were provided
92 ## Create the class, which automatically triggers ModelBase processing
93 #model = type(name, (models.Model,), attrs)
95 ## Create an Admin class if admin options were provided
96 #if admin_opts is not None:
97 #class Admin(admin.ModelAdmin):
99 #for key, value in admin_opts:
100 #setattr(Admin, key, value)
101 #admin.site.register(model, Admin)
106 def copy_field(field):
108 Instantiate a new field, with all of the values from the old one, except
109 the to and to_field in the case of related fields.
111 This taken from http://www.djangosnippets.org/snippets/442/
113 base_kw = dict([(n, getattr(field, n, '_null')) for n in \
114 models.fields.Field.__init__.im_func.func_code.co_varnames])
115 if isinstance(field, models.fields.related.RelatedField):
116 rel = base_kw.get('rel')
117 rel_kw = dict([(n, getattr(rel, n, '_null')) for n in \
118 rel.__init__.im_func.func_code.co_varnames])
119 if isinstance(field, models.fields.related.ForeignKey):
120 base_kw['to_field'] = rel_kw.pop('field_name')
121 base_kw.update(rel_kw)
123 return field.__class__(**base_kw)