简体   繁体   中英

validate and submit Django form (django-crispy-forms) with Ajax

I'm very new at django and web development. I need help submitting Django form (using django-crispy-forms) with Ajax How do I:

  1. validate input

  2. submit without reloading

  3. display errors in case of validation failure

Right now i can submit the form and it saves the entries into the database but reloads the entire page in the process. i have included relevant snippets of my code below

// forms.py

class SubscriptionForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(SubscriptionForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.template_pack = 'bootstrap3'
        self.helper.form_tag        = True
        self.helper.form_id         = 'sub-form-1'
        self.helper.form_class      = 'form-inline'
        self.helper.field_template  = 'bootstrap3/inline_field.html'
        self.helper.layout          = Layout(

            Div(Div(css_class='sub-form-notifications-content'),
                css_class='sub-form-notifications'),

            InlineField('name',  id='subName'),
            InlineField('email', id='subEmail'),

            FormActions(Submit('submit', 'Notify me', css_class='form-control')),

    )

class Meta:
    model = Sub
    fields = "__all__"

def clean_email(self):
    """
   Validate that the supplied email address is unique for the
   site.

   """
    if User.objects.filter(email__iexact=self.cleaned_data['email']):
        raise forms.ValidationError(
            _("This email address is already in use. Please supply a different email address."))
    return self.cleaned_data['email']

// views.py

from django.shortcuts import render, redirect
from .forms import SubscriptionForm
from .models import Sub


def index(request):
    if request.method == 'POST':
        sub_form = SubscriptionForm(request.POST)
        if sub_form.is_valid():
            sub_form.save()
            # return redirect('landing:landing')

    else:
        sub_form = SubscriptionForm()
    return render(request, 'landing/index.html', {'sub-form': sub_form})

// template

...
         {% crispy sub-form %}
...

// rendered form HTML

<form class="form-inline" id="sub-form-1" method="post">
    <input type='hidden' name='csrfmiddlewaretoken'
           value='tdiucOssKfKHaF7k9FwTbgr6hbi1TwIsJyaozhTHFTKeGlphtzUbYcqf4Qtcetre'/>
    <div class="sub-form-notifications">
        <div class="sub-form-notifications-content">
        </div>
    </div>
    <div id="div_id_name" class="form-group">
        <label for="subName" class="sr-only requiredField">Name</label>
        <input type="text" name="name" maxlength="30" required placeholder="Name"
           class="textinput textInput form-control" id="subName"/>
    </div>
    <div id="div_id_email" class="form-group"><label for="subEmail" class="sr-only requiredField">Email address</label>
        <input type="email" name="email" maxlength="60" required placeholder="Email address"
           class="emailinput form-control" id="subEmail"/>
    </div>
    <div class="form-group">
        <div class="controls ">
            <input type="submit" name="submit" value="Notify me" class="btn btn-primary" id="submit-id-sub-form"/>
        </div>
    </div>
</form>

I'll try to give you an idea of how to do it easily.

Add the onsubmit event listener to the form and error-block eg bellow the form where errors will be displayed.

template

<form class="form-inline" id="sub-form-1" method="post" onsubmit="sendData();">
    ...
</form>
<div class="error-block">
    <!-- Here is the space for errors -->
</div>

now the handler which will send the data to the view to be validated and saved

<script>

    function sendData(e) {
        e.preventDefault(); // don not refresh the page

        var form_data = {
            name: $('input[name="name"]').val(),
            ... other field values ...
        }

        $.ajax({
            url: "{% url 'url-you-want-send-form-to' %}",
            method: "POST",
            data: form_data,
            success: function(response) {
                // here are the success data in the response
                // you can redirect the user or anything else
                //window.location.replace("{% url 'success-url' %}");
            },
            error: function(response) {
                // here are the errors which you can append to .error-block
                //$('.error-block').html(response);
            }
        })

    }

</script>

In the view you'll receive the data in the same form as the form would be submitted but you will not have to render whole template to the response, but only the erros from the validated form, so the view you will send your ajax POST request to will have to be different from the view which renders the form. You can create another which will handle it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM