Serialization en ajax avec Django et csrf vérification

Bonjour,
Je suis en train de m’intéresser à l’interaction ajax avec Django et j’avais besoin de faire des appels ajax pour avoir une application toute jolie. Pour cela, je passe par des jsons qui sont pour moi les objets les plus faciles à manipuler en javascript.

Mon cas est la création d’une messagerie interne entre utilisateur en ajax pour la frime 🙂 Je souhaitais que lorsqu’on répond à un message, notre réponse apparaisse automatiquement en dessous de la liste des messages. J’ai donc besoin pour ca que l’appel ajax qui sauvegarde la réponse me retourne un json avec toutes les informations du nouveau message.

Pour cela, j’ai donc créé un appel json tout simple avec jquery lorsqu’on poste notre réponse :

$.ajax({
  url: '{% url message_answer messagee.id %}',
  type: 'POST',
  dataType : 'json',
  data: $(this).serialize() ,
  success : function(data) {
  	//On success
        console.log(data);
  },
  error : function(data) {

  },
  beforeSend: function(xhr, settings) {
     function getCookie(name) {
         var cookieValue = null;
         if (document.cookie && document.cookie != '') {
             var cookies = document.cookie.split(';');
             for (var i = 0; i < cookies.length; i++) {
                 var cookie = jQuery.trim(cookies[i]);
                 // Does this cookie string begin with the name we want?
             if (cookie.substring(0, name.length + 1) == (name + '=')) {
                 cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                 break;
             }
         }
     }
     return cookieValue;
     }
     if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
         // Only send the token to relative URLs i.e. locally.
         xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
     }
 }
});

Cet appel ajax est donc déclenché au moment où on envoie notre réponse (quand on clique sur le bouton submit), il prend comme paramètres toutes les variables de mon formulaire pour avoir le POST complet.

Il ne reste plus qu’à sauver la nouvelle réponse au niveau de la vue et de retourner le message qui a été sauvé sous forme de json :

from django.http import HttpResponseRedirect, HttpResponse
from django.core import serializers

@login_required
def answer(request, message_id):
    if request.method == "POST":
        form = NewForm(request.POST, request.FILES) # A form bound to the POST data
        if form.is_valid():
            message = get_object_or_404(Message, id=message_id)
            #On s'assure que l'utilisateur qui poste le message fait bien partie de la conversation
            if (message.isInConversation(request.user)):
                #On crée le nouveau message avec toutes les données nécessaires
                newMessage = Message.objects.create(userFrom = request.user, userTo = message.getOtherUser(request.user), message = request.POST['message'], status = message.STATUS_ANSWER, title = message.title, parentMessage=message.id)
                data=serializers.serialize("json", [newMessage], indent=4, relations=('userTo','userFrom') )
                return HttpResponse(data, mimetype="application/json")
            else :
                callback = { 'result' : False, 'error': 'Vous ne pouvez répondre à ce message' }
                return HttpResponse(simplejson.dumps(callback), mimetype="application/json")
        else:
            return HttpResponse(simplejson.dumps(form.errors), mimetype="application/json")
    return True

La partie qui nous intéresse sont les lignes en gras :

data=serializers.serialize("json", [newMessage], indent=4, relations=('userTo','userFrom') )
return HttpResponse(data, mimetype="application/json")

serializers est natif à Django et permet lorsqu’on a un dictionnaire d’objet, de les renvoyer sous forme de json. Mais dans mon cas problème, j’ai une foreign key sur mon model, en effet un message appartient à un utilisateur… et celui-ci n’était pas nativement retourné par Django.

J’ai donc utilisé DjangoFullSerializers qui me permet de faire cela si je lui spécifie quels foreign key je veux charger, dans mon cas : userTo et userFrom

Ainsi j’obtiens un json de la forme :

[
    {
        "pk": 63,
        "model": "messages.message",
        "fields": {
            "status": 2,
            "title": "coucou",
            "parentMessage": 5,
            "created_on": "2011-08-09 13:10:41",
            "read_on": "2011-08-09 13:10:41",
            "message": "test",
            "userTo": {
                "pk": 1,
                "model": "auth.user",
                "fields": {
                    "username": "admin",
                    "first_name": "",
                    "last_name": "",
                    "is_active": true,
                    "is_superuser": true,
                    "is_staff": true,
                    "last_login": "2011-08-08 10:04:48",
                    "groups": [],
                    "user_permissions": [],
                    "password": "sha1$31e47$cc03b1b61ce695dbed1232c23fd620498a7b221b",
                    "email": "[email protected]",
                    "date_joined": "2011-08-05 05:11:49"
                }
            },
            "userFrom": {
                "pk": 2,
                "model": "auth.user",
                "fields": {
                    "username": "sebastien",
                    "first_name": "",
                    "last_name": "",
                    "is_active": true,
                    "is_superuser": false,
                    "is_staff": false,
                    "last_login": "2011-08-09 13:10:13",
                    "groups": [],
                    "user_permissions": [],
                    "password": "sha1$e75bf$ea83e33e49241536d66429b7dcb9f172fe8ac8ca",
                    "email": "[email protected]",
                    "date_joined": "2011-08-05 06:33:59"
                }
            }
        }
    }
]

Ainsi avec ça je peux reconstruire un bloc html de réponses avec l’avatar de l’utilisateur et toutes les infos nécessaires.

En espérant vous aider.