Using data from Foreign Key before final save of form.

Hey!

I’m having a model to create position per employee in the company (to remain history of the given employee’s positions):

class EmployeePosition(models.Model):
    position_date_from = models.DateField(blank=True, null=True)
    position_date_to = models.DateField(blank=True, null=True)
    is_current_position = models.BooleanField(default=True)
    employee_position = models.ForeignKey(Position, on_delete=models.DO_NOTHING)
    employee_name = models.ForeignKey('Employee', on_delete=models.DO_NOTHING, blank=True, null=True, related_name='position')

I have following form for the model:

class EmployeePositionForm(ModelForm):
    class Meta:
        model = EmployeePosition
        fields = ['position_date_from', 'position_date_to', 'is_current_position', 'employee_position', 'employee_name']

When saving the new position I’m trying to verify if the previous position wasn’t closed, before starting the new position.

def create_employee_position(request):
    employee_position_form = EmployeePositionForm(request.POST or None)
    position_date_from = PositionDateFromForm(request.POST or None)
    position_date_to = PositionDateToForm(request.POST or None)
    if request.method == "POST":
        if employee_position_form.is_valid() and position_date_from.is_valid() and position_date_to.is_valid():
            selected_date_from = position_date_from.cleaned_data['position_date_from']
            selected_date_to = position_date_to.cleaned_data['position_date_to']
            employee_position_form.save(commit=False)
            print(f"employee_position_form.employee_name: {employee_position_form.employee_name}")
            employee_position_form.position_date_from = selected_date_from
            employee_position_form.position_date_to = selected_date_to
            positions = EmployeePosition.objects.all()
            for position in positions:
                if position.employee_name == employee_position_form.employee_name:
                    if position.position_date_to.blank:
                        return render(request, 'error_position.html', {'position': position})
                    else:
                        if position.position_date_to < employee_position_form.position_date_from:
                            employee_position_form.save()
                        else:
                            return render(request, 'error_position_date.html',
                                          {'position': position, 'employee_position_form': employee_position_form})
                else:
                    employee_position_form.save()

            return redirect(list_employee_positions)
        else:
            print(f"employee_position_form.errors: {employee_position_form.errors}")
            print(f"position_date_from.errors: {position_date_from.errors}")
            print(f"position_date_to.errors: {position_date_to.errors}")
    context = {
        'employee_position_form': employee_position_form,
        'position_date_from': position_date_from,
        'position_date_to': position_date_to,
    }

    return render(request, 'create_employee_position.html', context)

Unfortunately I’m getting following error from Django:
'EmployeePositionForm' object has no attribute 'employee_name'

Apparently I do not understand some logic, or I’m missing something here. Why it says that attribute is not there while it is defined in the model and the form?

Thanks in advance for your support.

The error in this line

print(f"employee_position_form.employee_name: {employee_position_form.employee_name}")

Try to make

for field in employee_position_form:
   print('My_Form_Fields_And_Errors::', field.name, field.errors)

You will get all fields of your Form with errors if any

Also to use it as you described in your code

You have to do like this

if employee_position_form.is_valid():
     save_employee_position_form = employee_position_form.save(commit=False)
     save_employee_position_form.YOUR_FORM_FIELD = WHAT_YOU_WANT
     save_employee_position_form.save()
     # After saving Your_Form you can 
     save_employee_position_form.position_date_from = selected_date_from
     save_employee_position_form.position_date_to = selected_date_to

Hope it helps

The issue is that you’re trying to get a value from a bound field in a form - for that you need to use the cleaned_data attribute in the same way that you are using it to retrieve the values from the position_date_from and position_date_to forms.

Likewise, further down, when you do this:

that function call returns the instance of EmployeePosition being saved - it’s that object that you need to perform further work on, not the employee_position_form object.

Review the docs and examples at Creating forms from models | Django documentation | Django

Thank you very much!