Django - 在点击重定向后提交无效表单提交按钮

时间:2022-09-25 16:13:32

I have a django project in which i have a form in a div being loaded by ajax.

我有一个django项目,其中我有一个由ajax加载的div中的表单。

when I submit the form with empty fields it returns the form with the required fields shown.

当我提交带有空字段的表单时,它返回显示所需字段的表单。

when I hit submit again it redirects to the action of the form instead of reloading the form in the div and showing errors as it does the first time I submit.

当我再次点击提交时,它会重定向到表单的操作,而不是重新加载div中的表单并显示错误,就像我第一次提交时一样。

does anyone have any idea where the error might be occurring? I imagine somewhere in the ajax or view in my django project.

有没有人知道错误可能发生在哪里?我想象在我的django项目中的ajax或view中的某个地方。

here is what is returned by the second submit:

这是第二次提交返回的内容:

{"success": false, "form": "<head>\n\n</head>\n<body>\n<form action=\"/cookbook/createrecipe/\" method=\"POST\" name=\"recipeform\" id=\"createrecipeform\">\n\t<table>\n\t\t<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='c5ea952ee2144b377b375d91b0843c75' /></div>\n\t\t<tr><th><label for=\"id_name\">Name:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><input id=\"id_name\" type=\"text\" name=\"name\" maxlength=\"200\" /></td></tr>\n<tr><th><label for=\"id_author\">Author:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><input id=\"id_author\" type=\"text\" name=\"author\" maxlength=\"100\" /></td></tr>\n<tr><th><label for=\"id_picture\">Picture:</label></th><td><input type=\"file\" name=\"picture\" id=\"id_picture\" /></td></tr>\n<tr><th><label for=\"id_ingredients\">Ingredients:</label></th><td><ul class=\"errorlist\"><li>This field cannot be null.</li></ul><textarea id=\"id_ingredients\" rows=\"10\" cols=\"40\" name=\"ingredients\"></textarea></td></tr>\n<tr><th><label for=\"id_steps\">Steps:</label></th><td><ul class=\"errorlist\"><li>This field cannot be null.</li></ul><textarea id=\"id_steps\" rows=\"10\" cols=\"40\" name=\"steps\"></textarea></td></tr>\n<tr><th><label for=\"id_prep_time\">Prep time:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><input type=\"text\" name=\"prep_time\" id=\"id_prep_time\" /></td></tr>\n<tr><th><label for=\"id_type\">Type:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><select name=\"type\" id=\"id_type\">\n<option value=\"\" selected=\"selected\">---------</option>\n<option value=\"SW\">Sandwich</option>\n<option value=\"AP\">Appetizers</option>\n<option value=\"SD\">Sauces and Dressings</option>\n<option value=\"SS\">Soups and Salads</option>\n<option value=\"VG\">Vegetables</option>\n<option value=\"RG\">Rice, Grains and Beans</option>\n<option value=\"PA\">Pasta</option>\n<option value=\"BR\">Breakfast</option>\n<option value=\"MT\">Meat</option>\n<option value=\"SF\">Seafood</option>\n<option value=\"BP\">Bread and Pizza</option>\n<option value=\"DT\">Desserts</option>\n</select><input type=\"hidden\" name=\"reset_recipe\" id=\"id_reset_recipe\" /></td></tr>\n\t</table>\n\t<p><input type=\"submit\" value=\"Submit\"></p>\n</form>\n</body>"}

here is my ajax code:

这是我的ajax代码:

<script type="text/javascript"> 
$(document).ready(function(){
    var form = $('form#createrecipeform');
    form.submit(function(e) {
    e.preventDefault();
    console.log('ajax form submission function called successfully.');
    //form = $(this);
    console.log(form)
    var serialized_form = form.serialize();
        $.ajax({ type: "POST", 
            url: $(this).attr('action'),
            data: serialized_form, 
            success: (function(data) { 
                console.log('ajax success function called successfully.');
                data = $.parseJSON(data);
                if (data.success) {
                    console.log('success');
                } else {        
                    console.log('failure');
                    var newForm = data.form;
                    form.replaceWith(newForm);  
                }
            })
        });
        return false;
    });
});
</script> 

