Title: ordering modelchoicefield in django loses formatting
Tags: python;django
Question: I wanted to order a list in my form view, and found this post here:
How do I specify an order of values in drop-down list in a Django ModelForm?
So I edited my code and added the line specialty = forms.ModelChoiceField(queryset ='...')
So then I reload the form and the widget is all smoshed and funky looking.  I checked the html code and the specialties are indeed in the right order!  But it misses the widget definition lower adding the form-control class.  I am not sure why.  if I remove the line specialty = form.ModelChoiceField then everything looks great aside from the dropdown not being in the right order (alphabetical by name field)
Not sure why it is missing that widget definition and attaching the class form-control or the tabindex even.    Guessing the specialty = forms.ModelChoiceField is overriding it somehow?
class ProviderForm(forms.ModelForm):
specialty = forms.ModelChoiceField(queryset = Specialty.objects.order_by('name'))   #added this
def __init__(self, *args, **kwargs):
super(ProviderForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-md-6'
self.helper.field_class = 'col-md-6'
self.fields['ptan'].required = False
self.helper.layout = Layout(
Field('...'),
Field('specialty'),
FormActions(
Submit('save', 'Save'),
Button('cancel', 'Cancel'),
Button('terminate', 'Terminate', css_class=&quot;btn-danger&quot;),
),
class Meta:
model=Provider
fields = (
'...',
'specialty'
)
widgets = {
'specialty':Select(attrs={
'tabindex':'4',
'class':'form-control'
}),


Here is the accepted answer: This is explained in the documentation, inside a big note:
When you explicitly instantiate a form field like this, it is important to understand how ModelForm and regular Form are related.
ModelForm is a regular Form which can automatically generate certain fields. The fields that are automatically generated depend on the content of the Meta class and on which fields have already been defined declaratively. Basically, ModelForm will only generate fields that are missing from the form, or in other words, fields that weren’t defined declaratively.
Fields defined declaratively are left as-is, therefore any customizations made to Meta attributes such as widgets, labels, help_texts, or error_messages are ignored; these only apply to fields that are generated automatically.
So, just add the widget argument to your declarative field:
specialty = forms.ModelChoiceField(
queryset = Specialty.objects.order_by('name'),
widget = Select(attrs={
'tabindex':'4',
'class':'form-control'
})


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2021:00:04/30/21', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<python><django>', 'Title': 'ordering modelchoicefield in django loses formatting', 'ViewCount': 49, 'id': 67339575, 'user_AboutMe': 'Programmer and photographer, jack of all trades master of absolutely zilch!\r\n', 'user_AccountId': 129002.0, 'user_DisplayName': 'Codejoy', 'user_Reputation': 3528.0, 'user_Views': 653.0, 'user_id': 327258.0}}