How do you know exactly what causes the form not to be valid

Hey Mentors and Teachers, we appreciate having you, please help a young one here in this industry.
I recently had a similar issue with form submission and sure since I am a beginner this is one of my common challenges since I am still trying new ways, here I am using a model to save a form and also model form without having to use the form in the template

here is the model

class Order(models.Model):
    STATUS = (
        ('New', 'New'),
        ('Accepted', 'Accepted'),
        ('Completed', 'Completed'),
        ('Cancelled', 'Cancelled'),
    )

    user = models.ForeignKey(Account, on_delete=models.SET_NULL, null=True)
    payment = models.ForeignKey(Payment, on_delete=models.SET_NULL, blank=True, null=True)
    order_number = models.CharField(max_length=20)
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    phone = models.CharField(max_length=15)
    email = models.EmailField(max_length=50)
    address_line_1 = models.CharField(max_length=50)
    address_line_2 = models.CharField(max_length=50, blank=True)
    country = models.CharField(max_length=50)
    state = models.CharField(max_length=50)
    city = models.CharField(max_length=50)
    order_note = models.CharField(max_length=100, blank=True)
    order_total = models.FloatField()
    tax = models.FloatField()
    status = models.CharField(max_length=10, choices=STATUS, default='New')
    ip = models.CharField(blank=True, max_length=20)
    is_ordered = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


    def full_name(self):
        return f'{self.first_name}'

and here is a view that is am using:

def place_order(request, total=0, quantity=0,):
    current_user = request.user

    # If the cart count is less than or equal to 0, then redirect back to shop
    cart_items = CartItem.objects.filter(user=current_user)
    cart_count = cart_items.count()
    if cart_count <= 0:
        return redirect('store')

    grand_total = 0
    tax = 0
    for cart_item in cart_items:
        total += (cart_item.product.price * cart_item.quantity)
        quantity += cart_item.quantity
    tax = (2 * total)/100
    grand_total = total + tax

    if request.method == 'POST':
        form = OrderForm(request.POST)
        if form.is_valid():
            # Store all the billing information inside Order table
            data = Order()
            data.user = current_user
            data.first_name = form.cleaned_data['first_name']
            data.last_name = form.cleaned_data['last_name']
            data.phone = form.cleaned_data['phone']
            data.email = form.cleaned_data['email']
            data.address_line_1 = form.cleaned_data['address_line_1']
            data.address_line_2 = form.cleaned_data['address_line_2']
            data.country = form.cleaned_data['country']
            data.state = form.cleaned_data['state']
            data.city = form.cleaned_data['city']
            data.more_address_details = form.cleaned_data['more_address_details']
            data.order_note = form.cleaned_data['order_note']
            data.order_note = form.cleaned_data['order_note']
            data.order_total = grand_total
            data.tax = tax
            data.ip = request.META.get('REMOTE_ADDR')
            data.save()
            # Generate order number
            yr = int(datetime.date.today().strftime('%Y'))
            dt = int(datetime.date.today().strftime('%d'))
            mt = int(datetime.date.today().strftime('%m'))
            d = datetime.date(yr,mt,dt)
            current_date = d.strftime("%Y%m%d") #20210305
            order_number = current_date + str(data.id)
            data.order_number = order_number
            data.save()

            order = Order.objects.get(user = current_user, is_ordered = False, order_number = order_number)
            context = {
                'order': order,
                'cart_items': cart_items,
                'total': total,
                'tax': tax,
                'grand_total': grand_total,
                
                }
            return render(request, 'orders/payments.html', {'context': context})
        else:
            return redirect('checkout')

            
    else:
        return redirect('store')

