Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django temporary fields only upon creation

Consider two models:

Contract

class Contract(models.Model):
    employee = models.OneToOneField(Employee, on_delete=models.CASCADE)
    contract_type = models.ForeignKey(ContractType, on_delete=models.CASCADE)
    start_date = models.DateField()
    end_date = models.DateField()

and

Employee

class Employee(models.Model):

    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    contract = models.OneToOneField(Contract, on_delete=models.CASCADE, null=True, blank=True)

I was wondering if there's a way to add temporary fields in a model form that are only shown upon creation in the Employee model so I can add all those fields while I create a new Employee then when saving, I first create an Employee object, then automatically generate a Contract object and edit the original Employee object and link the now generated Contract object.

I really hope this makes sense, and if it does, can someone guide me in the right direction?

Thank you, for your time reading this.

like image 574
Rocky Cipher Avatar asked Mar 12 '26 14:03

Rocky Cipher


1 Answers

First of all, you here made two relations between Employee and Contract. Django automatically makes a relation in reverse, so you probably should remove one. Otherwise it is possible that some_contract.emplyee.contract is not the same as some_contract.

You thus for example might want to re-model this to:

class Employee(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)

class Contract(models.Model):
    employee = models.OneToOneField(Employee, on_delete=models.CASCADE, related_name='contract')
    contract_type = models.ForeignKey(ContractType, on_delete=models.CASCADE)
    start_date = models.DateField()
    end_date = models.DateField()

You can just create two ModelForms:

# app/forms.py

from app.models import Employee, Contract

class EmployeeForm(ModelForm):
    class Meta:
        model = Employee
        exclude = ['contract']

class ContractForm(ModelForm):
    class Meta:
        model = Contract

Then we can render the two forms:

# app/views.py

from django.shortcuts import redirect, render
from app.forms import EmployeeForm, ContractForm

def some_view(request):
    if request.method == 'POST':
        employee_form = EmployeeForm(request.POST)
        contract_form = ContractForm(request.POST)
        if employee_form.is_valid() and contract_form.is_valid():
            employee = employee_form.save()
            contract_form.instance.employee = employee
            contract_form.save()
            return redirect('some-view')
    else:
        employee_form = EmployeeForm()
        contract_form = ContractForm()
    return render(
        request,
        'some_template.html',
        {'employee_form': employee_form, 'contract_form': contract_form}
    )

in the template, we then render the two forms in the same <form> tag:

<!-- some_template.html -->
<form method="post">
    {% csrf_token %}
    {{ employee_form }}
    {{ contract_form }}
    <button type="submit">submit</button>
</form>
like image 118
Willem Van Onsem Avatar answered Mar 15 '26 17:03

Willem Van Onsem



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!