here is the view: (createrecipe is the action of the form and account is the page that is loading the ajax)

这里是视图:( createrecipe是表单的动作,帐号是加载ajax的页面)

def createrecipe(request):
        print "entering createrecipeview"
        if request.method == 'POST':
            print "form is a post"
            form = RecipeForm(request.POST)
            print form.errors
            if form.is_valid():
                print "form is valid"
                form = RecipeForm(initial = {'original_cookbook' : request.user.cookbooks.all()[0]})
                form = form.save()

                t = loader.get_template('cookbook/create_form.html')
                c = RequestContext(request, {
                'form': form,
                })

                data = {
                'replace': True,
                'form': t.render(c),
                'success': True,
                }

                json = simplejson.dumps(data)
                return HttpResponse(json, mimetype='text/plain')
            else:
                print "form is invalid"
                form = RecipeForm(request.POST)
                t = loader.get_template('cookbook/create_form.html')
                c = RequestContext(request, {
                    'form':form,
                })

                data ={
                    'form': t.render(c),
                    'success': False,
                }

                json = simplejson.dumps(data)
                return HttpResponse(json, mimetype='text/plain')

def account(request):
    user = request.user
    if request.user.is_authenticated():

        cookbooks = user.cookbooks
        if cookbooks.all().exists():
            cookbook = cookbooks.all()[0]
            form = RecipeForm(initial = {'original_cookbook' : request.user.cookbooks.all()[0]})
            recipe_list = cookbook.recipes.all()
        else:
            raise Http404
    else:
        return HttpResponseRedirect('/accounts/login')
    t = loader.get_template('cookbook/account.html')
    c = RequestContext(request, {
        'form': form,
        'recipe_list': recipe_list
    })
    return HttpResponse(t.render(c))

here is the create_form.html template:

这是create_form.html模板:

<head>

</head>
<body>
<form action="{% url cookbook.views.createrecipe %}" method="POST" name="recipeform" id="createrecipeform">
    <table>
        {% csrf_token %}
        {{ form.as_table }}
    </table>
    <p><input type="submit" value="Submit"></p>
</form>
</body>

and here is the account template that includes the create_form template:

这是包含create_form模板的帐户模板:

{% extends "cookbook/base.html" %}
{% load pagination_tags %}
{% load comments %}


    <h1>{{ user }}'s Cookbook</h1>

<ul>
{% block nav-cookbooks %}
<li><a class="nav-inactive" href="/cookbooks/">Cookbooks</a></li>
{% endblock %}
{% block nav-account %}
<li><a class="nav-active" href="/account/">My Cookbook</a></li>
{% endblock %}
</ul>
{% block content %}
{% autopaginate recipe_list 6 %}
    <div id="recipe_cont">
            {% for recipe in recipe_list %}
        <div class="recipe">
            <div class="button">    
            <a href="{% url cookbook.views.userrecipe recipe.id %}" style="display: none;"></a>   
            <img src="{{ STATIC_URL }}chicknbraw.jpg" alt="" height="70" width="70" style="display:inline;" />
            <h4>{{ recipe.name }}</h4>
             </div>
            <h5>{{ recipe.author }}</h5>
            <h5>Prep Time: {{ recipe.prep_time }} minutes</h5>

            <h6><a href="/addrecipe/{{ recipe.id }}">Add Recipe</a>
                <a href="/removerecipe/{{ recipe.id }}">Remove Recipe</a></h6>
        </div>
    {% endfor %}
    </div>

    <div id="popupContact" class="popup">
            <a id="popupContactClose" style="cursor:pointer;float:right;">x</a>
            <p id="contactArea">
            <h1 style="text-align:center">Create New Recipe</h1>
            {% include 'cookbook/create_form.html' %} 
            </p>
    </div>
    <div id="backgroundPopup">
    </div>  
    <div id="col2-footer">
    {% paginate %}
    <p id="recipe_order_text"> order by: <a href="/userbook/ordered/name">abc</a>|<a href="/userbook/ordered/date">date</a> 
    </div>

