Search code examples
djangodjango-formsmodelform

Pre populating a django form using Initial not working


I am trying to save a modelform by prepopulating 'template_name' field . As per django documentation and other threads it is clear that initial parameter should work but i just can't make it work for my code. I am getting the error that template_name field is empty. Any help on what am I missing and any other approach towards this will be great. Here is the code

models.py

class TemplateNameModel(models.Model):
    "Model to add the template name"
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    tna_template_name = models.CharField(verbose_name="Template name",max_length = 128, unique = True,
                                    null = False, blank = False, help_text="please enter name of the new tna template")
    description = models.CharField(verbose_name="template description", max_length = 256,
                                    null = True, blank = True, help_text ="Please enter the description(optional)")
    created_by = models.TextField(verbose_name="Template created by", max_length= 128,
                                    null = False, blank = False,help_text ="Please enter the name of creator")
    date_created = models.DateTimeField(auto_created= True, null = True, blank = True)
    is_active = models.BooleanField(verbose_name="Template status",null = False , blank= False)

    def __str__(self):
        return self.tna_template_name

class TnaTemplateModel(models.Model):
    id = models.AutoField(primary_key=True, editable=False)
    template_name = models.ForeignKey(TemplateNameModel, verbose_name="template name", null=False,
                                        blank=False, on_delete=models.CASCADE, help_text="Select the template")
    process_name = models.ForeignKey(ProcessModel, verbose_name="process name", null=False,
                                        blank=False, on_delete=models.CASCADE, help_text="Select the process")
    sequence = models.IntegerField(verbose_name="Process Sequence",null = False,blank = False)
    is_base = models.BooleanField()
    formula = models.IntegerField(verbose_name="Formula", null= True,blank = True)
    remarks = models.CharField(verbose_name="Process remarks", null= True, blank = True,max_length= 300)
    class Meta:
        unique_together = ["template_name", "process_name"]
    
    def __str__(self):
        return str(self.template_name)

forms.py

class ProcessModelformNew(forms.ModelForm):

    class Meta:
        model = TnaTemplateModel
        fields =('__all__')

views.py

def processcreatenew(request,pk):
    template_name = TemplateNameModel.objects.get(id=pk)
    if request.method == 'POST':
        form = ProcessModelformNew(request.POST)
        if form.is_valid():
            form.save()
    else:
        data = {'template_name': template_name}
        form = ProcessModelformNew(initial= data)
    return render (request,"tna/template_tna/baseprocessmodel_create.html",{'form':form})

Html template

<form role="form" method="POST" enctype="multipart/form-data">
                {% csrf_token %}
                <div class="card-body">
                    <div class="row">
                        <div class="col-md-6 col-sm-12">
                            <!-- text input -->
                            <div class="form-group">
                                {{form.process_name|as_crispy_field}}
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-6 col-sm-12">
                            <!-- text input -->
                            <div class="form-group">
                                {{form.sequence|as_crispy_field}}
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-6 col-sm-12">
                            <!-- text input -->
                            <div class="form-group">
                                {{form.is_base|as_crispy_field}}
                            </div>
                        </div>
                        <div class="col-md-6 col-sm-12">
                            <!-- text input -->
                            <div class="form-group">
                                {{form.formula|as_crispy_field}}
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-6 col-sm-12">
                            <!-- text input -->
                            <div class="form-group">
                                {{form.remarks|as_crispy_field}}
                            </div>
                        </div>
                    </div>
                    
                </div>
                <!-- /.card-body -->
                <div class="card-footer">
                    <button type="submit" class="btn btn-primary">Save</button>
                </div>
            </form>

Solution

  • You need to render the template_name field in your template so the selected value is passed in the POST data.

    {{ form.template_name }}
    

    I suspect you do not want to display the field, you should override it's widget with forms.HiddenInput so that it is not visible to the user

    class ProcessModelformNew(forms.ModelForm):
    
        class Meta:
            model = TnaTemplateModel
            fields = '__all__'
            widgets = {'template_name': forms.HiddenInput()}