0
# Admin Integration
1
2
Django admin integration with optimized country filters and form field handling. The admin integration provides efficient country-based filtering and selection in the Django admin interface with automatic field handling.
3
4
## Capabilities
5
6
### CountryFilter
7
8
Optimized Django admin list filter that only shows countries present in the current queryset, improving performance and user experience.
9
10
```python { .api }
11
class CountryFilter(admin.FieldListFilter):
12
"""
13
Optimized country filter for Django admin.
14
Only shows countries that exist in the current queryset.
15
"""
16
17
title = "Country" # Filter title in admin
18
19
def expected_parameters(self):
20
"""Return expected URL parameters for this filter."""
21
22
def choices(self, changelist):
23
"""Generate filter choice options."""
24
25
def lookup_choices(self, changelist):
26
"""Get available country choices from current queryset."""
27
```
28
29
## Usage Examples
30
31
### Basic Admin Configuration
32
33
```python
34
from django.contrib import admin
35
from django_countries.filters import CountryFilter
36
from myapp.models import Person
37
38
@admin.register(Person)
39
class PersonAdmin(admin.ModelAdmin):
40
list_display = ['name', 'country', 'email']
41
list_filter = [
42
('country', CountryFilter), # Use optimized country filter
43
'created_date'
44
]
45
search_fields = ['name', 'email']
46
47
# CountryField automatically gets proper admin widget
48
# No additional field configuration needed
49
```
50
51
### Multiple Country Fields
52
53
```python
54
from django.contrib import admin
55
from django_countries.filters import CountryFilter
56
from myapp.models import Organization
57
58
@admin.register(Organization)
59
class OrganizationAdmin(admin.ModelAdmin):
60
list_display = ['name', 'headquarters_country', 'employee_count']
61
list_filter = [
62
('headquarters_country', CountryFilter),
63
('operating_countries', CountryFilter), # Works with multiple countries too
64
'organization_type'
65
]
66
67
fieldsets = (
68
('Basic Information', {
69
'fields': ('name', 'description')
70
}),
71
('Geographic Information', {
72
'fields': ('headquarters_country', 'operating_countries')
73
}),
74
)
75
```
76
77
### Custom Admin Configuration
78
79
```python
80
from django.contrib import admin
81
from django import forms
82
from django_countries.widgets import CountrySelectWidget
83
from django_countries.filters import CountryFilter
84
from myapp.models import Event
85
86
class EventAdminForm(forms.ModelForm):
87
"""Custom admin form with enhanced country widget."""
88
89
class Meta:
90
model = Event
91
fields = '__all__'
92
widgets = {
93
'country': CountrySelectWidget(attrs={
94
'class': 'admin-country-select',
95
'style': 'width: 200px;'
96
})
97
}
98
99
@admin.register(Event)
100
class EventAdmin(admin.ModelAdmin):
101
form = EventAdminForm
102
list_display = ['title', 'country', 'start_date', 'attendee_count']
103
list_filter = [
104
('country', CountryFilter),
105
'event_type',
106
'start_date'
107
]
108
109
# Enable country-based search
110
search_fields = ['title', 'description', 'country__name_exact']
111
```
112
113
### Inline Admin Support
114
115
```python
116
from django.contrib import admin
117
from myapp.models import Company, Office
118
119
class OfficeInline(admin.TabularInline):
120
"""Inline for company offices with country selection."""
121
model = Office
122
extra = 1
123
fields = ['city', 'country', 'employee_count']
124
125
# CountryField automatically gets proper inline widget
126
127
@admin.register(Company)
128
class CompanyAdmin(admin.ModelAdmin):
129
list_display = ['name', 'headquarters_country', 'total_offices']
130
list_filter = [
131
('headquarters_country', CountryFilter),
132
]
133
inlines = [OfficeInline]
134
135
def total_offices(self, obj):
136
return obj.offices.count()
137
total_offices.short_description = 'Total Offices'
138
```
139
140
## Filter Behavior
141
142
### Optimized Filtering
143
144
The CountryFilter only displays countries that exist in the current queryset:
145
146
```python
147
# Example: Person model with countries ["US", "CA", "DE", "FR", "JP"]
148
# CountryFilter will only show these 5 countries as options
149
# Instead of showing all 249+ countries
150
151
@admin.register(Person)
152
class PersonAdmin(admin.ModelAdmin):
153
list_filter = [('country', CountryFilter)]
154
155
# Filter automatically adapts to:
156
# - Current search results
157
# - Other active filters
158
# - Queryset restrictions
159
```
160
161
### Filter URL Parameters
162
163
```python
164
# CountryFilter generates clean URL parameters:
165
# /admin/myapp/person/?country=US
166
# /admin/myapp/person/?country=US&country=CA (multiple selection in Django 5.0+)
167
168
# Works with other filters:
169
# /admin/myapp/person/?country=US&created_date__gte=2023-01-01
170
```
171
172
### Multiple Country Field Filtering
173
174
```python
175
from myapp.models import Organization
176
177
@admin.register(Organization)
178
class OrganizationAdmin(admin.ModelAdmin):
179
list_filter = [
180
('headquarters_country', CountryFilter),
181
('operating_countries', CountryFilter), # Filters multiple country field
182
]
183
184
# operating_countries filter shows all countries that appear
185
# in ANY organization's operating_countries list
186
```
187
188
## Advanced Admin Features
189
190
### Custom Filter Labels
191
192
```python
193
from django_countries.filters import CountryFilter
194
195
class HeadquartersCountryFilter(CountryFilter):
196
title = 'Headquarters Location' # Custom filter title
197
198
class OperatingRegionFilter(CountryFilter):
199
title = 'Operating Regions'
200
201
@admin.register(Organization)
202
class OrganizationAdmin(admin.ModelAdmin):
203
list_filter = [
204
('headquarters_country', HeadquartersCountryFilter),
205
('operating_countries', OperatingRegionFilter),
206
]
207
```
208
209
### Custom Country Display
210
211
```python
212
from django.contrib import admin
213
from django_countries import countries
214
215
@admin.register(Person)
216
class PersonAdmin(admin.ModelAdmin):
217
list_display = ['name', 'get_country_display', 'email']
218
list_filter = [('country', CountryFilter)]
219
220
def get_country_display(self, obj):
221
"""Custom country display with flag."""
222
if obj.country:
223
flag_url = obj.country.flag
224
return format_html(
225
'<img src="{}" width="16" height="12" style="margin-right: 5px;"> {}',
226
flag_url,
227
obj.country.name
228
)
229
return '-'
230
get_country_display.short_description = 'Country'
231
get_country_display.admin_order_field = 'country'
232
```
233
234
### Bulk Actions with Countries
235
236
```python
237
from django.contrib import admin
238
from django.contrib import messages
239
240
@admin.register(Person)
241
class PersonAdmin(admin.ModelAdmin):
242
list_display = ['name', 'country', 'status']
243
list_filter = [('country', CountryFilter)]
244
actions = ['assign_to_us_region', 'export_by_country']
245
246
def assign_to_us_region(self, request, queryset):
247
"""Bulk assign people to US region."""
248
count = queryset.filter(country='US').update(region='North America')
249
messages.success(request, f'Updated {count} US residents to North America region.')
250
assign_to_us_region.short_description = 'Update US residents region'
251
252
def export_by_country(self, request, queryset):
253
"""Export selected records grouped by country."""
254
countries_data = {}
255
for person in queryset:
256
country = person.country.name if person.country else 'Unknown'
257
if country not in countries_data:
258
countries_data[country] = []
259
countries_data[country].append(person)
260
261
# Generate export (simplified example)
262
messages.info(request, f'Export prepared for {len(countries_data)} countries.')
263
export_by_country.short_description = 'Export by country'
264
```
265
266
### ReadOnly Country Display
267
268
```python
269
from django.contrib import admin
270
from django.utils.html import format_html
271
272
@admin.register(Person)
273
class PersonAdmin(admin.ModelAdmin):
274
list_display = ['name', 'country_with_flag']
275
readonly_fields = ['country_details']
276
277
def country_with_flag(self, obj):
278
"""Display country with flag in list view."""
279
if obj.country:
280
return format_html(
281
'<img src="{}" width="20"> {} ({})',
282
obj.country.flag,
283
obj.country.name,
284
obj.country.code
285
)
286
return '-'
287
country_with_flag.short_description = 'Country'
288
289
def country_details(self, obj):
290
"""Detailed country info in form view."""
291
if obj.country:
292
return format_html(
293
'''
294
<div style="padding: 10px; border: 1px solid #ddd;">
295
<img src="{}" width="32" style="float: left; margin-right: 10px;">
296
<strong>{}</strong><br>
297
Code: {}<br>
298
Alpha3: {}<br>
299
Numeric: {}<br>
300
IOC: {}
301
</div>
302
''',
303
obj.country.flag,
304
obj.country.name,
305
obj.country.code,
306
obj.country.alpha3,
307
obj.country.numeric or 'N/A',
308
obj.country.ioc_code or 'N/A'
309
)
310
return 'No country selected'
311
country_details.short_description = 'Country Information'
312
```
313
314
### Custom Fieldsets
315
316
```python
317
@admin.register(Organization)
318
class OrganizationAdmin(admin.ModelAdmin):
319
fieldsets = (
320
('Basic Information', {
321
'fields': ('name', 'description', 'website')
322
}),
323
('Location & Operations', {
324
'fields': ('headquarters_country', 'operating_countries'),
325
'description': 'Specify headquarters location and all countries of operation.'
326
}),
327
('Contact Information', {
328
'fields': ('contact_email', 'phone'),
329
'classes': ('collapse',)
330
}),
331
)
332
333
list_filter = [
334
('headquarters_country', CountryFilter),
335
('operating_countries', CountryFilter),
336
]
337
```
338
339
### Admin Search Integration
340
341
```python
342
@admin.register(Person)
343
class PersonAdmin(admin.ModelAdmin):
344
search_fields = [
345
'name',
346
'email',
347
'country__name_icontains', # Search by country name
348
]
349
list_filter = [('country', CountryFilter)]
350
351
# Example searches:
352
# "john" - finds people named John
353
# "united" - finds people from countries containing "United"
354
# "us" - finds people from countries containing "us" (like "United States", "Russia")
355
```
356
357
### Performance Optimization
358
359
```python
360
from django.contrib import admin
361
from django.db import models
362
363
@admin.register(Person)
364
class PersonAdmin(admin.ModelAdmin):
365
list_display = ['name', 'get_country_name']
366
list_filter = [('country', CountryFilter)]
367
368
# Optimize queries
369
def get_queryset(self, request):
370
"""Optimize queryset for country access."""
371
qs = super().get_queryset(request)
372
# CountryField doesn't need select_related since it's not a ForeignKey
373
# Country objects are created on-demand from stored codes
374
return qs
375
376
def get_country_name(self, obj):
377
"""Efficient country name display."""
378
return obj.country.name if obj.country else '-'
379
get_country_name.short_description = 'Country'
380
get_country_name.admin_order_field = 'country' # Enable sorting
381
```