简体   繁体   English

使用 Django Rest Framework 的 Ajax POST 请求上的 400(错误请求)

[英]400 (Bad Request) on an Ajax POST request using Django Rest Framework

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.我正在尝试使用 Django Rest Framework Class 通过 AJAX 执行 POST 请求。 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.我试图做到这一点,当用户单击“添加到列表”按钮时,它会向用户定义的列表发送一个 cafeName(以及最终的其他详细信息)。

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这是相关的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.最后,这里是包含 CSRF 代码的 ajax 调用。

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?我不确定这是 Ajax 中的错误还是我的视图中的错误?

Thanks!谢谢!

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.我已经导入了 UserVenue 并试图命名类 UserVenue 这导致了整体问题。

Renamed to views.py class to UserVenueViewset fixed it.重命名为 views.py 类到 UserVenueViewset 修复了它。

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 文件中,您需要执行以下操作:

// 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:然后,在您的 views.py 中,您可以执行以下操作:

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当然,不要忘记将视图函数路由到 urls.py 中的 'add_to_list' url

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM