worm2d
worm2d

Reputation: 159

Empty QueryDict in ajax POST query - Django

I use an ajax POST query with data: {'action':'add'} in Django template but if I print request.POST in views.py it shows in console <QueryDict: {}>.

But firebug shows POST 302 and action=add or action=remove parameters! So I cannot understand why is <QueryDict: {}> is empty. Please help.

PS. If I use GET it works fine.

template show_event.html:

<form id="unfollow" {% if user not in event.users.all %}style="display:none;"{% endif %}>
    <input type="hidden" value="{{ event.id }}" name="remove">
    <button type="submit" class="btn btn-warning btn-block">{% trans "Remove from My events"%}</button>
</form>

<form id="follow" {% if user in event.users.all %}style="display:none;"{% endif %}>
    <input type="hidden" value="{{ event.id }}" name="add">
    <button type="submit" class="btn btn-primary btn-block">{% trans "Add to My events"%}</button>
</form>

    $(document).on('submit','#unfollow', function(e){
        e.preventDefault();
        $.ajax({
            type:"POST",
            url:'/event/follow/{{ event.id }}/',
            data: {'action':'remove'},
            success:function(){
                $('#unfollow').hide();
                $('#follow').show();
            }
        })
    });

    $(document).on('submit','#follow', function(e){
        e.preventDefault();
        $.ajax({
            type:"POST",
            url:'/event/follow/{{ event.id }}/',
            data: {'action':'add'},
            success:function(){
                 $('#follow').hide();
                 $('#unfollow').show();
            }
        })
    });

views.py:

def follow (request, event_id):
    event = get_object_or_404(Event, id=event_id)
    user = request.user
    print request.POST
    if request.method == 'POST':
        print "post"
        if request.POST['action'] == 'add':
            print "add"
            event.users.add(user)
            event.save()
        elif request.POST['action'] == 'remove':
            print "remove"
            event.users.remove(user)
            event.save()
    return HttpResponse('')

urls.py:

url(r'^event/follow/(?P<event_id>[0-9]+)/$', 'events.views.follow', name='follow')

Upvotes: 1

Views: 1589

Answers (1)

Risadinha
Risadinha

Reputation: 16666

EDIT (2nd: fixing the form markup to match the URL):

Actually, as you have the form complete in your markup, there is a simpler way to do this:

var submitHandler = function(event) {
    event.preventDefault();
    event.stopPropagation();

    var $form = $(this);
    var url = $form.attr( "action" );
    $.post(url, $form.serialize())
        .done(function(data) {
            if (data.following) {
                $('#follow').hide();
                $('#unfollow').show();
            } else {
                $('#follow').show();
                $('#unfollow').hide();
            }
        });
};

$(document).on('submit','#unfollow', submitHandler);
$(document).on('submit','#follow', submitHandler);

Your markup should read:

<form id="unfollow" method="POST" action="{% url 'follow' event_id=event.id %}
      {% if user not in event.users.all %}style="display:none;"{% endif %}>
    {% csrf_token %}
    <input type="hidden" value="remove" name="action">
    <button type="submit" class="btn btn-warning btn-block">{% trans "Remove from My events"%}</button>
</form>

<form id="follow" method="POST" action="{% url 'follow' event_id=event.id %}
      {% if user in event.users.all %}style="display:none;"{% endif %}>
    {% csrf_token %}
    <input type="hidden" value="add" name="action">
    <button type="submit" class="btn btn-primary btn-block">{% trans "Add to My events"%}</button>
</form>

Your Django code:

@require_http_methods(['POST'])
def follow (request, event_id):
    event = get_object_or_404(Event, id=event_id)
    user = request.user
    action = request.POST.get('action', None)
    following = False
    if action == 'add':
        event.users.add(user)
        following = True
    elif action == 'remove':
        event.users.remove(user)
    else:
        return HttpResponseBadRequest('Unknown action: {}'.format(action))
    event.save()
    return JsonResponse({'following': following})

Previous answer:

Depending on your jQuery version, type might not be available anymore. Try using method: "POST" in the AJAX config instead of type: "POST". http://api.jquery.com/jQuery.ajax/

Also, to make your markup more aligned to what you expect in the view and JS, add method="POST" to your form element.


Side note:

You can handle non existing parameters better by accessing the QueryDict via get() method like this:

request.POST.get('action', None)

This will always work (unless request.POST is None). If the parameter is not present the default is returned or the second parameter (in this case None).

request.POST['action']

This will fail with a KeyError if action is not present.

Upvotes: 2

Related Questions