Як інтегрувати Ajax з програмами Django?


264

Я новачок у Django і досить новий в Ajax. Я працюю над проектом, де мені потрібно інтегрувати ці два. Я вважаю, що я розумію принципи, що стоять за ними обома, але не знайшли хорошого пояснення обох разом.

Чи міг би хтось дати мені коротке пояснення того, як повинна змінюватися база даних коду, коли вони об'єднуються разом?

Наприклад, чи можу я все-таки користуватися програмою HttpResponseAjax, чи потрібно змінити мої відповіді із застосуванням Ajax? Якщо так, чи можете ви надати приклад того, як відповіді на запити повинні змінюватися? Якщо це має значення, дані, які я повертаю, - це JSON.

Відповіді:


637

Незважаючи на те, що це не зовсім в дусі SO, я люблю це питання, тому що у мене були ті ж проблеми, коли я починав, тому я дам вам короткий посібник. Очевидно, ви не розумієте принципів, які стоять за ними (не сприймайте це як образа, але якби ви цього не зробили, ви не запитували).

Джанго на стороні сервера . Це означає, що, скажімо, клієнт переходить до URL-адреси, у вас є функція, viewsяка відображає побачене і повертає відповідь у HTML. Розбимо його на приклади:

views.py:

def hello(request):
    return HttpResponse('Hello World!')

def home(request):
    return render_to_response('index.html', {'variable': 'world'})

index.html:

<h1>Hello {{ variable }}, welcome to my awesome site</h1>

urls.py:

url(r'^hello/', 'myapp.views.hello'),
url(r'^home/', 'myapp.views.home'),

Ось приклад найпростіших звичаїв. Перехід до 127.0.0.1:8000/helloозначає запит до hello()функції, збирається 127.0.0.1:8000/homeповернутиindex.html і замінимо всі змінні, як було запропоновано (ти, мабуть, знаєш це все до цього часу).

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

Наприклад, дзвінок AJAX 127.0.0.1:8000/helloповерне те саме, що і коли б ви його відвідали. Тільки цього разу у вас є функція JavaScript, і ви можете з нею працювати, як завгодно. Давайте розглянемо простий випадок використання:

$.ajax({
    url: '127.0.0.1:8000/hello',
    type: 'get', // This is the default though, you don't actually need to always mention it
    success: function(data) {
        alert(data);
    },
    failure: function(data) { 
        alert('Got an error dude');
    }
}); 

Загальний процес такий:

  1. Виклик переходить до URL-адреси 127.0.0.1:8000/hello, ніби ви відкрили нову вкладку та зробили це самостійно.
  2. Якщо це вдасться (код статусу 200), виконайте функцію успіху, яка сповістить про отримані дані.
  3. Якщо не вдалося, виконайте іншу функцію.

А що б тут сталося? Ви отримаєте сповіщення про "привіт світ" у ньому. Що станеться, якщо ви зателефонуєте додому в AJAX? Те саме, ви отримаєте попередження про те, що <h1>Hello world, welcome to my awesome site</h1>.

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

  1. Вивчіть jQuery . Я не можу наголосити на цьому достатньо. Вам доведеться трохи це зрозуміти, щоб знати, як обробляти отримані дані. Вам також потрібно буде зрозуміти базовий синтаксис JavaScript (неподалік від python, ви звикнете до нього). Настійно рекомендую відео-уроки Envato для jQuery , вони чудові та допоможуть вам зробити правильний шлях.
  2. Коли користуватися JSON? . Ви побачите чимало прикладів, коли дані, надіслані видами Джанго, є в JSON. Я не вдавався в деталі з цього приводу, тому що не важливо, як це зробити (є багато пояснень) і набагато важливіше, коли . І відповідь на це - дані JSON - це серіалізовані дані. Тобто, даними, якими можна маніпулювати. Як я вже згадував, дзвінок AJAX отримає відповідь так, як ніби користувач це зробив сам. Тепер скажіть, що ви не хочете возитися з усіма html, а натомість хочете надсилати дані (можливо, список об’єктів). JSON хороший для цього, оскільки він надсилає його як об’єкт (дані JSON схожі на словник python), а потім ви можете перебирати його чи робити щось інше, що позбавляє від необхідності просіювати непотрібний HTML.
  3. Додайте останнє . Коли ви створюєте веб-додаток і хочете реалізувати AJAX - зробіть собі послугу. По-перше, створити весь додаток, повністю позбавлений будь-якого AJAX. Дивіться, що все працює. Тоді і тільки після цього починайте писати дзвінки AJAX. Це хороший процес, який допомагає вам також багато чому навчитися.
  4. Використовуйте інструменти для розробників chrome . Оскільки AJAX дзвінки виконуються у фоновому режимі, іноді дуже важко їх налагодити. Слід скористатися інструментами хронічного розробника (або подібними інструментами, такими як firebug) та console.logречами для налагодження. Я не буду докладно пояснювати, просто гугл навколо і дізнайся про це. Вам було б дуже корисно.
  5. Поінформованість про КСВР . Нарешті, пам’ятайте, що для запитів на публікації в Джанго потрібні csrf_token. Під час дзвінків AJAX ви багато разів хочете надсилати дані, не оновлюючи сторінку. Ви, мабуть, зіткнетеся з деякими неприємностями, перш ніж ви нарешті згадаєте про це - зачекайте, ви забули відправити csrf_token. Це відомий початковий блок-перешкоди в інтеграції AJAX-Django, але після того, як ви навчитеся робити його добре грати, це легко як пиріг.

