1

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!

Ezra Lin
  • 87
  • 9

1 Answers1

2

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(),    
        }
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • The default widget for `ModelChoiceField` is `select`. Official docs here: https://docs.djangoproject.com/en/3.2/ref/forms/fields/#modelchoicefield – Stoobish May 08 '21 at 06:41
  • @Stoobish: yes, but here we are dealing with the form field, and the default form field for a `ForeignKey` is a `ModelChoiceField`. – Willem Van Onsem May 08 '21 at 06:42
  • @WillemVanOnsem yep, was just a FYI for him. – Stoobish May 08 '21 at 06:45
  • I learn a lot from you! I have found what mistake I made for three hours. By the way, could I use CBV to design custom form which I can do some actions for each input tag with javascript , not use {{ form.as_p}} to show all fields? – Ezra Lin May 08 '21 at 06:47
  • 1
    @EzraLin: you can render a form manually: https://docs.djangoproject.com/en/3.2/topics/forms/#rendering-fields-manually – Willem Van Onsem May 08 '21 at 06:54
  • @WillemVanOnsem Oh! Thanks for your helpful. I will read it and try to use it. Thank you again. These help me a lot. – Ezra Lin May 08 '21 at 06:59