Customizing ForeignKey Choices in Django Admin: Tailoring Forms Based on User Roles
In Django Admin, the formfield_for_foreignkey
method allows you to customize how ForeignKey fields are displayed in forms. This can be particularly useful for tailoring which options are available based on the user or specific conditions. Here’s a straightforward example of how to use formfield_for_foreignkey
to adjust field options based on user roles.
Let’s say you have a model named Project
with ForeignKey fields user
and company
. You want to customize the admin form so that:
- Superusers see all users except other superusers.
- Regular users can only see companies associated with them.
- Regular users see only users they created.
Here’s how you can achieve this:
# admin.py
from django.contrib import admin
from django.contrib.auth.models import User
from .models import Project, Company, CompanyUser, UserPreference
class ProjectAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
# Check if the user is a superuser
if request.user.is_superuser:
if db_field.name == "user":
# Show all users except superusers
kwargs["queryset"] = User.objects.filter(is_superuser=False)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
# If the user is not a superuser
if db_field.name == "company":
if request.user.is_owner:
# Show only companies associated with the logged-in user
queryset = CompanyUser.objects.filter(user=request.user)
kwargs["queryset"] = Company.objects.filter(
pk__in=[i.company.id for i in queryset])
else:
# Show only the company set in user preferences
kwargs["queryset"] = Company.objects.filter(
pk=UserPreference.objects.get(user=request.user).company)
if db_field.name == "user":
# Show only users created by the logged-in user
kwargs["queryset"] = User.objects.filter(
created_by=request.user)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
admin.site.register(Project, ProjectAdmin)
Explanation
- For Superusers: The
user
ForeignKey field will exclude other superusers. This ensures that superusers can’t select other superusers in forms.
2. For Regular Users:
- Company Field: If the user is an owner, they’ll see only the companies they’re associated with. Otherwise, they’ll see only the company specified in their preferences.
- User Field: Regular users will only see users they created
By using formfield_for_foreignkey
in this way, you can make your Django Admin forms more relevant and user-friendly, ensuring that users only see choices that are appropriate for their role and context.
By using formfield_for_foreignkey
in this way, you can make your Django Admin forms more relevant and user-friendly, ensuring that users only see choices that are appropriate for their role and context.