Ось і все, що приходить мені в голову. Це величезна тема, але так, мабуть, прикладів там недостатньо. Просто працюйте там, повільно, ви отримаєте це врешті-решт.


1
Дякую. Я просто був там, де ти є, я знаю почуття. Що стосується спілкування в чаті - загалом, так, але зараз не так (також, для конкретних питань у вас є ... ну ... сукупність ТАК).
yuvi

2
PS відео, яке я пов’язав, цілий тиждень присвячував AJAX. Серйозно, проходьте їх. Вони фантастичні
юві

Дякую @yuvi за це! Я задаю собі те саме питання щодо AJAX. Більше того, я не впевнений, коли я повинен використовувати AJAX чи ні. Наприклад, я розумію, що мені потрібен Javascript для обробки модальних форм Bootstrap, але я не розумію, пов’язаний він з AJAX чи ні. І якщо серйозно, потрібно вивчити весь Jquery лише для того, щоб з'явити спливаюче вікно на моїй сторінці ... Я не бачу рентабельності інвестицій :( Чи є простіша альтернатива? :( Ще раз дякую за вашу відповідь.
Девід D.

5
@DavidW. Привіт, Девіде, я щасливий, що моя відповідь допомогла тобі. AJAX - це техніка, яку можна виконати за допомогою простого javascript, але може стати дуже складною. jQuery просто має ярлики, які значно полегшують його. Це не має нічого спільного з модулем Bootstrap (ви можете отримати форми через AJAX, якщо хочете, але це інакше не пов'язано). У будь-якому разі, я настійно пропоную спробувати помалувати свій шлях. jQuery важливий і дуже основний в наші дні, тому хороші інвестиції є. Коли ви потрапили на блокпост, підійдіть до ТА і запитайте (не тут, у коментарях до вже відповіді, відкрийте нове). Удачі!
юві

Що стосується вашої згадки про те csrf_token, чи можемо ми обходити цей метод? Якби у нас була прикладна функція, ajaxCall()ми можемо просто використовувати традиційний метод чогось подібного <form onsubmit='ajaxCall();return false;'>, правда?
ytpillai

22

Надалі від чудової відповіді юві, я хотів би додати невеликий конкретний приклад того, як боротися з цим в межах Джанго (крім будь-якого js, який буде використовуватися). У цьому прикладі використовується AjaxableResponseMixinта передбачається авторська модель.

import json

from django.http import HttpResponse
from django.views.generic.edit import CreateView
from myapp.models import Author

class AjaxableResponseMixin(object):
    """
    Mixin to add AJAX support to a form.
    Must be used with an object-based FormView (e.g. CreateView)
    """
    def render_to_json_response(self, context, **response_kwargs):
        data = json.dumps(context)
        response_kwargs['content_type'] = 'application/json'
        return HttpResponse(data, **response_kwargs)

    def form_invalid(self, form):
        response = super(AjaxableResponseMixin, self).form_invalid(form)
        if self.request.is_ajax():
            return self.render_to_json_response(form.errors, status=400)
        else:
            return response

    def form_valid(self, form):
        # We make sure to call the parent's form_valid() method because
        # it might do some processing (in the case of CreateView, it will
        # call form.save() for example).
        response = super(AjaxableResponseMixin, self).form_valid(form)
        if self.request.is_ajax():
            data = {
                'pk': self.object.pk,
            }
            return self.render_to_json_response(data)
        else:
            return response

class AuthorCreate(AjaxableResponseMixin, CreateView):
    model = Author
    fields = ['name']

Джерело: Документація Django, Обробка форми з видами на основі класу

Посилання на версію 1.6 Django більше не доступне для оновлення до версії 1.11


14

Я пишу це тому, що прийнята відповідь досить стара, вона потребує оновлення.

Ось так я б інтегрував Ajax з Django у 2019 році :) І давайте реально приклади того, коли нам знадобиться Ajax: -

Скажімо, у мене є модель з зареєстрованими іменами користувачів, і за допомогою Ajax я хочу знати, чи існує вказане ім'я користувача.

