skip to Main Content

I thought I’d ask this here as I’m not too sure where I am going wrong. I am trying to do a POST request via AJAX using Django Rest Framework Class. However, I am getting the following error whenever the event fires:

OST http://127.0.0.1:8000/api/uservenue/ 400 (Bad Request)

This is what is appearing in the Stack Trace:

{"list":["This field is required."],"venue":["This field is required."]}

Context

I am trying to make it so when a user clicks an "add-to-list" button it sends a cafeName (and eventually other details) to a user defined list.

I’m wondering if someone could take a look at my code and give me some guidance as to where I am going wrong?

The Code

Here is the relevant model:

class UserVenue(models.Model):
    venue = models.ForeignKey(mapCafes, on_delete=models.PROTECT)  
    list = models.ForeignKey(UserList, on_delete=models.PROTECT)
Here is the relevant serializer.py

class UserVenueSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserVenue
        fields = ['list', 'venue']

Here is the relevant URLs

router = DefaultRouter() #need help understanding router register
router.register('userlist', views.UserList)
router.register('uservenue', views.UserVenue)

Here is the relevant views.py

class UserVenue(viewsets.ModelViewSet):
    serializer_class = UserVenueSerializer
    queryset = UserVenue.objects.all()

    @ensure_csrf_cookie
    def get_queryset(self):
        cafeName = self.request.GET.get('cafeName', None)
        print(cafeName)

        return UserVenue.objects.all()

And, finally, here is the ajax call with the CSRF code incl.

var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  }


$.ajaxSetup({
    beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});


$.ajax({
  type: "POST",
   url : '/api/uservenue/',
   //dataType: "json", //I tried using this and commenting it out and it made no diff.
   //contentType: "application/json", //I tried using this and commenting it out and it made no diff.
   data: {
     'cafeName': cafeName,
     'list_id':  1,
     'csrfmiddlewaretoken': document.querySelector('input[name="csrfmiddlewaretoken"]').value,
   },

      success: function(data){
      //$("user-list").html(data);
      console.log('User clicked: ' +  data)

      },
      failure: function(errMsg) {
        alert(errMsg);
      }
    });

I’m not sure if this is an error in the Ajax or perhaps in my Views?

Thanks!

2

Answers


  1. Chosen as BEST ANSWER

    Turns out I was shadowing a variable. I had both imported UserVenue and was trying to name the class UserVenue this was causing the overall problem.

    Renamed to views.py class to UserVenueViewset fixed it.


  2. Let’s start with a simple pattern, we can go in depth where needed:

    First in your js file you’ll need to do something like this:

    // js function is executed when button is clicked:
    function add_to_list() {
            
        // execute ajax request:
        $.ajax({
            url : 'add_to_list',
            method : 'POST',
            data : {
                csrfmiddlewaretoken: 'the_csrf_token',
                cafe_name : 'the_cafe_name',
                ...
            },
            success: add_to_list_success,
        });
        
    } $('#button-id').click(add_to_list);
    
    
    // executes on successfully contacting backend:
    function add_to_list_success(response) {
        
        // unpack response (context variable from view function)
        data = response.data;        
      
        ...     
    }
    

    Then, in your views.py you can do something like this:

    from django.http import HttpResponse
    import json
    
    def add_to_list(request):
        
        # unpack POST data:
        cafe_name = request.POST['cafe_name']
        ...
        
        # conduct other logic:
        ...
        
        # pack context:
        context = json.dumps({
           'data' : 'some_data'
        })
        
        return HttpResponse(context)
        
    

    Of course, don’t forget to route the views function to the ‘add_to_list’ url in your urls.py

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search