302 for main
[wolnelektury.git] / apps / modeltranslation / admin.py
1 # -*- coding: utf-8 -*-
2 from copy import deepcopy
3
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
8
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
15
16
17 class TranslationAdminBase(object):
18     """
19     Mixin class which adds patch_translation_field functionality.
20     """
21     def patch_translation_field(self, db_field, field, **kwargs):
22         trans_opts = translator.get_options_for_model(self.model)
23
24         # Hide the original field by making it non-editable.
25         if db_field.name in trans_opts.fields:
26             db_field.editable = False
27
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),
33                                                            **kwargs)
34
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
41                 field.required = True
42                 field.blank = False
43
44             field.widget = deepcopy(orig_formfield.widget)
45
46
47 class TranslationAdmin(admin.ModelAdmin, TranslationAdminBase):
48     def __init__(self, *args, **kwargs):
49         super(TranslationAdmin, self).__init__(*args, **kwargs)
50
51         trans_opts = translator.get_options_for_model(self.model)
52
53         # Replace original field with translation field for each language
54         if self.fields:
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
62
63         if self.fieldsets:
64             fieldsets_new = list(self.fieldsets)
65             for (name, dct) in self.fieldsets:
66                 if 'fields' in dct:
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
75
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] = \
86                         translation_fields
87             self.list_editable = editable_new
88             self.list_display = display_new
89
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
96
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,
100                                                                     **kwargs)
101         self.patch_translation_field(db_field, field, **kwargs)
102         return field
103
104
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)
111         return field
112
113
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)
120         return field
121
122
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)
130         return field
131
132
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)
140         return field