Search code examples
djangoautocomplete-fields

Filter queryset for foreign key in Django autocomplete_fields



class InstitutionProfileAdmin(admin.ModelAdmin):
    def institute_pic_tag(self, obj):
        if obj.institute_pic:
            return format_html('<img src="{}" width="30x"/>'.format(obj.institute_pic.url))

    institute_pic_tag.short_description = 'Instituion Image'

    list_display = ["institute_name", "institute_location",
                    "institute_code", "institute_pic_tag", "owner_name", "owner_email", "active"]

    search_fields = ('user__username', 'institute_name', 'user__email',)
    list_filter = ['active']
    list_editable = ['active']
    autocomplete_fields = ['user']
    list_per_page = 20

    def owner_name(self, obj):
        return obj.user.username

    def owner_email(self, obj):
        return obj.user.email

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "user":
            kwargs["queryset"] = get_user_model().objects.filter(
                user_profile__user_type='1')
        return super().formfield_for_foreignkey(db_field, request, **kwargs)


admin.site.register(InstitutionProfile, InstitutionProfileAdmin)

Here if I do not use autocomplete_fields then the foreign key filtering in working but if I use autocomplete_fields it gives all the data

Without autocomplete_fields:

With autocomplete_fields:


Solution

  • Whenever you call autocomplete function the get_queryset() method of the other foreign key's Admin class get called and that's the reason why the search field is showing all the users because get_queryset() of the User model admin is called and it's returning all the objects of user model.

    However, when you try to save a Institution object with an invalid user(as you have mentioned in formfield_for_foreignkey() function) you will get a 'Select a valid choice. That choice is not one of the available choices.' message.

    Unfortunately you can't filter the foreign key objects from Institute model admin you have to do it from user model admin. you can override the get_search_results() method of User admin class but that's going to change the functionality of User Admin, which i believe not what you want.