it-swarm.com.ru

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

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

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

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

226
tjons

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

Джанго на стороне сервера. Это означает, что клиент говорит, что у вас есть функция внутри представлений, которая отображает то, что он видит, и возвращает ответ в 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 вернет то же самое, что и при посещении. Только на этот раз у вас есть это внутри функции js, и вы можете справиться с ней так, как захотите. Давайте посмотрим на простой случай использования:

$.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, но после того, как вы узнаете, как заставить его играть в Nice, все просто.

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

566
yuvi

В дополнение к отличному ответу 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

18
Wtower

Просто и приятно. Вам не нужно менять свои взгляды. 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

7
endur

Я пытался использовать AjaxableResponseMixin в моем проекте, но в результате получилось следующее сообщение об ошибке:

Неправильно сконфигурировано: нет URL для перенаправления. Либо укажите URL-адрес, либо определите метод get_absolute_url в модели.

Это потому, что CreateView будет возвращать ответ redirect вместо возврата 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
2
Enix

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/ пошаговое руководство для реализации ajax-in-Django

1
Jai Singhal

Я пишу это, потому что принятый ответ довольно старый, он нуждается в обновлении. 

Вот как я бы интегрировал 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 не считается устаревшим.

0
Ahtisham