75 votes

Comment POST un formulaire django avec AJAX & jQuery

J'ai consulté des tonnes de tutoriels pour les formulaires AJAX de Django, mais chacun d'entre eux vous indique une façon de procéder, aucune n'est simple et je suis un peu perdue car je n'ai jamais travaillé avec AJAX.

J'ai un modèle appelé "note", un formulaire de modèle pour celui-ci, et à l'intérieur du modèle j'ai besoin que chaque fois qu'un élément note envoie le signal stop() (de jQuery Sortables) django mette à jour l'objet.

Mon code actuel :

vues.py

def save_note(request, space_name):

    """
    Saves the note content and position within the table.
    """
    place = get_object_or_404(Space, url=space_name)
    note_form = NoteForm(request.POST or None)

    if request.method == "POST" and request.is_ajax:
        msg = "The operation has been received correctly."          
        print request.POST

    else:
        msg = "GET petitions are not allowed for this view."

    return HttpResponse(msg)

JavaScript :

function saveNote(noteObj) {
    /*
        saveNote(noteObj) - Saves the notes making an AJAX call to django. This
        function is meant to be used with a Sortable 'stop' event.
        Arguments: noteObj, note object.
    */
    var noteID = noteObj.attr('id');

    $.post("../save_note/", {
        noteid: noteID,
        phase: "Example phase",
        parent: $('#' + noteID).parent('td').attr('id'),
        title: $('#' + noteID + ' textarea').val(),
        message: "Blablbla",
    });
}

Le code actuel récupère les données du modèle et les imprime dans le terminal. Je ne sais pas comment je peux manipuler ces données. J'ai vu certaines personnes gérer les données à travers jqueryforms pour les envoyer à django.

Comment puis-je accéder aux données envoyées par AJAX et mettre à jour l'objet note ?

129voto

Sevenearths Points 1274

Puisque vous utilisez jQuery, pourquoi ne pas utiliser ce qui suit :

<script language="JavaScript">
    $(document).ready(function() {
        $('#YOUR_FORM').submit(function() { // catch the form's submit event
            $.ajax({ // create an AJAX call...
                data: $(this).serialize(), // get the form data
                type: $(this).attr('method'), // GET or POST
                url: $(this).attr('action'), // the file to call
                success: function(response) { // on success..
                    $('#DIV_CONTAINING_FORM').html(response); // update the DIV 
                }
            });
            return false;
        });
    });
</script>

EDIT

Comme indiqué dans les commentaires, il arrive que la méthode ci-dessus ne fonctionne pas. Essayez donc ce qui suit :

<script type="text/javascript">
    var frm = $('#FORM-ID');
    frm.submit(function () {
        $.ajax({
            type: frm.attr('method'),
            url: frm.attr('action'),
            data: frm.serialize(),
            success: function (data) {
                $("#SOME-DIV").html(data);
            },
            error: function(data) {
                $("#MESSAGE-DIV").html("Something went wrong!");
            }
        });
        return false;
    });
</script>

0 votes

Merci, je vais probablement utiliser cette solution. Les autres solutions fonctionnent également, mais je pense que celle-ci sera plus propre (sans utiliser le plugin jQuery forms).

0 votes

$(this).serialize() ne peut pas attraper submit entrée. Par exemple, si nous avons deux boutons d'envoi dans un formulaire ! Pouvez-vous me dire comment le gérer ?

0 votes

@Sevenearths,lors de la sauvegarde des données d'un formulaire dans une méthode utilisant un post ajax, dois-je utiliser return render ou HttpResponse, besoin d'une clarification.

11voto

Gerardo Curiel Points 71

Vous pouvez accéder aux données sur la requête POST en utilisant le nom de la variable, dans votre cas :

request.POST["noteid"]
request.POST["phase"]
request.POST["parent"]
... etc

L'objet request.POST est inmutable. Vous devez affecter sa valeur à une variable, puis la manipuler.

Je vous conseille d'utiliser ce plugin JQuery Ainsi, vous pouvez écrire des formulaires HTML normaux, puis les faire évoluer vers AJAX. Avoir $.post partout dans votre code est un peu fastidieux.

Utilisez également la vue Réseau de Firebug (pour Firefox) ou les outils de développement de Google Chrome pour voir ce qui est envoyé par vos appels AJAX.

1 votes