{% endblock %}

{% block footer %}
        <a class="create" style="cursor:pointer" >Create New Recipe</a>
{% endblock %}

sorry for putting so much code but it all seems to rely upon another piece of code so I figured all relevant code would be helpful

很抱歉放了这么多代码,但它似乎都依赖于另一段代码,所以我认为所有相关代码都会有所帮助

thanks for any help you can give me

感谢你给与我的帮助

katie

1 个解决方案

#1


0  

In your javascript, you're hijacking the form so that it submits via ajax, but then you're calling replaceWith on the form, so your hijacked form gets obliterated and is replaced with a new, non-hijacked form. To solve this you can either

在你的javascript中,你正在劫持表单以便它通过ajax提交,但是你在表单上调用replaceWith,所以你被劫持的表单被删除并被一个新的,未被劫持的表单替换。要解决这个问题,你也可以

1) Only replace the content of the form - this should work since you're only attaching events to the form itself and not its child elements

1)只替换表单的内容 - 这应该有效,因为您只是将事件附加到表单本身而不是其子元素

2) Write your js as a function which you can call firstly on the initial form, and subsequently on any new forms loaded via ajax.

2)将您的js编写为一个函数,您可以先在初始表单上调用,然后在通过ajax加载的任何新表单上调用。

UPDATE: for example,

更新:例如,

<script type="text/javascript"> 
$(document).ready(function(){

    function hijack() {
        var form = $('form#createrecipeform');
        form.submit(function(e) {
            e.preventDefault();
            console.log('ajax form submission function called successfully.');
            //form = $(this);
            console.log(form)
            var serialized_form = form.serialize();
            $.ajax({ type: "POST", 
                url: $(this).attr('action'),
                data: serialized_form, 
                success: (function(data) { 
                    console.log('ajax success function called successfully.');
                    data = $.parseJSON(data);
                    if (data.success) {
                        console.log('success');
                    } else {        
                        console.log('failure');
                        var newForm = data.form;
                        form.replaceWith(newForm);
                        hijack();
                    }
                })
            });
            return false;
        });
    };

    hijack();

});
</script> 

#1


0  

In your javascript, you're hijacking the form so that it submits via ajax, but then you're calling replaceWith on the form, so your hijacked form gets obliterated and is replaced with a new, non-hijacked form. To solve this you can either

在你的javascript中,你正在劫持表单以便它通过ajax提交,但是你在表单上调用replaceWith,所以你被劫持的表单被删除并被一个新的,未被劫持的表单替换。要解决这个问题,你也可以

1) Only replace the content of the form - this should work since you're only attaching events to the form itself and not its child elements

1)只替换表单的内容 - 这应该有效,因为您只是将事件附加到表单本身而不是其子元素

2) Write your js as a function which you can call firstly on the initial form, and subsequently on any new forms loaded via ajax.

2)将您的js编写为一个函数,您可以先在初始表单上调用,然后在通过ajax加载的任何新表单上调用。

UPDATE: for example,

更新:例如,

<script type="text/javascript"> 
$(document).ready(function(){

    function hijack() {
        var form = $('form#createrecipeform');
        form.submit(function(e) {
            e.preventDefault();
            console.log('ajax form submission function called successfully.');
            //form = $(this);
            console.log(form)
            var serialized_form = form.serialize();
            $.ajax({ type: "POST", 
                url: $(this).attr('action'),
                data: serialized_form, 
                success: (function(data) { 
                    console.log('ajax success function called successfully.');
                    data = $.parseJSON(data);
                    if (data.success) {
                        console.log('success');
                    } else {        
                        console.log('failure');
                        var newForm = data.form;
                        form.replaceWith(newForm);
                        hijack();
                    }
                })
            });
            return false;
        });
    };

    hijack();

});
</script>