A Django application that provides country choices for use with forms, flag icons static files, and a country field for models.
—
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.
Optimized Django admin list filter that only shows countries present in the current queryset, improving performance and user experience.
class CountryFilter(admin.FieldListFilter):
"""
Optimized country filter for Django admin.
Only shows countries that exist in the current queryset.
"""
title = "Country" # Filter title in admin
def expected_parameters(self):
"""Return expected URL parameters for this filter."""
def choices(self, changelist):
"""Generate filter choice options."""
def lookup_choices(self, changelist):
"""Get available country choices from current queryset."""from django.contrib import admin
from django_countries.filters import CountryFilter
from myapp.models import Person
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_display = ['name', 'country', 'email']
list_filter = [
('country', CountryFilter), # Use optimized country filter
'created_date'
]
search_fields = ['name', 'email']
# CountryField automatically gets proper admin widget
# No additional field configuration neededfrom django.contrib import admin
from django_countries.filters import CountryFilter
from myapp.models import Organization
@admin.register(Organization)
class OrganizationAdmin(admin.ModelAdmin):
list_display = ['name', 'headquarters_country', 'employee_count']
list_filter = [
('headquarters_country', CountryFilter),
('operating_countries', CountryFilter), # Works with multiple countries too
'organization_type'
]
fieldsets = (
('Basic Information', {
'fields': ('name', 'description')
}),
('Geographic Information', {
'fields': ('headquarters_country', 'operating_countries')
}),
)from django.contrib import admin
from django import forms
from django_countries.widgets import CountrySelectWidget
from django_countries.filters import CountryFilter
from myapp.models import Event
class EventAdminForm(forms.ModelForm):
"""Custom admin form with enhanced country widget."""
class Meta:
model = Event
fields = '__all__'
widgets = {
'country': CountrySelectWidget(attrs={
'class': 'admin-country-select',
'style': 'width: 200px;'
})
}
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
form = EventAdminForm
list_display = ['title', 'country', 'start_date', 'attendee_count']
list_filter = [
('country', CountryFilter),
'event_type',
'start_date'
]
# Enable country-based search
search_fields = ['title', 'description', 'country__name_exact']from django.contrib import admin
from myapp.models import Company, Office
class OfficeInline(admin.TabularInline):
"""Inline for company offices with country selection."""
model = Office
extra = 1
fields = ['city', 'country', 'employee_count']
# CountryField automatically gets proper inline widget
@admin.register(Company)
class CompanyAdmin(admin.ModelAdmin):
list_display = ['name', 'headquarters_country', 'total_offices']
list_filter = [
('headquarters_country', CountryFilter),
]
inlines = [OfficeInline]
def total_offices(self, obj):
return obj.offices.count()
total_offices.short_description = 'Total Offices'The CountryFilter only displays countries that exist in the current queryset:
# Example: Person model with countries ["US", "CA", "DE", "FR", "JP"]
# CountryFilter will only show these 5 countries as options
# Instead of showing all 249+ countries
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_filter = [('country', CountryFilter)]
# Filter automatically adapts to:
# - Current search results
# - Other active filters
# - Queryset restrictions# CountryFilter generates clean URL parameters:
# /admin/myapp/person/?country=US
# /admin/myapp/person/?country=US&country=CA (multiple selection in Django 5.0+)
# Works with other filters:
# /admin/myapp/person/?country=US&created_date__gte=2023-01-01from myapp.models import Organization
@admin.register(Organization)
class OrganizationAdmin(admin.ModelAdmin):
list_filter = [
('headquarters_country', CountryFilter),
('operating_countries', CountryFilter), # Filters multiple country field
]
# operating_countries filter shows all countries that appear
# in ANY organization's operating_countries listfrom django_countries.filters import CountryFilter
class HeadquartersCountryFilter(CountryFilter):
title = 'Headquarters Location' # Custom filter title
class OperatingRegionFilter(CountryFilter):
title = 'Operating Regions'
@admin.register(Organization)
class OrganizationAdmin(admin.ModelAdmin):
list_filter = [
('headquarters_country', HeadquartersCountryFilter),
('operating_countries', OperatingRegionFilter),
]from django.contrib import admin
from django_countries import countries
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_display = ['name', 'get_country_display', 'email']
list_filter = [('country', CountryFilter)]
def get_country_display(self, obj):
"""Custom country display with flag."""
if obj.country:
flag_url = obj.country.flag
return format_html(
'<img src="{}" width="16" height="12" style="margin-right: 5px;"> {}',
flag_url,
obj.country.name
)
return '-'
get_country_display.short_description = 'Country'
get_country_display.admin_order_field = 'country'from django.contrib import admin
from django.contrib import messages
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_display = ['name', 'country', 'status']
list_filter = [('country', CountryFilter)]
actions = ['assign_to_us_region', 'export_by_country']
def assign_to_us_region(self, request, queryset):
"""Bulk assign people to US region."""
count = queryset.filter(country='US').update(region='North America')
messages.success(request, f'Updated {count} US residents to North America region.')
assign_to_us_region.short_description = 'Update US residents region'
def export_by_country(self, request, queryset):
"""Export selected records grouped by country."""
countries_data = {}
for person in queryset:
country = person.country.name if person.country else 'Unknown'
if country not in countries_data:
countries_data[country] = []
countries_data[country].append(person)
# Generate export (simplified example)
messages.info(request, f'Export prepared for {len(countries_data)} countries.')
export_by_country.short_description = 'Export by country'from django.contrib import admin
from django.utils.html import format_html
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_display = ['name', 'country_with_flag']
readonly_fields = ['country_details']
def country_with_flag(self, obj):
"""Display country with flag in list view."""
if obj.country:
return format_html(
'<img src="{}" width="20"> {} ({})',
obj.country.flag,
obj.country.name,
obj.country.code
)
return '-'
country_with_flag.short_description = 'Country'
def country_details(self, obj):
"""Detailed country info in form view."""
if obj.country:
return format_html(
'''
<div style="padding: 10px; border: 1px solid #ddd;">
<img src="{}" width="32" style="float: left; margin-right: 10px;">
<strong>{}</strong><br>
Code: {}<br>
Alpha3: {}<br>
Numeric: {}<br>
IOC: {}
</div>
''',
obj.country.flag,
obj.country.name,
obj.country.code,
obj.country.alpha3,
obj.country.numeric or 'N/A',
obj.country.ioc_code or 'N/A'
)
return 'No country selected'
country_details.short_description = 'Country Information'@admin.register(Organization)
class OrganizationAdmin(admin.ModelAdmin):
fieldsets = (
('Basic Information', {
'fields': ('name', 'description', 'website')
}),
('Location & Operations', {
'fields': ('headquarters_country', 'operating_countries'),
'description': 'Specify headquarters location and all countries of operation.'
}),
('Contact Information', {
'fields': ('contact_email', 'phone'),
'classes': ('collapse',)
}),
)
list_filter = [
('headquarters_country', CountryFilter),
('operating_countries', CountryFilter),
]@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
search_fields = [
'name',
'email',
'country__name_icontains', # Search by country name
]
list_filter = [('country', CountryFilter)]
# Example searches:
# "john" - finds people named John
# "united" - finds people from countries containing "United"
# "us" - finds people from countries containing "us" (like "United States", "Russia")from django.contrib import admin
from django.db import models
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_display = ['name', 'get_country_name']
list_filter = [('country', CountryFilter)]
# Optimize queries
def get_queryset(self, request):
"""Optimize queryset for country access."""
qs = super().get_queryset(request)
# CountryField doesn't need select_related since it's not a ForeignKey
# Country objects are created on-demand from stored codes
return qs
def get_country_name(self, obj):
"""Efficient country name display."""
return obj.country.name if obj.country else '-'
get_country_name.short_description = 'Country'
get_country_name.admin_order_field = 'country' # Enable sortingInstall with Tessl CLI
npx tessl i tessl/pypi-django-countries