Django Admin内联模型多选咨询:替换下拉框为表格复选框
Absolutely! You can swap out that default M2M dropdown in Django Admin inlines for a table with checkboxes—here are two reliable ways to pull this off, depending on whether you want full custom control or prefer leveraging existing patterns:
1. Custom Inline + Template Override (Most Flexible)
This approach lets you fully customize what data shows in the table and how it’s styled. Here’s how to implement it:
Step 1: Define the Inline in admin.py
We’ll use the many-to-many through model for the inline, which gives us control over the selection widget:
from django.contrib import admin from django.forms.widgets import CheckboxSelectMultiple from .models import ParentModel, ChildModel class ChildM2MInline(admin.TabularInline): # Target the through model of your M2M relationship model = ParentModel.children.through extra = 0 # Disable empty default rows template = "admin/custom_m2m_inline.html" # Our custom template def formfield_for_manytomany(self, db_field, request, **kwargs): # Override the widget for the related model field if db_field.name == "childmodel": kwargs["widget"] = CheckboxSelectMultiple return super().formfield_for_manytomany(db_field, request, **kwargs) class ParentModelAdmin(admin.ModelAdmin): inlines = [ChildM2MInline] exclude = ("children",) # Hide the default M2M field since we're using the inline admin.site.register(ParentModel, ParentModelAdmin) admin.site.register(ChildModel)
Step 2: Create the Custom Inline Template
Create templates/admin/custom_m2m_inline.html to render the checkboxes as a table. We’ll extend Django’s default tabular inline template and modify the field rendering:
{% extends "admin/edit_inline/tabular.html" %} {% block inline_fieldset %} {% for inline_admin_form in inline_admin_formset %} <tr class="{% cycle 'row1' 'row2' %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last %} empty-form{% endif %}"> {% for field in inline_admin_form %} {% if field.name == 'childmodel' %} <td colspan="{{ inline_admin_form.field_count }}"> <table class="m2m-checkbox-table" style="width:100%;border-collapse:collapse;"> {% for choice in field.field.widget.choices %} {% if not choice.0 == "" %} <!-- Skip empty choice --> <tr style="border-bottom:1px solid #eee;"> <td style="padding:8px;"><input type="checkbox" name="{{ field.html_name }}" value="{{ choice.0 }}" {% if choice.0 in field.value or choice.0|stringformat:"s" in field.value %}checked{% endif %}></td> <td style="padding:8px;">{{ choice.1 }}</td> <!-- Add extra fields from ChildModel here, e.g.: --> <td style="padding:8px;">{{ choice.1.description }}</td> </tr> {% endif %} {% endfor %} </table> </td> {% else %} <td>{{ field.field.errors.as_ul }}{{ field }}</td> {% endif %} {% endfor %} </tr> {% endfor %} {% endblock %}
Step 3 (Optional): Add Custom CSS
To polish the table, add this to your admin’s custom CSS (via ModelAdmin.media or a global admin CSS file):
.m2m-checkbox-table tr:hover { background-color: #f5f5f5; } .m2m-checkbox-table td { vertical-align: middle; }
2. Leverage Admin Extension Libraries
If you don’t want to build everything from scratch, some Django Admin extensions include pre-built table-style M2M selectors. These tools handle the widget rendering and styling out of the box, though you’ll have less control over customizing the table’s content compared to the first method.
Key Notes
- If your M2M relationship doesn’t use a custom through model, you can still apply similar logic by overriding the form widget for the M2M field in your inline and using a custom template to render it.
- The table approach makes it far easier for users to scan and select related objects, especially when you include additional context (like descriptions or statuses) alongside each checkbox.
内容的提问来源于stack exchange,提问作者HanSol

