J'apprécierais que quelqu'un me montre comment faire une simple demande POST en utilisant JSON avec Django REST. Je ne vois pas des exemples de cela dans le tutoriel n'importe où?
Voici mon objet de modèle de rôle que j'aimerais poster. Ce sera un tout nouveau rôle que je voudrais ajouter à la base de données mais je reçois une erreur 500.
{
"name": "Manager",
"description": "someone who manages"
}
Voici ma demande curl sur une invite de terminal bash:
curl -X POST -H "Content-Type: application/json" -d '[
{
"name": "Manager",
"description": "someone who manages"
}]'
http://localhost:8000/lakesShoreProperties/role
L'URL
http://localhost:8000/lakesShoreProperties/roles
Travaille avec une requête GET, et je peux extraire tous les rôles de la base de données, mais je n'arrive pas à créer de nouveaux rôles. Je n'ai pas d'autorisations définies. J'utilise une vue standard dans 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
Et dans mon urls.py
pour cette application, les URL correspondantes - les mappages de vue sont correctes:
url(r'^roles/$', views.RoleList.as_view()),
url(r'^role/(?P<pk>[0-9]+)/$', views.RoleDetail.as_view()),
Le message d'erreur est:
{
"detail": "CSRF Failed: CSRF token missing or incorrect."
}
Qu'est-ce qui se passe ici et quelle est la solution pour cela? Localhost est-il une demande intersite? J'ai ajouté @csrf_exempt
à RoleDetail
et RoleList
mais cela ne semble rien changer. Ce décorateur peut-il même être ajouté à une classe ou doit-il être ajouté à une méthode? Ajout du @csrf_exempt
décorer, mon erreur devient:
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'
Ensuite, j'ai désactivé CSRF dans l’ensemble de l’application, et j’obtiens le message suivant:
{"non_field_errors": ["Données non valides"]} lorsque mon objet JSON que je connais est un json valide. C'est une erreur hors champ, mais je suis coincé ici.
Eh bien, il s'avère que mon code secret n'était pas valide?
{
"name": "admin",
"description": "someone who administrates"
}
contre
[
{
"name": "admin",
"description": "someone who administrates"
}
]
Le fait d'avoir entre crochets [] entraîne l'échec de la demande POST. Mais l'utilisation du validateur jsonlint.com valide les deux objets json.
Update : Le problème était l'envoi du POST avec PostMan, pas dans le backend. Voir https : //stackoverflow.com/a/17508420/203312
Vous devrez probablement envoyer le jeton CSRF avec votre demande. Départ https://docs.djangoproject.com/fr/1.7/ref/contrib/csrf/#csrf-ajax
Mise à jour: Puisque vous avez déjà essayé d'exempter CSRF, cela pourrait peut-être vous aider (selon la version de Django que vous utilisez): https://stackoverflow.com/a/14379073/977931
CSRF est exempté par défaut dans Django REST Framework. Par conséquent, curl POST fonctionne correctement. L'appel de demande POSTMAN a renvoyé CSRF incorrect car POSTMAN a inclus un jeton CSRF s'il se trouve dans les cookies. Vous pouvez résoudre ce problème en nettoyant les cookies.
C'est à partir de votre REST Paramètres du framework. Dans votre settings.py
fichier, votre REST_FRAMEWORK
devrait avoir ce qui suit.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
}
Ceci définira votre structure REST) pour utiliser l'authentification par jeton au lieu de l'authentification csrf. Et en définissant l'autorisation sur AllowAny
, vous pouvez vous authentifier uniquement à l'endroit souhaité.
OK, bien évidemment, je retire ce que j'ai dit. CSRF fonctionne comme prévu.
Je faisais une demande POST en utilisant un plugin chrome appelé POSTMAN. Ma demande POST échoue avec CSRF activé).
Mais une requête POST demande en utilisant
curl -X POST -H "Content-Type: application/json" -d '
{
"name": "Manager",
"description": "someone who manages"
}' http://127.0.0.1:8000/lakeshoreProperties/roles/
fonctionne bien ... Je devais enlever les accolades, c'est-à-dire [], et m'assurer qu'il y avait une barre oblique après le 's' dans les rôles, c'est-à-dire, roles /, et que csrf activé ne générait aucune erreur.
Je ne sais pas quelle est la différence entre appeler à l'aide de POSTMAN et utiliser à l'aide de curl, mais POSTMAN est exécuté dans le navigateur Web, ce qui est la plus grande différence. Cela dit, j'ai désactivé csrf pour toute la classe RoleList, mais une requête identique fonctionne avec Curl, mais échoue avec POSTMAN.
Pour faire le point sur l’état actuel et résumer quelques réponses:
Les requêtes AJAX effectuées dans le même contexte que l'API avec laquelle elles interagissent utilisent généralement
SessionAuthentication
. Cela garantit qu'une fois qu'un utilisateur est connecté, toutes les demandes effectuées par AJAX) peuvent être authentifiées à l'aide de la même authentification basée sur la session que celle utilisée pour le reste du site Web.Les requêtes AJAX effectuées sur un site différent de l'API avec laquelle elles communiquent doivent généralement utiliser un schéma d'authentification non basé sur une session, tel que
TokenAuthentication
.
Par conséquent, les réponses recommandant de remplacer SessionAuthentication
par TokenAuthentication
peuvent résoudre le problème, mais ne sont pas nécessairement tout à fait correctes.
Pour vous protéger contre ce type d'attaques, vous devez faire deux choses:
Assurez-vous que les opérations HTTP 'sûres', telles que
GET
,HEAD
etOPTIONS
ne peuvent pas être utilisées pour modifier un état côté serveur.Assurez-vous que toute opération HTTP 'non sécurisée', telle que
POST
,PUT
,PATCH
etDELETE
, nécessite toujours un jeton CSRF valide. Si vous utilisezSessionAuthentication
, vous devez inclure des jetons CSRF valides pour toute opérationPOST
,PUT
,PATCH
ouDELETE
. .Afin de faire des requêtes AJAX, vous devez inclure un jeton CSRF dans l'en-tête HTTP , comme décrit dans le = Django documentation.
Par conséquent, il est important que csrf soit inclus dans l'en-tête, comme par exemple cette réponse suggère.
Référence: Travailler avec AJAX, CSRF & CORS, Django REST) .
Comme vous l'avez dit, votre URL était
http://localhost:8000/lakesShoreProperties/roles
Postman a quelques problèmes avec localhost. Envoi du POST à 127.0.0.1:8000/your-api/endpoint
à la place a fait le tour pour moi.
si vous avez défini la permission AllowAny
et que vous êtes confronté au problème csrf
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny'
]
}
puis placer suit dans le settings.py
va résoudre le problème
REST_SESSION_LOGIN = False