Un avertissement pour l'accès aux données directement à partir de l'objet POST pour ceux qui viendront chercher des réponses ici à l'avenir. Assurez-vous d'accéder aux données après validation en utilisant la méthode cleaned_data attribut 2.2 docs . Je n'étais pas sûr de la version de Django de l'opérateur, mais cela semble cohérent jusqu'à la version 1.4.6 ou plus.

5voto

JUhrig Points 11

Il faut faire attention lorsque l'on renvoie le formulaire sous forme d'extrait html à une modale.

Vues.py

@require_http_methods(["POST"])
def login(request):
form = BasicLogInForm(request.POST)
    if form.is_valid():
        print "ITS VALID GO SOMEWHERE"
        pass

    return render(request, 'assess-beta/login-beta.html', {'loginform':form})

Vue simple pour renvoyer le code html extrait

Form html Snipped

<form class="login-form" action="/login_ajx" method="Post"> 
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
    <h4 class="modal-title" id="header">Authenticate</h4>
  </div>
  <div class="modal-body">
        {%if form.non_field_errors %}<div class="alert alert-danger">{{ form.non_field_errors }}</div>{%endif%}
        <div class="fieldWrapper form-group  has-feedback">
            <label class="control-label" for="id_email">Email</label>
            <input class="form-control" id="{{ form.email.id_for_label }}" type="text" name="{{ form.email.html_name }}" value="{%if form.email.value %}{{ form.email.value }}{%endif%}">
            {%if form.email.errors %}<div class="alert alert-danger">{{ form.email.errors }}</div>{%endif%}
        </div>
        <div class="fieldWrapper form-group  has-feedback">
            <label class="control-label" for="id_password">Password</label>
            <input class="form-control" id="{{ form.password.id_for_label }}" type="password" name="{{ form.password.html_name}}" value="{%if form.password.value %}{{ form.password.value }}{%endif%}">
            {%if form.password.errors %}<div class="alert alert-danger">{{ form.password.errors }}</div>{%endif%}
        </div>
  </div>
  <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<input type="submit" value="Sign in" class="btn btn-primary pull-right"/>
</div>
</form>

Page contenant la modale

<div class="modal fade" id="LoginModal" tabindex="-1" role="dialog">{% include "assess-beta/login-beta.html" %}</div>

Utilisez la balise include pour charger l'extrait au chargement de la page afin qu'il soit disponible lorsque vous ouvrez la modale.

Modal.js

$(document).on('submit', '.login-form', function(){
$.ajax({ 
    type: $(this).attr('method'), 
    url: this.action, 
    data: $(this).serialize(),
    context: this,
    success: function(data, status) {
        $('#LoginModal').html(data);
    }
    });
    return false;
});

L'utilisation de .on() dans ce cas fonctionne comme .live(), la clé étant de lier l'événement de soumission non pas au bouton mais au document.

0 votes

Votre solution a fonctionné pour moi, la seule chose que j'ai dû changer était data: {} à data: $(this).serialize() .

3voto

Mandx Points 1403

Comme les autres réponses fonctionnent, je préfère utiliser l'option Plugin jQuery Form . Il supporte entièrement ce que vous voulez et plus encore. L'affichage des messages est géré comme d'habitude dans la partie Django, en retournant simplement le HTML qui est remplacé.

2voto

user931920 Points 129

Côté serveur, votre code django peut traiter le message AJAX de la même manière que les autres soumissions de formulaire. Par exemple,

vues.py

def save_note(request, space_name):

    """
    Saves the note content and position within the table.
    """
    place = get_object_or_404(Space, url=space_name)
    note_form = NoteForm(request.POST or None)

    if request.method == "POST" and request.is_ajax():        
        print request.POST
        if note_form.is_valid():
            note_form.save()
            msg="AJAX submission saved"
        else:
            msg="AJAX post invalid"
    else:
        msg = "GET petitions are not allowed for this view."

    return HttpResponse(msg)

J'ai supposé que votre NoteForm est un ModelForm - ce qui devrait être le cas - et qu'il possède donc une méthode de sauvegarde. Notez qu'en plus d'ajouter le save() j'ai changé votre request.is_ajax à request.is_ajax() ce qui est ce que vous voulez (si vous utilisez request.is_ajax votre code vérifiera simplement si la requête possède une méthode appelée is_ajax (ce qui est évidemment le cas).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X