Admin Reference
This page documents the Django admin integration components.
LocalizedFieldsAdmin
- class LocalizedFieldsAdmin
Base admin class for models with localized fields. Combines
LocalizedFieldsAdminMixinwithadmin.ModelAdmin.Usage:
from i18n_fields import LocalizedFieldsAdmin from .models import Article @admin.register(Article) class ArticleAdmin(LocalizedFieldsAdmin): list_display = ['title', 'created_at']
Features:
All features of
LocalizedFieldsAdminMixinNo need to explicitly extend
admin.ModelAdminCleaner, more concise syntax
Full type safety with Generic types
When to Use:
Use
LocalizedFieldsAdminwhen you don’t need to combine with other admin base classes. For multiple inheritance scenarios, useLocalizedFieldsAdminMixininstead.
LocalizedFieldsAdminMixin
- class LocalizedFieldsAdminMixin
Mixin for Django admin that enables localized field widgets and proper display.
Usage:
from django.contrib import admin from i18n_fields import LocalizedFieldsAdminMixin from .models import Article @admin.register(Article) class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin): list_display = ['title', 'created_at']
Features:
Automatic widget selection for localized fields
Tab or dropdown language switchers
Proper display in list_display
Read-only field support
Works with inlines
Attributes:
- localized_fields_display
Display mode for localized fields:
"tab"or"dropdown"Default:
None(usesI18N_FIELDS["DISPLAY"]setting)Example:
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin): localized_fields_display = 'dropdown'
Methods:
- formfield_for_dbfield(db_field, request, **kwargs)
Override to use localized field widgets.
Parameters:
db_field: The database fieldrequest: The HTTP request**kwargs: Additional arguments
Returns: Form field with appropriate widget
- get_fieldsets(request, obj=None)
Get fieldsets with localized readonly field names replaced.
Parameters:
request: The HTTP requestobj: The model instance (None for add view)
Returns: List of fieldsets
Class Attributes:
- Media
Media class that includes required CSS and JavaScript files.
CSS:
i18n_fields/i18n-fields-admin.css
JavaScript:
admin/js/jquery.init.jsi18n_fields/i18n-fields-admin.jsi18n_fields/js/martor_tabs.js(included automatically when martor is installed)
Display Modes
Tab Mode
Shows language tabs above each field.
Configuration:
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
localized_fields_display = 'tab'
Features:
Horizontal tabs for each language
Active tab highlighted
Easy switching between languages
Best for 2-6 languages
Visual Structure:
┌─────────┬─────────┬─────────┐
│ English │ Spanish │ French │ ← Tabs
└─────────┴─────────┴─────────┘
┌─────────────────────────────┐
│ Field content in English... │ ← Content
└─────────────────────────────┘
Dropdown Mode
Shows a dropdown menu to select language.
Configuration:
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
localized_fields_display = 'dropdown'
Features:
Dropdown with all languages
More compact
Good for 7+ languages
Visual Structure:
┌──────────────────────┐
│ English ▼ │ ← Dropdown
└──────────────────────┘
┌─────────────────────────────┐
│ Field content in English... │ ← Content
└─────────────────────────────┘
Widgets
AdminLocalizedFieldWidget
- class AdminLocalizedFieldWidget(display_mode='tab')
Base widget for localized fields in admin.
Parameters:
display_mode(str):"tab"or"dropdown"
Used For: Base
LocalizedField
AdminLocalizedCharFieldWidget
- class AdminLocalizedCharFieldWidget(display_mode='tab')
Widget for
LocalizedCharFieldwith text input.Inherits From:
AdminLocalizedFieldWidgetHTML Input:
<input type="text">
AdminLocalizedIntegerFieldWidget
- class AdminLocalizedIntegerFieldWidget(display_mode='tab')
Widget for
LocalizedIntegerFieldwith number input.HTML Input:
<input type="number">
AdminLocalizedFloatFieldWidget
- class AdminLocalizedFloatFieldWidget(display_mode='tab')
Widget for
LocalizedFloatFieldwith number input.HTML Input:
<input type="number" step="any">
AdminLocalizedBooleanFieldWidget
- class AdminLocalizedBooleanFieldWidget(display_mode='tab')
Widget for
LocalizedBooleanFieldwith checkbox.HTML Input:
<input type="checkbox">
AdminLocalizedFileFieldWidget
- class AdminLocalizedFileFieldWidget(display_mode='tab')
Widget for
LocalizedFileFieldwith file input.HTML Input:
<input type="file">Features:
Shows current file
Clear checkbox
Upload new file
AdminLocalizedMartorWidget
- class AdminLocalizedMartorWidget(display_mode='tab')
Widget for
LocalizedMartorFieldwith Markdown editor.Requires:
martorpackage installedFeatures:
Full Markdown editor with toolbar (bold, italic, links, images, etc.)
Live preview support
Syntax highlighting
Emoji and mention support (configurable via martor settings)
Works with both tab and dropdown display modes
List Display
Localized fields in list_display automatically show translated values.
Example:
@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
list_display = ['title', 'author', 'created_at']
Behavior:
Shows value in active language
Falls back to primary language if active language unavailable
Shows “-” if no value available
Custom Display:
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
list_display = ['custom_title', 'created_at']
def custom_title(self, obj):
return f"{obj.title} (ID: {obj.id})"
custom_title.short_description = 'Title'
Readonly Fields
Read-only localized fields show all translations.
Example:
@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
readonly_fields = ['slug', 'created_at']
fields = ['title', 'slug', 'content', 'created_at']
Behavior:
Shows tab or dropdown interface (based on
localized_fields_display)All translations visible but not editable
Respects display mode setting
Inline Admin
Use with inline admin classes:
TabularInline:
class ChapterInline(LocalizedFieldsAdminMixin, admin.TabularInline):
model = Chapter
fields = ['title', 'order']
extra = 1
@admin.register(Book)
class BookAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
inlines = [ChapterInline]
StackedInline:
class ChapterInline(LocalizedFieldsAdminMixin, admin.StackedInline):
model = Chapter
fields = ['title', 'content', 'order']
extra = 0
Behavior:
Each inline row has localized field widgets
Same display mode as parent admin
Works with TabularInline and StackedInline
Fieldsets
Organize localized fields in fieldsets:
Example:
@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
fieldsets = [
('Content', {
'fields': ['title', 'slug', 'content']
}),
('Metadata', {
'fields': ['author', 'published', 'created_at'],
'classes': ['collapse']
}),
]
Features:
Localized fields work in any fieldset
Support for
classes(e.g.,collapse,wide)Support for
description
Search
Enable search by specific languages:
Example:
@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
search_fields = [
'title__en',
'title__es',
'content__en',
'author__name',
]
Usage:
# Search across English and Spanish titles
# Admin search box will search all specified fields
Filtering
Custom Filters
Create custom filters for localized fields:
from django.contrib import admin
class TitleLanguageFilter(admin.SimpleListFilter):
title = 'title language availability'
parameter_name = 'title_lang'
def lookups(self, request, model_admin):
return [
('en', 'Has English'),
('es', 'Has Spanish'),
('fr', 'Has French'),
]
def queryset(self, request, queryset):
if self.value() == 'en':
return queryset.filter(title__en__isnull=False)
if self.value() == 'es':
return queryset.filter(title__es__isnull=False)
if self.value() == 'fr':
return queryset.filter(title__fr__isnull=False)
@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
list_filter = [TitleLanguageFilter, 'published']
Ordering
Order by localized fields:
Example:
from i18n_fields import L
@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
# Order by title in current language
return qs.order_by(L('title'))
# Alternative: Order by specific language
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.order_by(L('title', 'en'))
Actions
Admin actions work with localized fields:
Example:
@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
actions = ['duplicate_to_spanish']
def duplicate_to_spanish(self, request, queryset):
for article in queryset:
title = article.title
if title.get('en') and not title.get('es'):
# Copy English to Spanish
title.set('es', title.get('en'))
article.title = title
article.save()
self.message_user(
request,
f'{queryset.count()} articles updated'
)
duplicate_to_spanish.short_description = 'Duplicate EN to ES'
Customization
Custom Widgets
Override widgets for specific fields:
from i18n_fields.widgets import AdminLocalizedFieldWidget
@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
def formfield_for_dbfield(self, db_field, request, **kwargs):
if db_field.name == 'title':
kwargs['widget'] = AdminLocalizedFieldWidget(
display_mode='dropdown'
)
return super().formfield_for_dbfield(db_field, request, **kwargs)
Custom CSS
Add custom styling:
@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
class Media:
css = {
'all': ('css/custom_i18n_admin.css',)
}
/* static/css/custom_i18n_admin.css */
.i18n-tab {
padding: 10px 20px;
font-weight: bold;
}
.i18n-tab.active {
background-color: #0066cc;
color: white;
}
Best Practices
Use LocalizedFieldsAdmin or LocalizedFieldsAdminMixin
Always use one of these for proper widget support:
# Best - using base class class ArticleAdmin(LocalizedFieldsAdmin): pass # Good - using mixin class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin): pass # Missing features - don't do this class ArticleAdmin(admin.ModelAdmin): pass
Choose Appropriate Display Mode
Tab mode: Best for 2-6 languages
Dropdown mode: Best for 7+ languages
Include in list_display
Show localized fields in list view:
list_display = ['title', 'created_at', 'published']
Use Language-Specific Search
Specify languages in search_fields:
search_fields = ['title__en', 'title__es', 'content__en']
Order Explicitly
Use
L()for consistent ordering:def get_queryset(self, request): return super().get_queryset(request).order_by(L('title', 'en'))
Troubleshooting
Widgets Not Showing
Problem: Localized field widgets not appearing
Solution:
Ensure mixin is included and comes first:
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin): pass
Check static files are collected:
python manage.py collectstatic
JavaScript Not Working
Problem: Tabs/dropdowns not switching
Solution:
Check browser console for errors
Ensure jQuery is loaded (required by Django admin)
Clear browser cache
Readonly Fields Not Displaying
Problem: Readonly localized fields showing as plain text
Solution:
Ensure the mixin is included - it handles readonly field display automatically.
See Also
Django Admin Integration - Admin integration guide
Fields Reference - Localized field types