html:

<p id="response_msg"></p> 
<form id="username_exists_form" method='GET'>
      Name: <input type="username" name="username" />
      <button type='submit'> Check </button>           
</form>   

ajax:

$('#username_exists_form').on('submit',function(e){
    e.preventDefault();
    var username = $(this).find('input').val();
    $.get('/exists/',
          {'username': username},   
          function(response){ $('#response_msg').text(response.msg); }
    );
}); 

urls.py:

from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('exists/', views.username_exists, name='exists'),
]

views.py:

def username_exists(request):
    data = {'msg':''}   
    if request.method == 'GET':
        username = request.GET.get('username').lower()
        exists = Usernames.objects.filter(name=username).exists()
        if exists:
            data['msg'] = username + ' already exists.'
        else:
            data['msg'] = username + ' does not exists.'
    return JsonResponse(data)

Також render_to_response , яка застаріла і була замінена на візуалізації і з Django 1.7 року замість HttpResponse ми використовуємо JsonResponse для AJAX відповідь. Оскільки він постачається з кодером JSON, тому вам не потрібно серіалізувати дані перед поверненням об'єкта відповіді, але HttpResponseвін не застарілий.


8

Просте і приємне. Не потрібно змінювати свої погляди. Bjax обробляє всі ваші посилання. Перевірте це: Bjax

Використання:

<script src="bjax.min.js" type="text/javascript"></script>
<link href="bjax.min.css" rel="stylesheet" type="text/css" />

Нарешті, включіть це до HEAD вашого html:

$('a').bjax();

Для отримання додаткових налаштувань замовлення демонструйте тут: Bjax Demo


18
Привіт, швидка примітка - Я хочу порадити всім, хто тільки починає вивчати Джанго та \ або AJAX - будь ласка , не використовуйте це. Ви нічого не навчитесь. Тримайте це у своїх улюблених та будуйте свої запити AJAX самостійно. Поверніться та використовуйте Bjax, коли ви вже знайомі з тим, як він працює у фоновому режимі. Це не так, як казати людям вивчати асамблею, щоб кодувати - вам не потрібно будувати свої запити AJAX за допомогою чистого JS, просто jQuery, адже якщо ви хочете коли-небудь бути професіоналом, це мінімальний базовий рівень знань потрібно мати. Ура
юві

5

AJAX - найкращий спосіб виконувати асинхронні завдання. Здійснення асинхронних дзвінків - це щось поширене в будь-якій будівлі веб-сайту. Ми візьмемо короткий приклад, щоб дізнатися, як ми можемо реалізувати AJAX у Django. Нам потрібно використовувати jQuery, щоб писати менше JavaScript.

Це контактний приклад, який є найпростішим прикладом, який я використовую для пояснення основ AJAX та його реалізації в Django. У цьому прикладі ми будемо робити запит POST. Я переглядаю один із прикладів цієї публікації: https://djangopy.org/learn/step-up-guide-to-implement-ajax-in-django

models.py

Спочатку створимо модель контакту, яка має основні деталі.

from django.db import models

class Contact(models.Model):
    name = models.CharField(max_length = 100)
    email = models.EmailField()
    message = models.TextField()
    timestamp = models.DateTimeField(auto_now_add = True)

    def __str__(self):
        return self.name

form.py

Створіть форму для вищевказаної моделі.

from django import forms
from .models import Contact

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
        exclude = ["timestamp", ]

views.py

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

from django.http import JsonResponse
from .forms import ContactForm

def postContact(request):
    if request.method == "POST" and request.is_ajax():
        form = ContactForm(request.POST)
        form.save()
        return JsonResponse({"success":True}, status=200)
    return JsonResponse({"success":False}, status=400)

urls.py

Створимо маршрут наведеного подання.

from django.contrib import admin
from django.urls import path
from app_1 import views as app1

urlpatterns = [
    path('ajax/contact', app1.postContact, name ='contact_submit'),
]

шаблон

Перемістившись до розділу фронтенд, візьміть форму, створену вище, що додає тег форми разом із csrf_token та кнопкою подання. Зауважте, що ми включили бібліотеку jquery.

<form id = "contactForm" method= "POST">{% csrf_token %}
   {{ contactForm.as_p }}
  <input type="submit" name="contact-submit" class="btn btn-primary" />
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Javascript

Тепер поговоримо про частину JavaScript, під час подання форми ми робимо запит ajax типу POST, приймаємо дані форми та надсилаємо на сторону сервера.

$("#contactForm").submit(function(e){
    // prevent from normal form behaviour
        e.preventDefault();
        // serialize the form data  
        var serializedData = $(this).serialize();
        $.ajax({
            type : 'POST',
            url :  "{% url 'contact_submit' %}",
            data : serializedData,
            success : function(response){
            //reset the form after successful submit
                $("#contactForm")[0].reset(); 
            },
            error : function(response){
                console.log(response)
            }
        });
   });

