0
# Admin Integration
1
2
Seamless integration with Django's admin interface for managing multilingual content. Provides admin classes that automatically handle translation fields with proper layout, widgets, and validation.
3
4
## Capabilities
5
6
### Translation Admin Classes
7
8
Admin classes that automatically display translation fields with proper language tabs and field organization.
9
10
```python { .api }
11
class TranslationAdmin(admin.ModelAdmin):
12
"""
13
ModelAdmin subclass with automatic translation support.
14
15
Automatically handles:
16
- Language-specific field grouping
17
- Translation field widgets
18
- Prepopulated fields for translations
19
- Required field validation per language
20
"""
21
22
class TranslationBaseModelAdmin:
23
"""
24
Base admin mixin providing translation functionality.
25
Can be used with custom admin classes.
26
"""
27
```
28
29
**Usage Example:**
30
31
```python
32
from django.contrib import admin
33
from modeltranslation.admin import TranslationAdmin
34
from .models import Article
35
36
@admin.register(Article)
37
class ArticleAdmin(TranslationAdmin):
38
list_display = ('title', 'author', 'created_at')
39
list_filter = ('author', 'created_at')
40
search_fields = ('title', 'content')
41
prepopulated_fields = {'slug': ('title',)} # Works with translations
42
```
43
44
### Translation Inline Classes
45
46
Inline admin classes for handling related model translations within parent model admin.
47
48
```python { .api }
49
class TranslationTabularInline(admin.TabularInline):
50
"""
51
TabularInline with translation support.
52
Displays related translations in tabular format.
53
"""
54
55
class TranslationStackedInline(admin.StackedInline):
56
"""
57
StackedInline with translation support.
58
Displays related translations in stacked format.
59
"""
60
```
61
62
**Usage Example:**
63
64
```python
65
from modeltranslation.admin import TranslationAdmin, TranslationTabularInline
66
67
class CommentInline(TranslationTabularInline):
68
model = Comment
69
extra = 1
70
fields = ('content', 'author')
71
72
@admin.register(Article)
73
class ArticleAdmin(TranslationAdmin):
74
inlines = [CommentInline]
75
```
76
77
### Generic Inline Support
78
79
Support for generic foreign key relationships in admin with translation handling.
80
81
```python { .api }
82
class TranslationGenericTabularInline(GenericTabularInline):
83
"""GenericTabularInline with translation support."""
84
85
class TranslationGenericStackedInline(GenericStackedInline):
86
"""GenericStackedInline with translation support."""
87
```
88
89
**Usage Example:**
90
91
```python
92
from django.contrib.contenttypes.admin import GenericTabularInline
93
from modeltranslation.admin import TranslationGenericTabularInline
94
95
class TagInline(TranslationGenericTabularInline):
96
model = Tag
97
extra = 1
98
```
99
100
### Field Layout and Organization
101
102
Translation admin automatically organizes fields by language with intuitive grouping.
103
104
**Automatic Field Grouping:**
105
106
```python
107
# Model with translations
108
@register(News)
109
class NewsTranslationOptions(TranslationOptions):
110
fields = ('title', 'content', 'summary')
111
112
# Admin automatically creates language-specific fieldsets:
113
# - English: title_en, content_en, summary_en
114
# - French: title_fr, content_fr, summary_fr
115
# - German: title_de, content_de, summary_de
116
117
@admin.register(News)
118
class NewsAdmin(TranslationAdmin):
119
# No special configuration needed for basic translation support
120
pass
121
```
122
123
**Custom Field Organization:**
124
125
```python
126
@admin.register(Article)
127
class ArticleAdmin(TranslationAdmin):
128
fieldsets = (
129
(None, {
130
'fields': ('title', 'slug', 'author')
131
}),
132
('Content', {
133
'fields': ('content', 'summary'),
134
'classes': ('collapse',)
135
}),
136
('Metadata', {
137
'fields': ('published', 'created_at'),
138
'classes': ('collapse',)
139
})
140
)
141
# Translation fields are automatically added to appropriate fieldsets
142
```
143
144
### Widget Customization
145
146
Specialized widgets for handling translation-specific input requirements.
147
148
```python { .api }
149
class ClearableWidgetWrapper:
150
"""
151
Widget wrapper that adds clear functionality for nullable translation fields.
152
153
Parameters:
154
- widget: Base widget to wrap
155
- empty_value: Value to use when field is cleared (default: None)
156
"""
157
```
158
159
**Usage in Admin:**
160
161
```python
162
from modeltranslation.widgets import ClearableWidgetWrapper
163
from django import forms
164
165
class ArticleAdmin(TranslationAdmin):
166
def formfield_for_dbfield(self, db_field, request, **kwargs):
167
if db_field.name == 'optional_field':
168
kwargs['widget'] = ClearableWidgetWrapper(forms.Textarea())
169
return super().formfield_for_dbfield(db_field, request, **kwargs)
170
```
171
172
### Prepopulated Fields
173
174
Automatic handling of prepopulated fields (like slugs) across all translation languages.
175
176
```python
177
@admin.register(Article)
178
class ArticleAdmin(TranslationAdmin):
179
prepopulated_fields = {'slug': ('title',)}
180
# Automatically creates:
181
# - slug_en from title_en
182
# - slug_fr from title_fr
183
# - slug_de from title_de
184
```
185
186
### Language-Specific Validation
187
188
Configure required fields and validation per language.
189
190
```python
191
@register(Product)
192
class ProductTranslationOptions(TranslationOptions):
193
fields = ('name', 'description')
194
required_languages = ('en', 'fr') # English and French are required
195
196
@admin.register(Product)
197
class ProductAdmin(TranslationAdmin):
198
# Admin automatically enforces required language validation
199
pass
200
```
201
202
### Field Filtering and Search
203
204
Translation-aware field filtering and search functionality.
205
206
```python
207
@admin.register(Article)
208
class ArticleAdmin(TranslationAdmin):
209
list_display = ('title', 'author', 'created_at')
210
list_filter = ('author', 'created_at', 'category')
211
search_fields = ('title', 'content') # Searches across all language versions
212
213
def get_search_results(self, request, queryset, search_term):
214
# Custom search logic can access all translation fields
215
return super().get_search_results(request, queryset, search_term)
216
```
217
218
### Admin Media and Assets
219
220
Translation admin includes specialized JavaScript and CSS for enhanced user experience.
221
222
**Built-in Assets:**
223
- Language tab switching
224
- Clear button functionality for nullable fields
225
- Field synchronization helpers
226
- Validation feedback for required languages
227
228
```python
229
# Assets are automatically included, but can be customized:
230
class CustomTranslationAdmin(TranslationAdmin):
231
class Media:
232
js = TranslationAdmin.Media.js + ('custom_translation.js',)
233
css = {
234
'all': TranslationAdmin.Media.css['all'] + ('custom_translation.css',)
235
}
236
```
237
238
## Advanced Usage
239
240
### Mixed Admin Classes
241
242
Combine translation admin with other admin mixins and functionality.
243
244
```python
245
from django.contrib.admin import ModelAdmin
246
from modeltranslation.admin import TranslationBaseModelAdmin
247
from some_package.admin import SomeAdminMixin
248
249
class CustomArticleAdmin(SomeAdminMixin, TranslationBaseModelAdmin, ModelAdmin):
250
# Combines functionality from multiple admin classes
251
pass
252
```
253
254
### Conditional Translation Fields
255
256
Show/hide translation fields based on conditions.
257
258
```python
259
class ConditionalTranslationAdmin(TranslationAdmin):
260
def get_fieldsets(self, request, obj=None):
261
fieldsets = super().get_fieldsets(request, obj)
262
263
# Modify fieldsets based on user permissions or object state
264
if not request.user.has_perm('myapp.change_advanced_fields'):
265
# Remove advanced translation fields
266
pass
267
268
return fieldsets
269
```
270
271
### Bulk Translation Actions
272
273
Admin actions for bulk translation operations.
274
275
```python
276
def copy_translation(modeladmin, request, queryset):
277
"""Copy content from default language to other languages."""
278
for obj in queryset:
279
# Bulk translation logic
280
pass
281
282
copy_translation.short_description = "Copy to all languages"
283
284
class ArticleAdmin(TranslationAdmin):
285
actions = [copy_translation]
286
```
287
288
### Form Validation
289
290
Custom validation for translation forms.
291
292
```python
293
from django import forms
294
from modeltranslation.forms import TranslationModelForm
295
296
class ArticleTranslationForm(TranslationModelForm):
297
class Meta:
298
model = Article
299
fields = '__all__'
300
301
def clean(self):
302
cleaned_data = super().clean()
303
304
# Custom validation across translation fields
305
title_en = cleaned_data.get('title_en')
306
title_fr = cleaned_data.get('title_fr')
307
308
if title_en and not title_fr:
309
raise forms.ValidationError(
310
"French title is required when English title is provided"
311
)
312
313
return cleaned_data
314
315
class ArticleAdmin(TranslationAdmin):
316
form = ArticleTranslationForm
317
```