pythondjangomodelchoicefield

Django Question 'ModelChoiceField' object has no attribute 'use_required_attribute'


Dears, I met a problem in Django. There is an error about 'ModelChoiceField' object has no attribute 'use_required_attribute' and I don't know where I made mistake.

My goal is to make my submit customizing form but I couldn't understand how CBV in Django can reach this goal, so I went back to use forms.py and FBV in Django. But my fields in form model have foreign keys to refer other models. I used forms.ModelChoiceField and expected to solve foreign key problem but it doesn't work and show this error.

Thank you for reading and hope someone can help me to solve it.

Here are my code:

forms.py

    from django import forms
    from .models import Case
    from school_app.models import School
    from student_app.models import Student
    class CaseModelForm(forms.ModelForm):
    
        class Meta:
            model = Case
            fields='__all__'
            widgets = {
                'name' : forms.ModelChoiceField(queryset=Student.objects.all()),
                'phone' : forms.TextInput(),
                'school' :forms.ModelChoiceField(queryset=School.objects.all())
}

models.py

    from django.db import models
    from django.urls import reverse
    import datetime,time
    from school_app.models import School
    from student_app.models import Student
    # Create your models here.
    class Case(models.Model):
        name=models.ForeignKey(Student,related_name='case_student_name',on_delete=models.CASCADE,verbose_name="姓名")
        phone=models.CharField(verbose_name="電話",blank=False,max_length=256)
        school=school=models.ForeignKey(School,related_name='case_school',on_delete=models.CASCADE,verbose_name="學校")

views.py

def CaseFormView(request):
    print("CaseForm")
    form_cus = CaseModelForm()
    if request.method == "POST":
        form = CaseModelForm(request.POST)
        if form.is_valid():
            form.save()
        return redirect("/")

    context={
        'form_cus': form_cus
    }
    return render(request, 'case_app/case_form.html',context)

urls.py

from student_app import views
from django.urls import path
app_name = 'student_app'

urlpatterns=[
    path('', views.StudentListView.as_view(),name='list'),
    path('<int:pk>/', views.StudentDetailView.as_view(), name='detail'),
    path('create/',views.StudentCreateView.as_view(), name='create')]

case_form.html

<form method="post">
    {% csrf_token %}
    
    <div class="form-group">
        <div class="form-group col-md-6">
            <label>{{form_cus.name.label}}</label>

            {{form_cus.name}}
        </div>
        <div class="form-group col-md-6">
            <label>{{form_cus.school.label}}</label>

            {{form_cus.school}}
        </div>
        {{form_cus}}
    <input type="submit" class="btn btn-primary" value="提交"> 
       
    </div>
    {% if not form.instance.pk %}
    <a class='btn btn-secondary' href="{% url 'case_app:list' %}">取消</a>
    {% else %}
    <a class='btn btn-secondary' href="{% url 'case_app:detail' pk=form.instance.pk %}">取消</a>
    {% endif %}
</form>

Thank you!


Solution

  • A ModelChoiceField is not a widget, it is a form field, you thus can implement this as:

    from django import forms
    from .models import Case
    from school_app.models import School
    from student_app.models import Student
    
    class CaseModelForm(forms.ModelForm):
        school = forms.ModelChoiceField(queryset=School.objects.all())
        name = forms.ModelChoiceField(queryset=Student.objects.all())
    
        class Meta:
            model = Case
            fields='__all__'
            widgets = {
                'phone' : forms.TextInput(),    
            }

    Since school and name are however ForeignKeys in your Case model, you do not need to specify these: we can implement the CaseModelForm with:

    from django import forms
    from .models import Case
    from school_app.models import School
    from student_app.models import Student
    
    class CaseModelForm(forms.ModelForm):
        # no school/name field
        class Meta:
            model = Case
            fields='__all__'
            widgets = {
                'phone' : forms.TextInput(),    
            }