Django Forms - How can I update a form with a disabled required field?
I have a Django Model with one required field (shpid). I want to set this field to disabled when updating the form. Although the value of this field is shown and disabled when the template is first displayed I get a crispy-forms
error saying 'this field is required
' with the field showing empty when I try and update.
I'm using crispy-forms
and FormHelper
to style the page.
The relevant part of forms.py
is:
class UpdateShpForm(ModelForm):
class Meta:
model = Shipment
fields = '__all__'
widgets = {
"shpid": TextInput(attrs={'disabled':False,'style':'max-width:120px'}), <=== Note diabled attribute
"costs": TextInput(attrs={'style':'max-width:200px'}),
"coldate": DateInput(attrs={'type': 'date','style':'max-width:180px'}),
"deldate": DateInput(attrs={'type': 'date','style':'max-width:180px'}),
"sts_date": DateInput(attrs={'type': 'date','style':'max-width:180px'}),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['shpid'].label = "Shipment ID"
self.fields['awb'].label = "AWB"
self.fields['pod'].label = "POD"
self.fields['coldate'].label = "Collection Date"
self.fields['deldate'].label = "Delivery Date"
self.fields['recipient'].label = "Recipient"
self.fields['status'].label = "Status"
self.fields['sts_date'].label = "Status Date"
self.fields['costs'].label = "Costs"
self.helper = FormHelper()
self.helper.layout = Layout(
Row (
Column('shpid',css_class='form-group col-md-3 mb-0 pe-4'),
Column('status',css_class='form-group col-md-3 mb-0 ps-2 pe-2'),
Column('sts_date', css_class='form-group col-md-3 mb-0 ps-4'),
),
Row(
Column('awb',css_class='form-group col-md-6 mb-0 pe-4'),
Column('pod',css_class='form-group col-md-6 mb-0 pe-4'),
),
Row(
Column('coldate', css_class='form-group col-md-3 mb-0 pe-4'),
Column('deldate', css_class='form-group col-md-3 mb-0 ps-2 pe-2'),
Column('recipient', css_class='form-group col-md-3 mb-0'),
),
Field('costs'),
ButtonHolder(
Submit('submit', 'Update Shipment', css_class='ms-5 px-3 fw-bold'),
css_class='center'
)
)
self.helper.form_class = 'form-horizontal'
The relevant part of views.py
is:
def update_shipment(request,shpid,orderid):
if shpid == 'None':
### When called from a list this will be either 'None' or an existing shpid
add_shipment(request,orderid)
return render(request,'tracker/add_shipment.html', {'form':AddShpForm()})
else:
instance = Shipment.objects.get(shpid=shpid)
shp_form = UpdateShpForm(request.POST or None, instance=instance)
print('########## Checking for Validity ############')
if shp_form.is_valid():
print('======== Form is valid ===============')
shp_form.save()
orders = Order.objects.all()
messages.success(request,f'Shipment no: {shpid} has been updated')
return render(request,'tracker/list_orders.html',{'orders':orders})
else:
return render(request,'tracker/update_shipment.html', {'form':shp_form, 'shpid':instance})
Currently I disable the shpid
field with a (shpid) widget which works fine when the form is first displayed but gives an error when the form is saved, as crispy-forms
has decided that it is empty.
How can I make a required field disabled without it causing a problem when trying to save the form styled with crispy-forms
?
You can't disable a form input element (or "widget" here). I mean, you can but if you do it, it's value will be completely ignored. Instead, use readonly=True
. This way, the value will actually be sent when you submit the form.
See the readonly attribute's page on MDN.