Django 2.0中使用inlineformset_factory无法修改主模型部件的问题
Hey, I’ve run into this exact issue with inlineformset_factory in Django 2.0 before—trying to tweak the main model’s widgets but nothing seems to stick. Here are two solid solutions that worked for me:
1. Customize the Main Model Form and Pass It to the Formset
By default, inlineformset_factory uses the default ModelForm for your main model. The fix here is to create a custom form for your WorkOrder model where you define the widget changes, then pass that form to the formset factory.
Here’s how to do it:
from django import forms from django.forms import ModelForm from django.forms.models import inlineformset_factory from .models import WorkOrder, Customer # Custom form for WorkOrder with modified widgets class WorkOrderForm(ModelForm): class Meta: model = WorkOrder fields = ['work_order_number', 'work_order_date', 'description'] widgets = { # Replace the default date input with an HTML5 date picker 'work_order_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), # Switch description from CharField's text input to a textarea 'description': forms.Textarea(attrs={'rows': 4, 'cols': 60, 'placeholder': 'Enter work order details...'}), # Add any other widget customizations here } # Create the inline formset using your custom form WorkOrderInlineFormSet = inlineformset_factory( Customer, # Parent model (since WorkOrder has a ForeignKey to Customer) WorkOrder, # Child model form=WorkOrderForm, # Pass in your custom main model form fields=['work_order_number', 'work_order_date', 'description'], extra=1 # Number of empty forms to display )
This tells the formset to use your custom form, so all your widget changes will apply to the main model’s fields.
2. Dynamically Modify Widgets in the View
If you don’t want to create a separate custom form class, you can adjust the widgets directly in your view after initializing the formset.
Check out this example:
from django import forms from django.shortcuts import render, get_object_or_404 from django.forms.models import inlineformset_factory from .models import WorkOrder, Customer def manage_work_orders(request, customer_id): customer = get_object_or_404(Customer, id=customer_id) # Initialize the formset without a custom form WorkOrderInlineFormSet = inlineformset_factory( Customer, WorkOrder, fields=['work_order_number', 'work_order_date', 'description'], extra=1 ) if request.method == 'POST': formset = WorkOrderInlineFormSet(request.POST, instance=customer) if formset.is_valid(): formset.save() # Add your redirect logic here else: formset = WorkOrderInlineFormSet(instance=customer) # Dynamically update the widgets for the main model's fields formset.form.base_fields['work_order_date'].widget = forms.DateInput(attrs={'type': 'date'}) formset.form.base_fields['description'].widget = forms.Textarea(attrs={'rows': 4}) return render(request, 'work_orders/manage.html', {'formset': formset, 'customer': customer})
This approach is great for one-off widget tweaks where a full custom form feels overkill.
Quick Notes
- Make sure the fields you want to modify are included in the
fieldsparameter ofinlineformset_factory—if they’re missing, you’ll get an error when trying to access them inbase_fields. - Both methods work perfectly in Django 2.0 and are compatible with later versions too.
- If you need to modify widgets for the child model fields instead of the main one, you’d create a custom form for the child model and pass it via the
formparameter (same logic, just targeting the child model).
内容的提问来源于stack exchange,提问作者shaheen ashraf

