with framework example apiview django json post django-rest-framework

example - django rest framework with django 2



¿Cómo hacer un POST simple JSON usando Django REST Framework? CSRF token missing or incorrect (9)

Agradecería que alguien me mostrara cómo hacer una solicitud POST simple utilizando JSON con el marco Django REST. No veo ningún ejemplo de esto en el tutorial en ninguna parte?

Aquí está mi objeto de modelo de rol que me gustaría publicar. Este será un nuevo rol que me gustaría agregar a la base de datos pero obtengo un error de 500.

{ "name": "Manager", "description": "someone who manages" }

Aquí está mi solicitud de curl en un indicador de terminal de bash:

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

La URL

http://localhost:8000/lakesShoreProperties/roles

SÍ trabaja con una solicitud GET, y puedo desplegar todos los roles en la base de datos, pero parece que no puedo crear nuevos Roles. No tengo permisos establecidos Estoy usando una vista estándar en 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

Y en mi urls.py para esta aplicación, las asignaciones relevantes de url - view son correctas:

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

Mensaje de error es:

{ "detail": "CSRF Failed: CSRF token missing or incorrect." }

¿Qué está pasando aquí y cuál es la solución para esto? ¿Localhost es una solicitud cruzada? He agregado @csrf_exempt a RoleDetail y a RoleList pero no parece cambiar nada. ¿Se puede agregar este decorador a una clase o se debe agregar a un método? Al @csrf_exempt decorar @csrf_exempt , mi error se convierte en:

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''

Luego deshabilité CSRF a través de toda la aplicación, y ahora recibo este mensaje:

{"non_field_errors": ["Datos no válidos"]} cuando mi objeto JSON sé que es válido json. No es un error de campo, pero estoy atrapado aquí mismo.

Bueno, resulta que mi json no era válido?

{ "name": "admin", "description": "someone who administrates" }

vs

[ { "name": "admin", "description": "someone who administrates" } ]

Tener los corchetes adjuntos [] hace que la solicitud POST falle. Pero al usar el validador jsonlint.com, ambos de mis objetos json validan.

Actualización : El problema fue enviar el POST con PostMan, no en el back-end. Ver https://stackoverflow.com/a/17508420/203312


Bien, ahora, por supuesto, recupero lo que dije. CSRF funciona según lo previsto.

Estaba haciendo una solicitud POST usando un complemento de Chrome llamado POSTMAN. Mi solicitud POST falla con CSRF habilitado.

Pero una solicitud POST de curl usando

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

funciona bien ... Tuve que quitar los frenos, es decir, [], y asegurarme de que haya una barra después de los roles ''s'', es decir, roles /, y csrf habilitado no arrojó ningún error.

No estoy seguro de cuál es la diferencia entre llamar usando POSTMAN vs usar curl, pero POSTMAN se ejecuta en el navegador web, que es la mayor diferencia. Dicho esto, deshabilité csrf para toda la clase RoleList pero una solicitud idéntica funciona con Curl, pero falla con POSTMAN.


CSRF está exento por defecto en Django REST Framework. Por lo tanto, la solicitud POST de curl funciona bien. La llamada de solicitud POSTMAN devolvió CSRF incorrecto porque POSTMAN incluyó token csrf si se encuentra en Cookies. Puede resolver esto limpiando las cookies.


Como dijiste, tu URL era

http://localhost:8000/lakesShoreProperties/roles

El cartero tiene algunos problemas con localhost. En su lugar, enviar el POST a 127.0.0.1:8000/your-api/endpoint fue el truco para mí.


Es desde la configuración de tu marco REST. en su archivo settings.py , su REST_FRAMEWORK debe tener lo siguiente.

REST_FRAMEWORK = { ''DEFAULT_AUTHENTICATION_CLASSES'': ( ''rest_framework.authentication.TokenAuthentication'', ), ''DEFAULT_PERMISSION_CLASSES'': ( ''rest_framework.permissions.AllowAny'', ), }

Esto establecerá su Marco REST para usar la autenticación token en lugar de la autenticación csrf. Y al establecer el permiso para AllowAny , puede autenticarse solo donde lo desee.


Para dar una actualización sobre el estado actual y resumir algunas respuestas:

Las solicitudes de AJAX que se realicen dentro del mismo contexto que la API con la que interactúan normalmente usarán SessionAuthentication . Esto garantiza que una vez que un usuario haya iniciado sesión, cualquier solicitud AJAX realizada se puede autenticar utilizando la misma autenticación basada en sesión que se utiliza para el resto del sitio web.

Las solicitudes AJAX que se realizan en un sitio diferente de la API con la que se están comunicando normalmente necesitarán un esquema de autenticación no basado en sesiones, como TokenAuthentication .

Por lo tanto, las respuestas que recomiendan sustituir SessionAuthentication con TokenAuthentication pueden resolver el problema, pero no son necesariamente totalmente correctas.

Para protegerse contra este tipo de ataques, debe hacer dos cosas:

  1. Asegúrese de que las operaciones HTTP ''seguras'', como GET , HEAD y OPTIONS no puedan usarse para alterar ningún estado del lado del servidor.

  2. Asegúrese de que cualquier operación HTTP ''insegura'', como POST , PUT , PATCH y DELETE , siempre requiera un token CSRF válido. Si usa SessionAuthentication , deberá incluir tokens CSRF válidos para cualquier operación POST , PUT , PATCH o DELETE .

Para realizar solicitudes AJAX, debe incluir el token CSRF en el encabezado HTTP , como se describe en la documentación de Django.

Por lo tanto, es importante que csrf esté incluido en el encabezado, como por ejemplo sugiere esta respuesta .

Referencia: Trabajando con AJAX, CSRF y CORS, documentación del framework Django REST .



También puede desactivar el CSRF para crear su propio middleware:

class DisableCSRF(object): def process_request(self, request): setattr(request, ''_dont_enforce_csrf_checks'', True)

E incluya este middleware en su archivo settings.py en MIDDLEWARE_CLASSES.


el viejo Postman está teniendo un problema con los tokens csrf porque no funciona con las cookies.

Te sugiero que cambies a la nueva versión de postman , funciona con cookies y no volverás a enfrentar este problema.


si ha establecido permiso AllowAny y se enfrenta con el problema csrf

REST_FRAMEWORK = { ''DEFAULT_PERMISSION_CLASSES'': [ ''rest_framework.permissions.AllowAny'' ] }

a continuación, colocar siguiente en settings.py resolverá el problema

REST_SESSION_LOGIN = False