and here is what is in the template:

 <div class="card">
                    <div class="card-body">
                        <h4 class="card-title mb-4">Billing address </h4>
                        <form action="{% url 'place_order' %}" method="POST">
                            {% csrf_token %}
                            <div class="form-row">
                                <div class="col form-group">
                                    <label for="">First Name</label>
                                    <input type="text" name="first_name" class="form-control" required>
                                </div>
                                <div class="col form-group">
                                    <label for="">Last Name</label>
                                    <input type="text" name="first_name" class="form-control" required>
                                </div>
                            </div>
                            <div class="form-row">
                                <div class="col form-group">
                                    <label for="">Email</label>
                                    <input type="email" name="email" class="form-control" required>
                                </div>
                                <div class="col form-group">
                                    <label for="">Phone Number</label>
                                    <input type="text" name="phone" class="form-control" required>
                                </div>
                            </div>
                            <div class="form-row">
                                <div class="col form-group">
                                    <label for="">Address line 1</label>
                                    <input type="text" name="address_line_1" class="form-control" required>
                                </div>
                                <div class="col form-group">
                                    <label for="">Address line 1</label>
                                    <input type="text" name="address_line_1" class="form-control">
                                </div>
                            </div>

                            <div class="form-row">
                                <div class="col form-group">
                                    <label for="">City</label>
                                    <input type="text" name="city" class="form-control" required>
                                </div>
                                <div class="col form-group">
                                    <label for="">State</label>
                                    <input type="text" name="state" class="form-control">
                                </div>
                                <div class="col form-group">
                                    <label for="">Country</label>
                                    <input type="text" name="country" class="form-control" required>
                                </div>

                            </div>

                            <div class="form-row">
                                <label for="">More details about your location</label>
                                <textarea name="order_note" class="form-control" rows="2"></textarea>
                            </div>

                            {% if form.errors %}
                                <div class="alert alert-danger">
                                    Please correct the error{{ form.errors|pluralize }} below.
                                </div>
                            {% endif %}
                      
                            <div class="form-row">
                                <label for="">Oder Note</label>
                                <textarea name="order_note" class="form-control" rows="2"></textarea>
                            </div>
                    </div>
                </div> <!-- card.// -->
   <button type="submit" name="submit" class="btn btn-primary btn-block">Place Order</button>
</form>

Why are you creating so much extra work for yourself?

The forms exist to save you from having to write about 70% of the code you’ve provided here in your view and template.

If you’re going to use Django, it’s really in your best interest to learn how to use Django.

yes MR. Ken, i know for sure but when I used the form, I wasn’t able to style the form the way I wanted it, maybe its less knowledge, but the shortcut I found was using crispy forms which provide a way for styling each field independently, however with this method, I was able to do it, by the way, you have ever given me this counsel before and I know that it works amazingly but I couldn’t style the form in the template. for example, I liked to make my form landscape which I didn’t manage by form.as_p or with crispy

I am willing to accept the guidance that will help me solve that in your way as long as I am able to style my HTML form however I want it. however, i would love to continue with the solution that will help me on the path that I have already taken

Using Django forms in general, and Crispy in particular, you don’t necessarily need to style the form in the template.

Crispy (specifically, the Layout object in the Helper) allows you to specify the layout in the form itself. From our perspective, that’s one of the real benefits of Crispy.

when I tried crispy helper, the form disappeared I was only seeing the button, and the other time I tried it, the project worked perfectly on the local host but after deployment, it was throwing an error, just I don’t remember the exact error. Sir @KenWhitesell is there any way to make that I did work? I would choose to use another if that fails completely

Is anyone here to help?, by the way I was trying this cripsy again but since I had used django 3.1 it wasnt compatible …

If you’re still having errors with code that you’re working on, please post the code that you would like assistance with.

same error, it was never resolved, I tried cripsy but crispy only supports Django 3.2 and my project is on 3.1 which means I have to make that work

I think we’ve got a little bit of confusion associated with two distinct topics being discussed in this thread.

My original point dealing with your original post, is that you should be using a form for the bulk of the work you’re currently doing.

The conversation regarding crispy was a side-bar that you raised in your first response when you started talking about formatting the form.

So your root issue is related to using a form - that’s what you should be focusing on initially. Then after you have a working form, we can address the desired formatting.

how would i be able to add those in the form if I used the form seeing that they are dynamic, I opted for that it used to work easy that way :disappointed_relieved:
i really need help

I went back to the first post, and I’m not seeing what the specific issue is needing to be addressed. I see a number of things that might be contributing to a variety of issues, but no one thing stands out to me.

That’s why I started by suggesting you simplify this view by getting rid of all the stuff you don’t need. It’ll reduce the size and make this easier to comprehend.

So lets start with the fundamentals.

Convert your view and your template to use the form you’ve defined. Follow the fundamental pattern in the Working with forms along with reading the docs starting with the save() method through the green Note box in that section.

You’re creating a form and binding the post data to it, but are then ignoring it after that.

When you’re using a form, you don’t need to assign all those individual fields to your model. The form takes care of that for you, along with performing the appropriate validation and generation of error messages.

The key point here is that form.save() returns the object being saved. You can then make updates to that object, and save it. That’s the essence of the information in the green Note box in the save method docs.

other is that it jumps to

which shows the form has issues, I am going to try again to avoid saving with the model and see what happens. I wished it worked but let me try again

just found where the problem was, :smiling_face_with_tear:
the name instead of being “more_address_details” I had forgotten and left it as order note

Thanks for keeping us engaged, stay blessed