1 # -*- coding: utf-8 -*-
2 from copy import deepcopy
4 from django import forms, template
5 from django.conf import settings
6 from django.contrib import admin
7 from django.contrib.contenttypes import generic
9 from modeltranslation.translator import translator
10 from modeltranslation.utils import get_translation_fields
11 # Ensure that models are registered for translation before TranslationAdmin
12 # runs. The import is supposed to resolve a race condition between model import
13 # and translation registration in production (see issue 19).
14 import modeltranslation.models
17 class TranslationAdminBase(object):
19 Mixin class which adds patch_translation_field functionality.
21 def patch_translation_field(self, db_field, field, **kwargs):
22 trans_opts = translator.get_options_for_model(self.model)
24 # Hide the original field by making it non-editable.
25 if db_field.name in trans_opts.fields:
26 db_field.editable = False
28 # For every localized field copy the widget from the original field
29 if db_field.name in trans_opts.localized_fieldnames_rev:
30 orig_fieldname = trans_opts.localized_fieldnames_rev[db_field.name]
31 orig_formfield = self.formfield_for_dbfield( \
32 self.model._meta.get_field(orig_fieldname),
35 # In case the original form field was required, make the default
36 # translation field required instead.
37 if db_field.language == settings.LANGUAGES[0][0] and \
38 orig_formfield.required:
39 orig_formfield.required = False
40 orig_formfield.blank = True
44 field.widget = deepcopy(orig_formfield.widget)
47 class TranslationAdmin(admin.ModelAdmin, TranslationAdminBase):
48 def __init__(self, *args, **kwargs):
49 super(TranslationAdmin, self).__init__(*args, **kwargs)
51 trans_opts = translator.get_options_for_model(self.model)
53 # Replace original field with translation field for each language
55 fields_new = list(self.fields)
56 for field in self.fields:
57 if field in trans_opts.fields:
58 index = fields_new.index(field)
59 translation_fields = get_translation_fields(field)
60 fields_new[index:index + 1] = translation_fields
61 self.fields = fields_new
64 fieldsets_new = list(self.fieldsets)
65 for (name, dct) in self.fieldsets:
67 fields_new = list(dct['fields'])
68 for field in dct['fields']:
69 if field in trans_opts.fields:
70 index = fields_new.index(field)
71 translation_fields = get_translation_fields(field)
72 fields_new[index:index + 1] = translation_fields
73 dct['fields'] = fields_new
74 self.fieldsets = fieldsets_new
76 if self.list_editable:
77 editable_new = list(self.list_editable)
78 display_new = list(self.list_display)
79 for field in self.list_editable:
80 if field in trans_opts.fields:
81 index = editable_new.index(field)
82 display_index = display_new.index(field)
83 translation_fields = get_translation_fields(field)
84 editable_new[index:index + 1] = translation_fields
85 display_new[display_index:display_index + 1] = \
87 self.list_editable = editable_new
88 self.list_display = display_new
90 if self.prepopulated_fields:
91 prepopulated_fields_new = dict(self.prepopulated_fields)
92 for (k, v) in self.prepopulated_fields.items():
93 translation_fields = get_translation_fields(v[0])
94 prepopulated_fields_new[k] = tuple([translation_fields[0]])
95 self.prepopulated_fields = prepopulated_fields_new
97 def formfield_for_dbfield(self, db_field, **kwargs):
98 # Call the baseclass function to get the formfield
99 field = super(TranslationAdmin, self).formfield_for_dbfield(db_field,
101 self.patch_translation_field(db_field, field, **kwargs)
105 class TranslationTabularInline(admin.TabularInline, TranslationAdminBase):
106 def formfield_for_dbfield(self, db_field, **kwargs):
107 # Call the baseclass function to get the formfield
108 field = super(TranslationTabularInline,
109 self).formfield_for_dbfield(db_field, **kwargs)
110 self.patch_translation_field(db_field, field, **kwargs)
114 class TranslationStackedInline(admin.StackedInline, TranslationAdminBase):
115 def formfield_for_dbfield(self, db_field, **kwargs):
116 # Call the baseclass function to get the formfield
117 field = super(TranslationStackedInline,
118 self).formfield_for_dbfield(db_field, **kwargs)
119 self.patch_translation_field(db_field, field, **kwargs)
123 class TranslationGenericTabularInline(generic.GenericTabularInline,
124 TranslationAdminBase):
125 def formfield_for_dbfield(self, db_field, **kwargs):
126 # Call the baseclass function to get the formfield
127 field = super(TranslationGenericTabularInline,
128 self).formfield_for_dbfield(db_field, **kwargs)
129 self.patch_translation_field(db_field, field, **kwargs)
133 class TranslationGenericStackedInline(generic.GenericStackedInline,
134 TranslationAdminBase):
135 def formfield_for_dbfield(self, db_field, **kwargs):
136 # Call the baseclass function to get the formfield
137 field = super(TranslationGenericStackedInline,
138 self).formfield_for_dbfield(db_field, **kwargs)
139 self.patch_translation_field(db_field, field, **kwargs)