template form will not post

I’ve been looking at this for over an hour and can’t put my finger on the problem, so I thought it was time to have someone else take a look.

I have a model form that I am presenting through a template. The form seems to be setup properly, and the field that I need to enter/update renders correctly.

Stepping through the debugger up to the initial render, all looks good, and the template renders as expected.

However, when I click the [Submit] button nothing happens. I put a stop in the debugger and it never gets there. It’s as if for some reason, the submit button is being ignored.

Here is the model form setup.

class PayrollSingleCheckForm(ModelForm):
    class Meta:
        model = PayrollPaychecks
        fields = ['payroll_employee', 'check_amount', 'payment_type', 'deposit_complete', 'check_printed',
                  'check_number', 'payment_voided']

        widgets = {
            'check_number': forms.TextInput(attrs={'style': 'width: 200px;'}),
        }

    def __init__(self, *args, check_number=None, **kwargs):
        super().__init__()
        self.fields['payroll_employee'].widget.attrs['hidden'] = True
        self.fields['check_amount'].widget.attrs['hidden'] = True
        self.fields['payment_type'].widget.attrs['hidden'] = True
        self.fields['deposit_complete'].widget.attrs['hidden'] = True
        self.fields['check_printed'].widget.attrs['hidden'] = True
        self.fields['payment_voided'].widget.attrs['hidden'] = True

        if check_number:
            self.fields['check_number'].initial = check_number

Here is the view that renders the form, and that should accept the posted form:

def paycheck_single_check(request, pk):
    paycheck_entry = PayrollPaychecks.objects.get(pk=pk)
    payroll = paycheck_entry.payroll_employee.payroll
    employee = paycheck_entry.payroll_employee.employee
    check_setup = employee.department.check_setup
    if request.method == 'POST':
        form = PayrollSingleCheckForm(request.POST, instance=paycheck_entry)
        if form.is_valid():
            form.save()
            # Create a file-like buffer to receive PDF data.
            buffer = io.BytesIO()

            # Create the PDF object, using the buffer as its "file."
            pdf_check = canvas.Canvas(buffer, pagesize=LETTER, initialFontSize=12)
            pdf_check.setFont('Courier', 12)

            # Create the check
            paycheck_create(paycheck_entry.id, pdf_check)

            return redirect('payroll_register', pk=payroll.id)

    last_check_number = check_setup.last_check_number
    if not last_check_number:
        last_check_number = 999
    elif last_check_number == 0:
        last_check_number = 999
    last_check_number = last_check_number + 1
    check_position = 'Top'
    if check_setup.check_position == 'M':
        check_position = 'Middle'
    elif check_setup.check_position == 'B':
        check_position = 'Bottom'

    form = PayrollSingleCheckForm(instance=paycheck_entry, check_number=last_check_number)

    context = {
        'employee_name': f'{employee.last_name}, {employee.first_name}',
        'department': employee.department.name,
        'check_amount': paycheck_entry.check_amount,
        'check_type': check_setup.check_description,
        'check_position': check_position,
        'payroll_id': payroll.id,
        'pk': pk,
        'form': form,
    }
    return render(request, 'PayrollChecks\paycheck_single_check.html', context)

Here is the template:

{% extends 'main.html' %}

{% block title %}

    Single Check - {{ employee_name }}

{% endblock title %}

