Customizing ForeignKey Choices in Django Admin: Tailoring Forms Based on User Roles

The CodeCrafter
2 min readAug 31, 2024

--

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:

  1. Superusers see all users except other superusers.
  2. Regular users can only see companies associated with them.
  3. 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

  1. 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.

--

--

The CodeCrafter

Writer | Python | Software Engineer | Deep Learning | Natural Language Processing | Mentor | Machine Learning |