Как интегрировать Ajax с приложениями Django?

264

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

Может ли кто-нибудь дать мне быстрое объяснение того, как кодовая база должна измениться, когда они интегрируются вместе?

Например, могу ли я по-прежнему использовать HttpResponseс Ajax или мои ответы должны измениться с использованием Ajax? Если да, не могли бы вы привести пример того, как должны изменяться ответы на запросы? Если это имеет какое-то значение, я возвращаю данные в формате JSON.

tjons
источник

Ответы:

637

Хотя это не совсем в духе ТАК, мне нравится этот вопрос, потому что у меня были те же проблемы, когда я начинал, поэтому я дам вам краткое руководство. Очевидно, вы не понимаете принципы, стоящие за ними (не воспринимайте это как оскорбление, но если бы вы это сделали, вы бы не спрашивали).

Джанго на стороне сервера . Это означает, что, скажем, клиент идет по 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? , Вы увидите много примеров, когда данные, отправляемые представлениями Django, находятся в формате JSON. Я не стал вдаваться в подробности, потому что не важно, как это сделать (имеется множество объяснений), и гораздо важнее, когда . И ответ на этот вопрос - данные JSON являются сериализованными данными. То есть данными, которыми вы можете манипулировать. Как я уже говорил, AJAX-вызов будет получать ответ, как если бы пользователь сделал это сам. Теперь скажите, что вы не хотите связываться со всеми html-файлами, а вместо этого хотите отправлять данные (возможно, список объектов). JSON хорош для этого, потому что он отправляет его как объект (данные JSON выглядят как словарь python), а затем вы можете перебирать его или делать что-то еще, что устраняет необходимость просеивать бесполезный html.
  3. Добавьте это в последнюю очередь . Когда вы создаете веб-приложение и хотите реализовать AJAX - сделайте себе одолжение. Во-первых, создайте приложение полностью без AJAX. Смотри что все работает. Тогда и только тогда начните писать вызовы AJAX. Это хороший процесс, который также помогает вам многому научиться.
  4. Используйте инструменты разработчика Chrome . Поскольку вызовы AJAX выполняются в фоновом режиме, иногда их очень трудно отладить. Вы должны использовать инструменты разработчика Chrome (или аналогичные инструменты, такие как firebug) и другие console.logвещи для отладки. Я не буду подробно объяснять, просто погуглите и узнайте об этом. Это было бы очень полезно для вас.
  5. CSRF осведомленность . Наконец, помните, что для отправки запросов в Django требуется csrf_token. С вызовами AJAX, часто вы хотели бы отправлять данные без обновления страницы. Вы , вероятно, столкнутся некоторые проблемы , прежде чем, наконец , помните , что - ждать, вы забыли отправить csrf_token. Это известное препятствие для начинающих в интеграции AJAX-Django, но после того, как вы узнаете, как заставить его играть хорошо, это просто как пирог.

Это все, что приходит мне в голову. Это обширная тема, но да, вероятно, там не достаточно примеров. Просто прокладывайте себе путь, медленно, в конце концов, вы получите это.

Yuvi
источник
1
Спасибо. Я просто был там, где ты есть, я знаю это чувство. Что касается чата - как правило, да, но не сейчас (также, для конкретных вопросов у вас есть ... ну ... в общем, ТАК).
Юви
2
PS у видео, которые я связал, есть целая неделя, посвященная AJAX. Серьезно, пройдите их. Они фантастические
ЮВи
Спасибо @yuvi за это! Я задаю себе тот же вопрос о AJAX. Более того, я не уверен, когда я должен использовать AJAX или нет. Например, я понимаю, что мне понадобится Javascript для обработки модальных форм Bootstrap, но я не понимаю, связано ли это с AJAX или нет. И если серьезно, то, что мне нужно изучить весь Jquery только для того, чтобы на моей странице появилось всплывающее окно ... Я не вижу отдачи от инвестиций :( Есть ли более простая альтернатива? :( Еще раз спасибо за ваш ответ.
Дэвид D.
5
@DavidW. Привет Дэвид, я рад, что мой ответ помог тебе. AJAX - это техника, которую вы можете сделать с простым javascript, но она может стать очень сложной. JQuery просто имеет ярлыки, которые делают его намного проще. Это не имеет ничего общего с модальностью Bootstrap (вы можете получать формы через AJAX, если хотите, но в остальном это не связано). Во всяком случае, я настоятельно рекомендую вам попытаться придумать свой путь медленно. jQuery важен и очень прост в наши дни, поэтому хорошие инвестиции есть. Когда вы преодолеете контрольно-пропускной пункт, подойдите к SO и спросите (не здесь, в комментариях к уже отвеченному вопросу, откройте новый). Удачи!
Юви
Что касается вашего упоминания о том csrf_token, можем ли мы обойти этот метод? Если бы у нас был пример функции, ajaxCall()мы могли бы просто использовать традиционный метод чего-то вроде <form onsubmit='ajaxCall();return false;'>, верно?
ytpillai
22

В дополнение к отличному ответу yuvi, я хотел бы добавить небольшой конкретный пример того, как с этим справляться в Django (помимо любых js, которые будут использоваться). В примере используется AjaxableResponseMixinи предполагается модель Author.

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

Wtower
источник
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, который устарел и был заменен render и начиная с Django 1.7 и далее вместо HttpResponse, мы используем JsonResponse для ответа ajax. Поскольку он поставляется с кодировщиком JSON, вам не нужно сериализовать данные перед возвратом объекта ответа, но HttpResponseэто не рекомендуется.

Ahtisham
источник
8

Просто и приятно. Вам не нужно менять свои взгляды. Bjax обрабатывает все ваши ссылки. Проверьте это: Bjax

Использование:

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

Наконец, включите это в заголовок вашего HTML:

$('a').bjax();

Для получения дополнительных настроек, ознакомьтесь с демо здесь: Bjax Demo

endur
источник
18
Привет, быстрое примечание - я хочу посоветовать всем, кто только начинает изучать Django и \ или 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

forms.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- реализовать-АЯКС-в-Джанго

Джай Сингхал
источник
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
Enix
источник
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. Затем сервер отправляет клиенту структуру данных.

Джанго отличается от Аякса. Причина этого заключается в следующем:

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

На мой взгляд, если вы хотите использовать ajax везде. когда вам нужно сначала инициализировать страницу с данными, вы можете использовать Django с Ajax. Но в некоторых случаях вам просто нужна статическая страница без чего-либо с сервера, вам не нужно использовать шаблон Django.

Если вы не думаете, Ajax - лучшая практика. Вы можете использовать шаблон Django, чтобы делать все, как аниме.

(Мой английский не очень хорош)

kyakya
источник