So veröffentlichen Sie ein Django-Formular mit AJAX & jQuery

74

Ich habe unzählige Tutorials für Django AJAX-Formulare durchgesehen, aber jedes von ihnen zeigt Ihnen eine Möglichkeit, keine davon ist einfach und ich bin ein bisschen verwirrt, da ich noch nie mit AJAX gearbeitet habe.

Ich habe ein Modell namens "note", eine Modellform dafür, und innerhalb der Vorlage muss jedes Mal, wenn ein note-Element das stop () -Signal (von jQuery Sortables) sendet, django das Objekt aktualisieren.

Mein aktueller Code:

views.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",
    });
}

Der aktuelle Code ruft die Daten aus der Vorlage ab und druckt sie im Terminal aus. Ich weiß nicht, wie ich diese Daten manipulieren kann. Ich habe gesehen, dass einige Leute die Daten über jqueryforms verwalten, um die Daten an django zu senden.

Wie kann ich auf die von AJAX gesendeten Daten zugreifen und das Notizobjekt aktualisieren?

Oscar Carballal
quelle

Antworten:

121

Da Sie jQuery verwenden, verwenden Sie Folgendes:

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

BEARBEITEN

Wie in den Kommentaren erwähnt, funktioniert das oben Gesagte manchmal nicht. Versuchen Sie also Folgendes:

<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>
Robert Johnstone
quelle
Danke, ich werde diese Lösung wahrscheinlich verwenden. Die anderen funktionieren auch, aber ich denke, das wird sauberer (ohne das jQuery Forms Plugin)
Oscar Carballal
$ (this) .serialize () kann keine submitEingaben abfangen . Zum Beispiel, wenn wir zwei Senden-Schaltflächen in einem Formular haben! Kannst du mir sagen, wie ich damit umgehen soll?
Surya
@ Sevenearths, während ich Formulardaten in einer Methode mit Ajax Post speichere, sollte ich Return Render oder HttpResponse verwenden, muss geklärt werden
user2086641
2
zuerst an der Spitze Ihrer views.pyVerwendung : from django.utils import simplejson. Dann mach so etwas returnedJSON['message_type'] = 'success' <newline> returnedJSON['message'] = 'The something saved successfully' <newline> return HttpResponse(simplejson.dumps(returnedJSON), mimetype="application/json"). So etwas sollte funktionieren
Robert Johnstone
Was ist, wenn ich nicht frm.serialize möchte? Ich möchte Einzelpersonen von Werten aus jedem Bereich erhalten?
Muhammad Taqi
10

Sie können auf die Daten in der POST-Anforderung unter Verwendung des Namens der Variablen zugreifen, in Ihrem Fall:

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

Das request.POST-Objekt ist unveränderlich. Sie sollten den Wert einer Variablen zuweisen und ihn dann bearbeiten.

Ich würde Ihnen raten, dieses JQuery-Plugin zu verwenden , damit Sie normale HTML-Formulare schreiben und sie dann auf AJAX "aktualisieren" können. Es ist ziemlich mühsam, überall in Ihrem Code $ .post zu haben.

Verwenden Sie außerdem die Netzwerkansicht in Firebug (für Firefox) oder die Entwicklertools für Google Chrome, um anzuzeigen, was von Ihren AJAX-Anrufen gesendet wird.

Gerardo Curiel
quelle
Faire Warnung für den direkten Zugriff auf Daten vom POST-Objekt für diejenigen, die hierher kommen, um in Zukunft Antworten zu erhalten. Stellen Sie sicher, dass Sie nach der Validierung mithilfe des cleaned_dataAttributs 2.2 docs auf Daten zugreifen . Ich war mir bei der Op-Version von Django nicht sicher, aber es scheint bereits ab 1.4.6 oder mehr konsistent zu sein.
Clay
4

Achten Sie beim Zurücksenden des Formulars darauf, dass ein HTML-Code in ein Modal geschnitten wird.

Views.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})

Einfache Ansicht, um den abgeschnittenen HTML-Code zurückzugeben

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>

Seite mit dem Modal

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

Verwenden Sie das Include-Tag, um das geladene Seitenladen zu laden, damit es beim Öffnen des Modals verfügbar ist.

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;
});

Wenn Sie in diesem Fall .on () verwenden, arbeiten Sie wie .live (), wobei der Schlüssel das Übermittlungsereignis nicht an die Schaltfläche, sondern an das Dokument bindet.

JUhrig
quelle
Ihre Lösung für mich gearbeitet, das einzige , was ich ändern müssen war data: {}zu data: $(this).serialize().
Jarrod
3

Da die anderen Antworten funktionieren, bevorzuge ich das jQuery Form Plugin . Es unterstützt voll und ganz, was Sie wollen und mehr. Die Post-Ansicht wird im Django-Teil wie gewohnt behandelt und gibt nur den HTML-Code zurück, der ersetzt wird.

Armando Pérez Marqués
quelle
2

Auf der Serverseite kann Ihr Django-Code den AJAX-Beitrag genauso verarbeiten wie andere Formularübermittlungen. Zum Beispiel,

views.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)

Ich habe angenommen, dass Ihre NoteForm eine ModelForm ist - was es auch sein sollte -, also hat sie eine Speichermethode. Beachten Sie, dass save()ich zusätzlich zum Hinzufügen des Befehls Ihren request.is_ajaxin geändert habe request.is_ajax(), was Sie möchten (wenn Sie request.is_ajaxIhren Code verwenden, wird nur geprüft, ob für die Anforderung eine Methode aufgerufen wurde is_ajax, was offensichtlich der Fall ist).

user931920
quelle
1

Die meisten Beispiele für die Verwendung von AJAX POST mit Django-Formularen, einschließlich des offiziellen Beispiels:

https://docs.djangoproject.com/de/1.9/topics/class-based-views/generic-editing/#ajax-example

sind in Ordnung, wenn ModelForm.clean()keine Fehler aufgetreten sind ( form_valid). Sie leisten jedoch keinen schwierigen Teil: Übersetzen von ModelFormFehlern über die AJAX-Antwort auf die clientseitige Javascript / DOM-Seite.

Meine steckbare Anwendung verwendet AJAX-Antwortrouting mit clientseitigen Ansichtsmodellen, um automatisch klassenbasierte AJAX-Nachprüfungsfehler anzuzeigen ModelForm, ähnlich wie sie in herkömmlichen HTTP -POSTs angezeigt würden:

https://django-jinja-knockout.readthedocs.org/en/latest/forms.html#ajax-forms-processing https://django-jinja-knockout.readthedocs.org/en/latest/viewmodels.html

Sowohl Jinja2 als auch Django Template Engine werden unterstützt.

Dmitriy Sintsov
quelle