0
votes

Update 2: I've given up on axios, I'm sure there is a way and now am using ajax with a bit of code from https://www.webforefront.com/django/formadvancedprocessing.html

<script>
    $(document).ready(function () {
        $("#feedbackform").submit(function (event) {
            event.preventDefault();
            $.ajax({
                data: $(this).serialize(),
                type: $(this).attr('method'),
                url: $(this).attr('action'),
                success: function (response) {
                    console.log(response);
                    if (response['success']) {
                        $("#feedbackmessage").html("<div class='alert alert-success'>klasjflaksjf;lkajs;dflkajs;dkflj</div>");
                        $("#feedbackform").addClass("hidden");
                    }
                    if (response['error']) {
                        $("#feedbackmessage").html("<div class='alert alert-danger'>" +
                            response['error']['comment'] + "</div>");
                    }
                },
                error: function (request, status, error) {
                    console.log(request.responseText);
                }
            });
        });
    })
</script>

This is validating the form as usual, but I'm getting redirected to the action url even though I have

$("#feedbackform").submit(function (event) {
        event.preventDefault();

The view:

def error_checking(request):
    print('in error checking')
    if request.POST:
        form = RiderProfileFormSet(request.POST)
        print('made it')
        if form.is_valid():
            print('NOT')
            return JsonResponse({'success': True})
        else:
            print('YES')
            return JsonResponse({'error': form.errors})

Where am I going worng.

I still would like to learn hwo to do this in axios.

Update 1: I can get the form to the view as a string, but get stumped on how to ge the management form data to validate. Here are things I'm trying with no luck. one:

# request_data = json.loads(request.body)['form_to_validate']  # The form as html string
# Error: AttributeError: 'str' object has no attribute 'get'

two:

# request_data = json.load(request)  # The form as a dict {'form_to_validate': '<form id="reg_form" method.....}
#Error: ValidationError: ['ManagementForm data is missing or has been tampered with']

three:

# request_data = RiderProfileFormSet(request.POST)
#Error: ValidationError: ['ManagementForm data is missing or has been tampered with']



formset_post = RiderProfileFormSet(request_data)



if formset_post.is_valid():
    print('the formset is valid')

If I could figure out how to validate the form as a string or convert the string to whatever format would work with .is_valid().

Original: I have searched for a few hours with no luck. Also, I'm new to programming.

I am trying to perform form validation on a Django formset.

I have multiple dynamically added (javascript) forms on one page. When a user submits the form/s, if there are errors in the form the forms are over wirtten by the redirct back to the registration page. I'm trying to retain thier inputs.

My solution is to perform form validation via axios. My problem is that I'm getting django.core.exceptions.ValidationError: ['ManagementForm data is missing or has been tampered with']

Full traceback:

[19/Aug/2018 14:39:42] "GET /event-registration/?event=Lone%20Wolf HTTP/1.1" 200 13455 [19/Aug/2018 14:39:42] "GET /static/events/style.css HTTP/1.1" 200 340 [19/Aug/2018 14:39:42] "POST /event_formset HTTP/1.1" 200 7917 in error checking > Internal Server Error: /error_checking Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner response = get_response(request) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response response = self.process_exception_by_middleware(e, request) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/Users/shanecheek/Desktop/projects/lobos/events/views.py", line 164, in error_checking if formset_post.is_valid(): File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/forms/formsets.py", line 301, in is_valid self.errors File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/forms/formsets.py", line 281, in errors self.full_clean() File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/forms/formsets.py", line 322, in full_clean for i in range(0, self.total_form_count()): File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/forms/formsets.py", line 110, in total_form_count return min(self.management_form.cleaned_data[TOTAL_FORM_COUNT], self.absolute_max) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/functional.py", line 37, in get res = instance.dict[self.name] = self.func(instance) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/forms/formsets.py", line 92, in management_form code='missing_management_form', django.core.exceptions.ValidationError: ['ManagementForm data is missing or has been tampered with']

On a normal submit I don't have this issue. But, when I call the vue method:

reveal_pay: function (request) {
let app = this
console.log('called the reveal_pay')
axios.post("{% url 'error_checking' %}",
    {
        headers:
            {
                'X-CSRFToken': '{{ csrf_token }}',
            }
    }
)

    .then(function (response) {
        app.formIsValid = response.data.errors
    })},

I think the reason is that I'm not submitting the form properly, not passing the right data to the function:

def error_checking(request):
    print('in error checking')
    print(request.POST.get)
    formset_post = RiderProfileFormSet(request.POST)
    # formset_post = json.loads(request.body)['form_to_validate']
    print(formset_post)

    if formset_post.is_valid():
        print('the formset is valid')
        print('passing to event_register')
        event_register(request)
    else:
        print('formset not valid')
        print(formset_post.errors)
        errors = formset_post.errors
        args = {'errors': errors}
        return JsonResponse(args)

I tried getting the form via js (form_to_validate = document.getElementById('reg_form')) and passing that in the body, but when I try to use that as the formset, I get the error: AttributeError: 'str' object has no attribute 'errors'

[19/Aug/2018 15:31:02] "GET /event-registration/?event=Lone%20Wolf HTTP/1.1" 200 13464 [19/Aug/2018 15:31:02] "GET /static/events/style.css HTTP/1.1" 200 340 [19/Aug/2018 15:31:02] "POST /event_formset HTTP/1.1" 200 7917 in error checking > form_to_validate Internal Server Error: /error_checking Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner response = get_response(request) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response response = self.process_exception_by_middleware(e, request) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/Users/shanecheek/Desktop/projects/lobos/events/views.py", line 171, in error_checking errors = formset_post.errors AttributeError: 'str' object has no attribute 'errors'

The template:

<form id='reg_form' class="form-horizontal" method="POST">
    {% csrf_token %}
    {{ formset.management_form }}
    <div style="background-color: black; padding: 20px 60px 20px 60px; margin-right: 15px;"
         class="row form-row">
        <div class="input-group">
            <div v-for="form in formList">
                <br>
                <div style="background-color: #ffe673; padding: 20px" v-html="form">
                </div>
            </div>
            <div style="padding-left: 60px; background-color: black">
                <p v-on:click="addForm" class="btn btn-primary btn-lg">Add Form</p>
                <p v-on:click="formID" class="btn btn-primary btn-lg">Delete Form</p>
                <p v-on:click="totalCost" class="btn btn-primary btn-lg">Total Cost</p>

            </div>

            <br>

            <br>
        </div>
    </div>
    <div style="margin: 0px 15px 100px -15px; padding: 0px 0px 60px 60px; background-color: black">
        {#<button id="form_submit_button" style="" type="submit" class="btn btn-primary btn-lg">Finish Registration</button>#}
        <div id="form_submit_button" v-on:click="reveal_pay"class="btn btn-primary btn-lg">AXIOS Finish Registration</div>
        <div class="btn btn-primary btn-lg">
            <paypal-checkout
                    :amount='amountStr'
                    currency="USD"
                    :button-style="aStyle"
                    :client="paypal"
                    env="sandbox"
                    v-on:payment-authorized="paymentAuthorized"
                    v-on:payment-completed="paymentCompleted"
                    v-on:payment-cancelled="paymentCancelled">
            </paypal-checkout>
        </div>
    </div>
</form>

Let me know if there is other information you need. First time asking a question on here. -Thanks!

1

1 Answers

0
votes

So long story short. Django takes a JSON object and then you pass that to the modelformset object in the view. This is how I did it:

Form:

<form v-on:submit.prevent="the3DayMethod" method="POST" id="feedbackform">
    {% csrf_token %}
    {{ formset.management_form }}
    <div style="background-color: black; padding: 20px 60px 20px 60px; margin-right: 15px;"
         class="row form-row">
        <div class="input-group">
            <div v-for="form in formList">
                <br>
                <div style="background-color: #ffe673; padding: 20px" v-html="form">
                </div>
            </div>
            <div style="padding-left: 60px; background-color: black">
                <p v-on:click="addForm" class="btn btn-primary btn-lg">Add Form</p>
                <p v-on:click="formID" class="btn btn-primary btn-lg">Delete Form</p>
            </div>
            <br>
        </div>
    </div>
    <div style="margin: 0px 15px 100px -15px; padding: 0px 0px 60px 60px; background-color: black">
        <div v-show="formIsValid === 'False'">
            <input v-on:click="the3DayMethod" class="btn btn-primary" value=" Check for Errors">
        </div>
        <div v-show="formIsValid === 'True'" class="btn btn-primary btn-lg">
            <paypal-checkout
                    :amount='amountStr'
                    currency="USD"
                    :button-style="aStyle"
                    :client="paypal"
                    env="sandbox"
                    v-on:payment-authorized="paymentAuthorized"
                    v-on:payment-completed="paymentCompleted"
                    v-on:payment-cancelled="paymentCancelled">
            </paypal-checkout>
        </div>
    </div>
</form>

Vue Method / Axios:

the3DayMethod: function () {
    let app = this
    var object = {}
    forms = document.getElementById('feedbackform')

    var formData = new FormData(forms),
        result = {};
    for (var entry of formData.entries()) {
        result[entry[0]] = entry[1];
    }
    data = JSON.stringify(result)
    console.log(result);
    console.log('called the the3DayMethod')


    axios.post("{% url 'error_checking' %}",
        data,
        {
            headers:
                {
                    'X-CSRFToken': '{{ csrf_token }}',
                }
        }
    )
        .then(function (response) {
            app.formIsValid = response.data.errors
        })
},

Django View:

def error_checking(request):

    forms = json.load(request)

    formset = RiderProfileFormSet(forms)

    if formset.is_valid():
        print('VALID')
        v = {'success': "True"}
        return JsonResponse(v)
    else:
        print('NOT VALID')
        v = {'error': formset.errors}
        return JsonResponse(v)