Це лише основний приклад, щоб розпочати роботу з AJAX з django, якщо ви хочете зануритися з ще кількома прикладами, ви можете ознайомитись із цією статтею: https://djangopy.org/learn/step-up-guide-to- реалізувати-ajax-in-django


2

Я спробував використовувати AjaxableResponseMixin у своєму проекті, але закінчився таким повідомленням про помилку:

Неправильно налаштовано: немає URL-адреси для переадресації. Надайте URL-адресу або визначте метод get_absolute_url на Моделі.

Це тому, що CreateView поверне відповідь про переадресацію замість повернення HttpResponse, коли ви надсилаєте запит JSON у браузер. Тому я вніс деякі зміни до AjaxableResponseMixin. Якщо запит є запитом ajax, super.form_validметод не викликатиме , просто зателефонуйте form.save()безпосередньо.

from django.http import JsonResponse
from django import forms
from django.db import models

class AjaxableResponseMixin(object):
    success_return_code = 1
    error_return_code = 0
    """
    Mixin to add AJAX support to a form.
    Must be used with an object-based FormView (e.g. CreateView)
    """
    def form_invalid(self, form):
        response = super(AjaxableResponseMixin, self).form_invalid(form)
        if self.request.is_ajax():
            form.errors.update({'result': self.error_return_code})
            return JsonResponse(form.errors, status=400)
        else:
            return response

    def form_valid(self, form):
        # We make sure to call the parent's form_valid() method because
        # it might do some processing (in the case of CreateView, it will
        # call form.save() for example).
        if self.request.is_ajax():
            self.object = form.save()
            data = {
                'result': self.success_return_code
            }
            return JsonResponse(data)
        else:
            response = super(AjaxableResponseMixin, self).form_valid(form)
            return response

class Product(models.Model):
    name = models.CharField('product name', max_length=255)

class ProductAddForm(forms.ModelForm):
    '''
    Product add form
    '''
    class Meta:
        model = Product
        exclude = ['id']


class PriceUnitAddView(AjaxableResponseMixin, CreateView):
    '''
    Product add view
    '''
    model = Product
    form_class = ProductAddForm

0

Коли ми використовуємо Django:

Server ===> Client(Browser)   
      Send a page

When you click button and send the form,
----------------------------
Server <=== Client(Browser)  
      Give data back. (data in form will be lost)
Server ===> Client(Browser)  
      Send a page after doing sth with these data
----------------------------

Якщо ви хочете зберегти старі дані, ви можете зробити це без Ajax. (Сторінка буде оновлена)

Server ===> Client(Browser)   
      Send a page
Server <=== Client(Browser)  
      Give data back. (data in form will be lost)
Server ===> Client(Browser)  
      1. Send a page after doing sth with data
      2. Insert data into form and make it like before. 
      After these thing, server will send a html page to client. It means that server do more work, however, the way to work is same.

Або ви можете зробити з Ajax (Сторінка не буде оновлена)

--------------------------
<Initialization> 
Server ===> Client(Browser) [from URL1]    
      Give a page                      
--------------------------  
<Communication>
Server <=== Client(Browser)     
      Give data struct back but not to refresh the page.
Server ===> Client(Browser) [from URL2] 
      Give a data struct(such as JSON)
---------------------------------

Якщо ви використовуєте Ajax, ви повинні зробити це:

  1. Створіть сторінку HTML за допомогою URL1 (ми зазвичай початкову сторінку за шаблоном Django). А потім сервер відправляє клієнту сторінку HTML.
  2. Використовуйте Ajax для спілкування з сервером за допомогою URL2. А потім сервер відправляє клієнту структуру даних.

Джанго відрізняється від Аякса. Причина цього полягає в наступному:

  • Річ повернення клієнта різна. Справа Джанго - це HTML-сторінка. Справа Ajax - структура даних. 
  • Джанго хороший у створенні чогось, але він може створити лише один раз, він нічого не може змінити. Джанго як аніме, складається з багатьох картин. На відміну від цього, Ajax не добре створювати sth, але добре змінювати sth на існуючій html-сторінці.

На мою думку, якщо ви хочете використовувати ajax скрізь. коли вам потрібно спочатку створити сторінку з даними, ви можете використовувати Django разом з Ajax. Але в деяких випадках вам просто потрібна статична сторінка без нічого з сервера, вам не потрібно використовувати шаблон Django.

Якщо ви не вважаєте, що Ajax - найкраща практика. ви можете використовувати шаблон Django, щоб зробити все, як аніме.

(Моя англійська не досить добра)

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