Search code examples
pythondjangoforms

Add a select field on Django form without saving on database


I have a form that refers to a model into the database so, each time is filled and a user click SUBMIT, the form is saved on the database.

The form has a series of fields took directly from the Django Model. See below.

My problem is that, I want to add a new field, a select field, that have as option inside data I've processed from the backend via the home view and, when the form is submitted, it passes the data selected to the same view so I can elaborate from there. I don't want this field to be saved on the database with the form.save()

Is there a way to have this kind of "hybrid" form where part of the data/field are taken from the database and others are just added by me?

models.py

class Test(models.Model):
    testTitle = models.CharField(max_length=50, blank=False, null=False)
    testDescription = models.TextField()
    sequenzaTest = models.ForeignKey("SequenzaMovimento", null=True, on_delete=models.SET_NULL)
    numeroCicli = models.IntegerField(blank=False, null=False)
    dataInizio = models.DateTimeField(auto_now_add=True)
    dataFine = models.DateTimeField(blank=False, null=True)
    testFinito = models.BooleanField(default=False)
    testInPausa = models.BooleanField(default=False)
    dataUltimaPausa = models.DateTimeField(null=True, blank=True)
    workerID = models.CharField(max_length=200, blank=True, null=True)

    def __str__(self):
        return self.testTitle
    

class StartWorker(ModelForm):
    class Meta:
        model = Test
        fields = ('testTitle', 'testDescription', 'sequenzaTest', 'numeroCicli')

        widgets = {
            'testTitle': forms.TextInput(attrs={'class':'form-control'}),
            'testDescription': forms.Textarea(attrs={'class':'form-control'}),
            'sequenzaTest': forms.Select(attrs={'class':'form-control'}),
            'numeroCicli': forms.NumberInput(attrs={'class':'form-control'}),
        }

views.py

def home(request):
    if request.method == "POST":
        form = StartWorker(request.POST)
        if form.is_valid():
            form_info = form.save()
            print("ID oggetto creato", form_info.id)
            # print(form.cleaned_data['dataInizio'])
            print("Ultima data aggiunta", Test.objects.get(pk=form_info.id).dataInizio.isoformat("T","seconds"))
        return redirect("home")
    
    else:
        form = StartWorker()
        return render(
            request,
            'dashboard/index.html',
            {
                "form": form,
            }
        )

index.html

    <form method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit">
    </form>

Solution

  • Sure. Just add your other fields to the ModelForm and process them as required. You can use the form's __init__ to fix up the choices for your field.

    class StartWorker(ModelForm):
        somethingElse = forms.ChoiceField(required=True, choices=())
        class Meta:
            model = Test
            fields = ('testTitle', 'testDescription', 'sequenzaTest', 'numeroCicli')
    
        def __init__(self, **kwargs):
            something_choices = kwargs.pop("something_choices")
            super().__init__(**kwargs)
            self.fields["somethingElse"].choices = something_choices
    

    ...

    form = StartWorker(request.POST, something_choices=[('a', 'A'), ('b', 'B')])
    ...
    if form.is_valid():
       something = form.cleaned_data.pop("somethingElse")
       # do something...
       test_instance = form.save()
    

    (That Test.objects.get(pk=form_info.id) is unnecessary, by the way, you already get the Test instance from form.save().)