Django CSRF check failing with an Ajax POST request

前端 未结 22 1879
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 03:46

I could use some help complying with Django\'s CSRF protection mechanism via my AJAX post. I\'ve followed the directions here:

http://docs.djangoproject.com/en/dev/r

22条回答
  •  感动是毒
    2020-11-22 03:47

    Easy ajax calls with Django

    (26.10.2020)
    This is in my opinion much cleaner and simpler than the correct answer.

    The view

    @login_required
    def some_view(request):
        """Returns a json response to an ajax call. (request.user is available in view)"""
        # Fetch the attributes from the request body
        data_attribute = request.GET.get('some_attribute')  # Make sure to use POST/GET correctly
        # DO SOMETHING...
        return JsonResponse(data={}, status=200)
    

    urls.py

    urlpatterns = [
        path('some-view-does-something/', views.some_view, name='doing-something'),
    ]
    

    The ajax call

    The ajax call is quite simple, but is sufficient for most cases. You can fetch some values and put them in the data object, then in the view depicted above you can fetch their values again via their names.

    You can find the csrftoken function in django's documentation. Basically just copy it and make sure it is rendered before your ajax call so that the csrftoken variable is defined.

    $.ajax({
        url: "{% url 'doing-something' %}",
        headers: {'X-CSRFToken': csrftoken},
        data: {'some_attribute': some_value},
        type: "GET",
        dataType: 'json',
        success: function (data) {
            if (data) {
                console.log(data);
                // call function to do something with data
                process_data_function(data);
            }
        }
    });
    

    Add HTML to current page with ajax

    This might be a bit off topic but I have rarely seen this used and it is a great way to minimize window relocations as well as manual html string creation in javascript.

    This is very similar to the one above but this time we are rendering html from the response without reloading the current window.

    If you intended to render some kind of html from the data you would receive as a response to the ajax call, it might be easier to send a HttpResponse back from the view instead of a JsonResponse. That allows you to create html easily which can then be inserted into an element.

    The view

    # The login required part is of course optional
    @login_required
    def create_some_html(request):
        """In this particular example we are filtering some model by a constraint sent in by 
        ajax and creating html to send back for those models who match the search"""
        # Fetch the attributes from the request body (sent in ajax data)
        search_input = request.GET.get('search_input')
    
        # Get some data that we want to render to the template
        if search_input:
            data = MyModel.objects.filter(name__contains=search_input) # Example
        else:
            data = []
    
        # Creating an html string using template and some data
        html_response = render_to_string('path/to/creation_template.html', context = {'models': data})
    
        return HttpResponse(html_response, status=200)
    

    The html creation template for view

    creation_template.html

    {% for model in models %}
       
  • {{ model.name }}
  • {% endfor %}

    urls.py

    urlpatterns = [
        path('get-html/', views.create_some_html, name='get-html'),
    ]
    

    The main template and ajax call

    This is the template where we want to add the data to. In this example in particular we have a search input and a button that sends the search input's value to the view. The view then sends a HttpResponse back displaying data matching the search that we can render inside an element.

    {% extends 'base.html' %}
    {% load static %}
    {% block content %}
        
        
        
    {% end block %} {% block extra_js %} {% endblock %}

提交回复
热议问题