data inserted in email filed is not broadcasted properly to backend, request.is_ajax() returns false

I am following a tutorial about an ecommerce app.

The app is made with Django 4, and ajax is used in the frontend.

I am currently working on a contact page.

compiling the form and submiting should trigger a jquery-confirm popup displaying message “thank you a lot!”.

This is obtained not by simple javascript submit form button
, but via a custom ajax logic.

The problem is that, when I compile and submit the form, the form is validated, the javascript is loaded, but the email data is not transmitted properly (I get None), and in views.py, request.is_ajax() returns None.

This is what happens when I fill up all the form fields and click on submit:

backend:

contact_form.cleaned_data {'fullname': 'John Doe', 'email': None, 'content': 'uvyibuon'}
no ajax in this request: <WSGIRequest: POST '/contact/'>
[20/Nov/2023 16:21:15] "POST /contact/ HTTP/1.1" 200 16035

frontend:

Navigated to http://127.0.0.1:8000/contact/
contact/:255 readyyyy
contact/:261 before submit

Here are my files

mainapp_ecommerce/urls.py

urlpatterns = [
...
path('contact/', contact_page, name="contact"),
]

mainapp_ecommerce/views.py

from .forms import ContactForm

def contact_page(request):

    contact_form = ContactForm(request.POST or None)

    context = {
    "title":"Contact",
    "content":"Welcome to the contact page!",
    "form": contact_form,
    "brand":"new brand name",
    }

    if contact_form.is_valid():
        print("contact_form.cleaned_data", contact_form.cleaned_data)
        
        if request.is_ajax(): # asinchronous javascript and xml
            print("Ajax request")
        
            dict_for_jsonresponse = {
                "message": "thanks!!"
            }
            return JsonResponse(dict_for_jsonresponse)

        else:
            print("no ajax in this request:", request) 

    else:
         print("form not valid")    

    return render(request, "contact/view.html", context )

mainapp_ecommerce/forms.py

class ContactForm(forms.Form):
    # eredita dalla classe form di django

    fullname = forms.CharField(
        widget=forms.TextInput(
            attrs={
                "class": "form-control", 
                "placeholder":"Your full name", 
                "id":"form_full_name"
                }
        )
    )

    email = forms.EmailField(
        widget=forms.EmailInput(
            attrs={
                "class": "form-control", 
                "placeholder":"Your email", 
                }
        )
    )
    

    content = forms.CharField(
        widget=forms.Textarea(
            attrs={
                "class": "form-control", 
                "placeholder":"Your content goes here...", 
                }
        )
    )

    def clean_email(self):
        email = self.cleaned_data.get("email")
        if not "gmail.com" in email:
            raise forms.ValidationError("Email has to be gmail.com")

mainapp_ecommerce/middlewares.py

class AjaxMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        def is_ajax(self):
            return request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
        
        request.is_ajax = is_ajax.__get__(request)
        response = self.get_response(request)
        return response

settings.py

...
MIDDLEWARE = [
    'django.middleware.security.AjaxMiddleware',
...

templates/base.html

    {% load static %}
    <!doctype html>
    <html lang="en">
      <head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        

        <!-- <title>Base template</title> -->
        {% include 'base/css.html' %} <!-- questo inietta il codice di una pagina nel punto in cui รจ messo -->

      </head>



      <body>

        {% include 'base/navbar.html' with brand_name='eCommerce' %}
        <div class='container'>
          {% block content %}
          {% endblock %}
        </div>


      {% include 'base/js.html' %}


        <script>
          $(document).ready(function(){

            console.log("readyyyy")
            // contact form habdrler
            var contactForm = $("contact-form")
            var contactFormMethod = contactForm.attr("method")
            var contactFormEndpoint = contactForm.attr("action")  /* questo lo prende da dove ho scritto action nella view dei contatti */
            
            console.log("before submit")

            contactForm.submit(function(event){
              console.log("entro submit")
              event.preventDefault()  /* quest mi serve a prevenire che lancio il submit premendo invio */
              var contactFormData = contactForm.serialize()
              console.log("serializzazione ok")
              var thisForm = $(this)
              
              $.ajax({

                method: contactFormMethod,
                url: contactFormEndpoint,
                data: contactFormData,

                success: function(data){
                  thisForm[0].reset()  /* empty the form */
                  $.alert({
                    title: "success!",
                    content: "thank you a lot!",
                    theme: "modern",
                  })              
                }, /* success chiudo */

                error: function(error){
                  console.log(error)
                  $.alert({
                    title: "oops",
                    content: "an error occurred",
                    theme: "modern",
                  })
                }, /* chiudo error */

              }) /* chiudo ajax  */


            }) /* chuso contactofrm submint */

        


          })
        </script>



        </body>
    </html>

templates/contact/view.html

  {% extends "base.html" %}

  {% block content %}


  <!doctype html>
  <html lang="en">
    <head>
      <!-- Required meta tags -->
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

      <!-- Bootstrap CSS -->
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

      <title>Contact</title>

    </head>

    <body>

      <div class='text-center'>
        <h1>{{title}}</h1>
        <h3>we are working</h3>
      </div>



    <div class='container'>
    <div class='row'>
      <div class='col'>      

        <div class='col-sm-6 col-12 mx-auto'>  <!-- mx auto lo manda nel mezzo -->

          <p>{{ content }}</p>

          <!-- <div class='col-sm-6 col-12'>
          <form method='POST'>
            {% csrf_token %}
            <input type='text' class='form-control' placeholder="Name" name='fullname'>
            <input type='email' class='form-control' placeholder="Email" name='email'>
            <input type='content' class='form-control' placeholder="Your content..." name='content'>
            <button type='submit' class="btn btn-primary">Submit</button>
          </form> -->

          <form class='contact-form' method='POST' action='{% url "contact" %}'>  
            <!-- questo token url mi serve per usare jquery,per essere sicuri che lo mando nel posto giusto. l'url lo prendo dalle views -->
            <!--  il selector della classe lo uso x jquery -->
            {% csrf_token %}
            {{ form.as_p }}
            <br>
            <button type='submit' class="btn btn-primary">Submit</button>
          </form>

        </div>

      </div>

    </div>
    </div>

    <br><br>


      <!-- Optional JavaScript -->
      <!-- jQuery first, then Popper.js, then Bootstrap JS -->
      <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    </body>
  </html>


  {% endblock %}