pallets-eco / flask-admin

Simple and extensible administrative interface framework for Flask
https://flask-admin.readthedocs.io
BSD 3-Clause "New" or "Revised" License
5.75k stars 1.57k forks source link

Overriding fields in an inline model? #2088

Open jessesheidlower opened 3 years ago

jessesheidlower commented 3 years ago

I'm looking for guidance on how to override a form field in an inline model; this doesn't seem to be one of the places where it's easy to do.

I have a situation where I have a many-to-many field in an inline model, and the other side of the relationship has a few hundred thousand records, so I need to replace it with an AJAX lookup (as it's obviously impractical to have a select list with this many entries). You don't seem to be able to use form_ajax_refs here (and I'm not actually clear on how that works anyway), nor is there a template block I can override.

ljluestc commented 4 weeks ago
  1. Create a Custom Form: Create a custom form for your inline model where you override the field that requires the AJAX lookup.

  2. Override the Field Widget: In your custom form, override the widget for the many-to-many field to use AutocompleteSelect from Django’s admin widgets. This widget supports AJAX lookups out of the box.

  3. Update the Inline Model Admin: Use the custom form in your TabularInline or StackedInline in the admin.

Step-by-Step Code Example:

  1. Define Your Custom Form: Here, you create a custom form where the many_to_many_field uses the AutocompleteSelect widget.

    from django import forms
    from django.contrib.admin.widgets import AutocompleteSelect
    from .models import YourModel
    
    class YourModelForm(forms.ModelForm):
       class Meta:
           model = YourModel
           fields = '__all__'
           widgets = {
               'many_to_many_field': AutocompleteSelect(YourModel._meta.get_field('many_to_many_field').remote_field, admin.site),
           }
  2. Update Your Inline Admin: In your admin.py, use this custom form in your inline model admin.

    from django.contrib import admin
    from .models import YourParentModel, YourModel
    from .forms import YourModelForm
    
    class YourModelInline(admin.TabularInline):  # or admin.StackedInline
       model = YourModel
       form = YourModelForm
    
    @admin.register(YourParentModel)
    class YourParentModelAdmin(admin.ModelAdmin):
       inlines = [YourModelInline,]
  3. Enable AJAX Lookups: Ensure that the model field is registered for AJAX lookups in Django Admin.

    from django.contrib import admin
    from .models import YourModel
    
    @admin.register(YourModel)
    class YourModelAdmin(admin.ModelAdmin):
       search_fields = ['related_field_name']  # Field to search in the related model
       autocomplete_fields = ['many_to_many_field']