CreateView disabled field not sending field data

Django can’t create item in the DB when I use CreateView with form_class. In the form_class I use disabled fields and initial data.
every time I submit the form, the data never created in DB.

then I tried to override post method in the class. the disabled field not send field data, altough the data already initiated

  • view.py
class CreateReport(CreateView):
    model = Letter
    form_class = LetterForm
    template_name_suffix="_create_form"
    success_url="/report/"
    def get_context_data(self,**kwargs):
        context = super().get_context_data(**kwargs)
        context=self.get_layout(context)
        return context

    def get_initial(self):
        return {"applicant": self.request.user}

    def get_layout(self,context):
        context['layout'] = Page.objects.get(layout__name="report").layout 
        items_pra=context['layout'].items.all()
        q=Q()
        items=[]
        for item in items_pra:
            q|=Q(id=item.source_id)
            table=apps.get_model(app_label='component',model_name=item.type)
            items.append(table.objects.get(q))
        context['items']=items
        return context
  • form.py
class LetterForm(ModelForm):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
    class Meta:
        model = Letter
        exclude=['departement_head','date_submitted','date_approved','status']
        widgets = {
            'applicant': Select(attrs={'disabled':True,'readonly':True}),
            'about': Textarea(attrs={'rows': 3,'class':'align-items-start d-flex '}),
            'research_begin': DateInput(attrs={'type':'date'}),
            'research_finish': DateInput(attrs={'type':'date'}),
        }
  • letter_create_form.html
{% block content %}
<div class="content ms-5 me-5" >
  <form style="margin-top:5rem" action="{% url 'create_report' %}" method="post">
    {% csrf_token %}
    {% for field in form %}
      <div class="row">
        <div class="col-2">
          <label for="{{ field.name.id_for_label }}">{{field.name|snake2title}}: </label>
        </div>
        <div class="col-5">
          {{ field}}
        </div>
      </div>
    {% endfor %}
    <input class='btn btn-outline-success mt-5 col-5' type="submit" value="Submit">
  </form>
</div>
{% endblock content %}
  • model.py
class Letter(models.Model):
    applicant=models.ForeignKey('auth.User',on_delete=models.CASCADE)
    supervisor=models.ForeignKey('Lecturer',on_delete=models.CASCADE,related_name='letter_supervisor')
    departement_head=models.ForeignKey('Lecturer',on_delete=models.CASCADE,related_name='letter_departemen_head',null=True)
    about=models.TextField()
    research_begin=models.DateField()
    research_finish=models.DateField()
    date_submitted=models.DateField(auto_now=True)
    date_approved=models.DateField(null=True)
    status=models.CharField(max_length=1,default='P',choices=[("P","On Progress"),("A","Approved")]) #Waiting, Aprroved

    def __str__(self):
        return self.applicant.username

class Lecturer(models.Model):
    name=models.CharField(max_length=255)
    sign=models.ImageField()
    def __str__(self):
        return self.name
  • request.POST after overriding post method to print the request object (applicant field not send the data)
Quit the server with CTRL-BREAK.
<QueryDict: {'csrfmiddlewaretoken': ['xxxx'], 'supervisor': ['1'], 'about': ['ffg'], 'research_begin': ['2022-08-23'], 'research_finish': ['2022-08-23']}>

How to send the data from disabled/readonly field in this case?

You don’t. By definition a disabled field is not submitted.

See HTML attribute: disabled - HTML: HyperText Markup Language | MDN
and Form fields | Django documentation | Django

On the widget, you can make it readonly as opposed to disabled.

that would be attrs={ 'readonly':True}

but I found that if you disable a particular field in the form initializer, you won’t have a problem with data not being sent because it’s not a HTML attribute in this case, it’s a Django Field datatype

It’s in the same link Ken posted (some way down the page):
https://docs.djangoproject.com/en/4.1/ref/forms/fields/#disabled

this is how you can make this work:

class LetterForm(ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        var = self.fields['applicant']
        var.disabled = True