{% block content %}

     {% load static %}

    <div class="container rounded bg-white mt-5 mb-5">
        <div>&nbsp;</div>
        <div class="h5 text-white bg-secondary rounded-corners px-3 pt-1 pb-1">
            {{ employee_name }} - Create Paycheck
        </div>
        <div class="row py-3">
            <div class="col-md-12 border-right">
                <a href="{% url 'payroll_register' payroll_id %}">
                    <button class="btn btn-primary button-wide" type="button">To Payroll Register</button></a>
            </div>
        </div>
        <form class="form" method="POST">
            {% csrf_token %}
            <div class="row">
                <div class="col-md-4 border-right">
                    <div class="row">
                        <div class="col-md-4">&nbsp;</div>
                    </div>
                    <div class="row">
                        <div class="col-md-4">&nbsp;</div>
                    </div>
                    <div class="row mt-3">
                        <div class="col-md-8">
                            <div
                                    class="d-flex flex-column align-items-center text-center"
                            >
                                <img
                                        class="rounded"
                                        width="150px"
                                        height="100px"
                                        alt="Payroll Employees"
                                        src='{% static "images/handtruck_box_move.png" %}'
                                />
                            </div>
                        </div>
                    </div>
                </div>
                <div class="col-md-8 border-right ">
                    <div class="row">
                        <div class="col-md4">
                            <label for="Employee" class="form-label text-primary">Department</label>
                            <div class="form__field px-3">
                                {{ department }}
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md4">
                            <label for="EarningsType" class="form-label text-primary">Check Amount</label>
                            <div class="form__field px-3">
                                ${{ check_amount|floatformat:"2g" }}
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-4">
                            <label for="Hours" class="form-label text-primary">Check Type</label>
                            <div class="form__field px-3">
                                {{ check_type }}
                            </div>
                        </div>
                        <div class="col-md-4">
                            <label for="Rate" class="form-label text-primary">Check Postion</label>
                            <div class="form__field px-3">
                                {{ check_position }}
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-8">
                            <label for="Memo" class="form-label text-primary">Check Number</label>
                            <div class="form__field px-3">
                                {{ form.check_number }}
                            </div>
                        </div>
                    </div>
                    {# Hidden fields - required to save the set check number #}
                    {{ form.payroll_employee }}
                    {{ form.check_amount }}
                    {{ form.payment_type }}
                    {{ form.deposit_complete }}
                    {{ form.check_printed }}
                    {{ form.payment_voided }}

                    <div class="row mt-3 mb-3">
                        <div class="col-md-12">
                            &nbsp;
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-md-4 border-right"></div>
                <div class="col-md-8 border-right">
                    <button type="submit" class="btn btn-primary">Create Check</button>
                </div>
            </div>
            <div class="row mt-5"></div>
        </form>
    </div>


{% endblock content %}

I’m open to any suggestions on why this form will not submit. I have dozens of other forms setup very similar with no issues, so I must be overlooking something here, but I can’t put my finger on it.

Thanks in advance for any help you can provide. No doubt, this is something very simple that I am just missing!

Hmm normally having a button or input with type=”submit” somewhere in the form should do the trick. Maybe you have some unmatched start or end tags in the form - I’d check in devtools if the form is well-balanced and not in some quirk mode cutting off the button.

What is happening when the form is invalid? It looks like you’re losing the invalid form and always creating a new one. Also, the template doesn’t render form errors.

Thanks jerch, I’ll check on the unmatched tags. That’s a possibility as this was a copy/paste job to start this template.

Massover, the form is never submitted, so I’m not even getting to the point where I can validate it. I actually did have a div tag to show the errors, but I pulled it out to simplify the template that I posted here.

Thanks for the replies.

Okay, I checked for missing or invalid tags and found none, however, just to eliminate any questions about the template, I simplified it to…

{% extends 'main.html' %}

{#{% block title %}#}
{##}
{#    Single Check - {{ employee_name }}#}
{##}
{#{% endblock title %}#}

{% block content %}

     <form method="POST">
        {% csrf_token %}

        {{ form.as_p }}

        <button type="submit">Submit</button>

    </form>

{% endblock content %}

The submit still does not take place. This is really confusing as it’s a very basic form. Now I’m thinking it might be something in the view, but I’m not sure what, or it could possibly be in the model form.

Any other thoughts on this are welcome!

Thanks!

Yes this minimal version should have triggered a POST request. Do you see any attempt in the network tab in devtools or any error message in the console log?

Something is really wrong either with the markup, or some JS event handler blocks the bubbling of the submit action on the form. Also check in page headers, that there are not some weird CSP/CORS rules in place.

Any maybe try a different browser engine to rule out an issue from browser profile settings.

Maybe also try to set the mimetype and the action on the form explicitly.

Just saw, that you have all field widgets set to hidden. Is there a mandatory value among the fields, that gets not prepopulated? Maybe remove the hidden flags temporarily to see the form fields in action.

Does the browser console show anything? Any error messages?

Are you possibly loading any JavaScript that might be capturing that event?

Does the network tab of the developer tools show any attempt to issue that request?

So I removed the hidden fields then loaded the basic form. However, the only field that was populated was the check number, which I pass to during the form instantiation. It is not retrieving the proper instance.

In the PyCharm debugger I did notice something peculiar. I am getting what appears to be an exception related to the model.

FormSubmit_01

It is saying that the model PayrollPaychecks has no payroll_employee. However, here is the model definition.

class PayrollPaychecks(models.Model):
    payroll_employee = models.ForeignKey(PayrollEmployees, on_delete=models.CASCADE)
    check_amount = models.DecimalField(max_digits=12, decimal_places=3, null=False, blank=False, default=0)
    payment_type = models.CharField(max_length=1, choices=PAYROLL_PAYMENT_TYPES, default='A')
    deposit_complete = models.BooleanField(null=False, default=False)
    check_printed = models.BooleanField(null=False, default=False)
    check_number = models.IntegerField(null=False, blank=False, default=0)
    payment_voided = models.BooleanField(null=False, default=False)
    date_added = models.DateField(auto_now_add=True)
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    def __str__(self):
        return (f'{self.payroll_employee.employee.last_name}, {self.payroll_employee.employee.first_name} '
                f'{self.payroll_employee.payroll.check_date}')

As you can see, there is definitely a payroll_employee field that is a foreign key to the model PayrollEmployees.

Also, in the PyCharm debugger, after the instance is loaded I can see that it is properly loaded by the following code, and seen in the image below that from the debugger.

def paycheck_single_check(request, pk):
    paycheck_entry = PayrollPaychecks.objects.get(pk=pk)

You can see that the field payroll_employee points to the correct payroll_employee entry.

Here is the form setup that I am working with. The hidden declarations have all been commented out.

class PayrollSingleCheckForm(ModelForm):
    class Meta:
        model = PayrollPaychecks
        fields = ['payroll_employee', 'check_amount', 'payment_type', 'deposit_complete', 'check_printed',
                  'check_number', 'payment_voided']

        widgets = {
            'check_number': forms.TextInput(attrs={'style': 'width: 200px;'}),
        }

    def __init__(self, *args, check_number=None, **kwargs):
        super().__init__()
        # self.fields['payroll_employee'].widget.attrs['hidden'] = True
        # self.fields['check_amount'].widget.attrs['hidden'] = True
        # self.fields['payment_type'].widget.attrs['hidden'] = True
        # self.fields['deposit_complete'].widget.attrs['hidden'] = True
        # self.fields['check_printed'].widget.attrs['hidden'] = True
        # self.fields['payment_voided'].widget.attrs['hidden'] = True

        if check_number:
            self.fields['check_number'].initial = check_number

I did check the Network tab in the debugger and it does not show any errors.

I also tried running this through a different browser, but I get the same results.

Not sure what the issue is, but I think it’s getting the form to load the instance. The code looks correct to me, so I’m not sure what I am missing.

Okay, I have an update to this. I removed the following section from the form and it properly loaded the instance.

class PayrollSingleCheckForm(ModelForm):
    class Meta:
        model = PayrollPaychecks
        fields = ['payroll_employee', 'check_amount', 'payment_type', 'deposit_complete', 'check_printed',
                  'check_number', 'payment_voided']

        widgets = {
            'check_number': forms.TextInput(attrs={'style': 'width: 200px;'}),
        }

    # def __init__(self, *args, check_number=None, **kwargs):
    #     super().__init__()
    #     # self.fields['payroll_employee'].widget.attrs['hidden'] = True
    #     # self.fields['check_amount'].widget.attrs['hidden'] = True
    #     # self.fields['payment_type'].widget.attrs['hidden'] = True
    #     # self.fields['deposit_complete'].widget.attrs['hidden'] = True
    #     # self.fields['check_printed'].widget.attrs['hidden'] = True
    #     # self.fields['payment_voided'].widget.attrs['hidden'] = True
    #
    #     if check_number:
    #         self.fields['check_number'].initial = check_number

There must be something wrong in this code, so I’ll take a look at it, but let me know if you notice anything wrong.

Thanks for all of the replies!

Well you dont apply the arguments to the super call here, so the values are not applied to the form fields either.

Yes, thanks jerch, just noticed that after looking at it again.

    def __init__(self, *args, check_number=None, **kwargs):
        super().__init__(*args, **kwargs)

I don’t know why I didn’t see this before. PyCharm code completion left off the arguments!! It’s a great tool, but you definitely have to look at the code it generates!

It’s working now! Thanks again for all the replies.