如何使用Django REST Framework制作POST简单JSON?CSRF令牌丢失或不正确

use*_*719 45 django post json django-rest-framework

非常感谢有人向我展示如何使用JSON与Django REST框架进行简单的POST请求.我在教程中没有看到任何这方面的例子吗?

这是我想要POST的我的角色模型对象.这将是一个全新的角色,我想添加到数据库,但我收到500错误.

{
    "name": "Manager", 
    "description": "someone who manages"
}
Run Code Online (Sandbox Code Playgroud)

这是我在bash终端提示符下的curl请求:

curl -X POST -H "Content-Type: application/json" -d '[
{
    "name": "Manager", 
    "description": "someone who manages"
}]'


http://localhost:8000/lakesShoreProperties/role
Run Code Online (Sandbox Code Playgroud)

网址

http://localhost:8000/lakesShoreProperties/roles
Run Code Online (Sandbox Code Playgroud)

是否可以使用GET请求,我可以删除数据库中的所有角色,但我似乎无法创建任何新角色.我没有权限设置.我在views.py中使用标准视图

class RoleDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Role.objects.all()
    serializer_class = RoleSerializer
    format = None

class RoleList(generics.ListCreateAPIView): 
        queryset = Role.objects.all()
        serializer_class = RoleSerializer
        format = None
Run Code Online (Sandbox Code Playgroud)

在我urls.py的这个应用程序中,相关的URL - 视图映射是正确的:

url(r'^roles/$', views.RoleList.as_view()),
url(r'^role/(?P<pk>[0-9]+)/$', views.RoleDetail.as_view()),
Run Code Online (Sandbox Code Playgroud)

错误信息是:

{
    "detail": "CSRF Failed: CSRF token missing or incorrect."
}
Run Code Online (Sandbox Code Playgroud)

这里发生了什么,这是什么解决方案?localhost是否是跨站点请求?我添加@csrf_exemptRoleDetail,RoleList但它似乎没有改变任何东西.这个装饰器甚至可以添加到类中,还是必须添加到方法中?添加@csrf_exempt装饰,我的错误变为:

Request Method: POST
Request URL:    http://127.0.0.1:8000/lakeshoreProperties/roles/
Django Version: 1.5.1
Exception Type: AttributeError
Exception Value:    
'function' object has no attribute 'as_view'
Run Code Online (Sandbox Code Playgroud)

然后我通过整个应用程序禁用了CSRF,现在我收到此消息:

{"non_field_errors":["无效数据"]}当我知道的JSON对象是有效的json时.这是一个非现场错误,但我被困在这里.

好吧,事实证明我的json无效?

{
    "name": "admin", 
    "description": "someone who administrates"
}
Run Code Online (Sandbox Code Playgroud)

VS

[
    {
        "name": "admin",
        "description": "someone who administrates"
    }
]
Run Code Online (Sandbox Code Playgroud)

使用括号[],会导致POST请求失败.但是使用jsonlint.com验证器,我的两个json对象都会验证.

更新:问题在于使用PostMan发送POST,而不是在后端发送.请参阅/sf/answers/1225589431/

Ter*_*Lam 34

在Django REST Framework中默认免除CSRF.因此,curl POST请求工作正常.POSTMAN请求调用返回CSRF不正确,因为POSTMAN包含csrf令牌(如果在Cookie中找到它).您可以通过清理Cookie来解决此问题.

  • 感谢邮递员的评论!这完全是饼干给我造成的:) (2认同)

小智 24

它来自您的REST Framework设置.在您的settings.py文件中,您REST_FRAMEWORK应该具有以下内容.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
   'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
    ),
}
Run Code Online (Sandbox Code Playgroud)

这将使您的REST Framework设置为使用令牌身份验证而不是csrf身份验证.通过设置权限AllowAny,您可以只在您想要的位置进行身份验证.


ste*_*iot 10

您可能需要使用您的请求发送CSRF令牌.查看https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#csrf-ajax

更新:因为您已经尝试过免除CSRF,这可能有所帮助(取决于您使用的Django版本):https://stackoverflow.com/a/14379073/977931


use*_*719 10

好吧,现在当然我收回我所说的话.CSRF确实按预期工作.

我正在使用名为POSTMAN的chrome插件发出POST请求.我的POST请求失败并启用了CSRF.

但是使用curl POST请求

curl -X POST -H "Content-Type: application/json" -d '
{
    "name": "Manager",
    "description": "someone who manages"
}' http://127.0.0.1:8000/lakeshoreProperties/roles/
Run Code Online (Sandbox Code Playgroud)

工作正常...我不得不取下大括号,即[],并确保角色中的's'后面有一个斜杠,即roles /,并且csrf启用时没有抛出任何错误.

我不确定使用POSTMAN调用vs使用curl之间有什么区别,但POSTMAN是在Web浏览器中运行的,这是最大的区别.也就是说,我为整个类RoleList禁用了csrf,但是一个相同的请求与Curl一起使用,但是使用POSTMAN失败了.