Як опублікувати форму django за допомогою AJAX & jQuery


75

Я перевірив безліч підручників для форм django AJAX, але кожен з них розповідає вам про один спосіб зробити це, жоден з них не є простим, і я трохи розгублений, оскільки ніколи не працював з AJAX.

У мене є модель під назвою "примітка", модель моделі для неї, і всередині шаблону мені потрібно, щоб кожен раз, коли елемент примітки надсилав сигнал stop () (з jQuery Sortables) django оновлював об'єкт.

Мій поточний код:

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

Поточний код отримує дані із шаблону та друкує їх у терміналі. Я не знаю, як я можу маніпулювати цими даними. Я бачив, як деякі люди керують даними через jqueryforms, щоб відправити дані в django.

Як я можу отримати доступ до даних, надісланих AJAX, і оновити об’єкт примітки?

Відповіді:


124

Оскільки ви використовуєте jQuery, чому б не використовувати наступне:

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

РЕДАГУВАТИ

Як зазначалося в коментарях, іноді вищезазначене не спрацьовує. Тож спробуйте наступне:

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

Дякую, я, мабуть, скористаюся цим рішенням. Інші також працюють, але я думаю, що це буде чистіше (без нашого використання плагіна jQuery forms)
Оскар Карбаллал

$ (this) .serialize () не може вловити submitвведення. Наприклад, якщо у нас є дві кнопки подання у формі! Чи можете ви сказати мені, як з цим боротися?
Суря

@ Sevenearths, зберігаючи дані форми у методі за допомогою ajax post, я повинен використовувати return render або HttpResponse, потребую роз'яснень
user2086641

2
перший у верхній частині views.pyвикористання: from django.utils import simplejson. Тоді зробіть щось на зразок returnedJSON['message_type'] = 'success' <newline> returnedJSON['message'] = 'The something saved successfully' <newline> return HttpResponse(simplejson.dumps(returnedJSON), mimetype="application/json"). Щось подібне мало би спрацювати
Роберт Джонстон

що робити, якщо я не хочу frm.serialize? я хочу отримати frm.values ​​для кожного поля?
Мухаммед Так

10

Ви можете отримати доступ до даних на запит POST, використовуючи ім'я змінної, у вашому випадку:

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

Об'єкт request.POST є незмінним. Вам слід призначити значення змінної, а потім маніпулювати нею.

Я б порадив вам використовувати цей плагін JQuery , щоб ви могли писати звичайні HTML-форми, а потім отримувати їх "оновленими" до AJAX. Мати $ .post скрізь у вашому коді виглядає нудно.

Крім того, скористайтеся поданням мережі на Firebug (для Firefox) або Інструментами розробника для Google Chrome, щоб ви могли переглядати те, що надсилають ваші дзвінки AJAX.


Чесне попередження про доступ до даних безпосередньо з об’єкта POST для тих, хто прийде сюди, щоб отримати відповіді в майбутньому. Забезпечте доступ до даних після перевірки за допомогою cleaned_dataатрибута 2.2 docs . Не був впевнений у версії опції Django, але вона здається послідовною ще до версії 1.4.6 або більше.
Клей

4

Щось, на що слід звернути увагу, - це повернення форми у вигляді html, відсіченого до модального.

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

Простий перегляд для повернення HTML-фрагмента

Форма html відрізана

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

Сторінка, що містить модаль

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

Використовуйте тег include, щоб завантажити обрізане завантаження сторінки, щоб воно було доступним, коли ви відкриваєте модальний.

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

Використання .on () у цьому випадку працює як .live (), ключ, який прив’язує подію подання не до кнопки, а до документа.


Ваше рішення спрацювало для мене, єдине, що мені потрібно змінити - data: {}це data: $(this).serialize().
Джаррод

3

Оскільки інші відповіді працюють, я вважаю за краще використовувати плагін jQuery Form . Він повністю підтримує те, що ви хочете, і багато іншого. Перегляд публікації обробляється, як зазвичай, у частині Django, просто повертаючи HTML, який замінюється.


2

На стороні сервера ваш код django може обробляти повідомлення AJAX так само, як і інші подані форми. Наприклад,

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)

Я припустив, що ваша NoteForm є ModelForm - якою вона повинна бути, - тому вона має метод збереження. Зауважте, що на додаток до save()команди, я змінив вашу request.is_ajaxна request.is_ajax(), що саме вам потрібно (якщо ви використовуєте request.is_ajaxсвій код, просто перевірите, чи має запит метод is_ajax, який викликається , що, очевидно, і має).


1

Більшість прикладів використання AJAX POST з формами Django, включаючи офіційний приклад:

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

добре, коли ModelForm.clean()не спричинило помилок ( form_valid). Однак вони не виконують важкої партії: перекладуModelForm помилок за допомогою відповіді AJAX на стороні клієнта Javascript / DOM.

Моя програма, що підключається, використовує маршрутизацію відповідей AJAX з моделями перегляду на стороні клієнта для автоматичного відображення ModelFormпомилок перевірки після перевірки AJAX на основі класу, подібних до того, як вони відображалися б у традиційному HTTP POST:

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

Підтримуються як Jinja2, так і Django Template Engine.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.