¿Cómo integro Ajax con las aplicaciones de Django?

264

Soy nuevo en Django y bastante nuevo en Ajax. Estoy trabajando en un proyecto donde necesito integrar los dos. Creo que entiendo los principios detrás de ambos, pero no he encontrado una buena explicación de los dos juntos.

¿Podría alguien darme una explicación rápida de cómo debe cambiar la base de código con la integración de los dos?

Por ejemplo, ¿puedo seguir usando el HttpResponsecon Ajax, o mis respuestas tienen que cambiar con el uso de Ajax? Si es así, ¿podría dar un ejemplo de cómo deben cambiar las respuestas a las solicitudes? Si hace alguna diferencia, los datos que estoy devolviendo son JSON.

tjons
fuente

Respuestas:

637

Aunque esto no está enteramente en el espíritu SO, me encanta esta pregunta, porque tuve el mismo problema cuando comencé, así que te daré una guía rápida. Obviamente no entiendes los principios detrás de ellos (no lo tomes como una ofensa, pero si lo hicieras no lo estarías preguntando).

Django es del lado del servidor . Significa que, digamos que un cliente va a una URL, tiene una función dentro viewsque representa lo que ve y devuelve una respuesta en HTML. Vamos a dividirlo en ejemplos:

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'),

Ese es un ejemplo del uso más simple. Ir a 127.0.0.1:8000/hellosignifica una solicitud a la hello()función, ir a 127.0.0.1:8000/homedevolverá index.htmly reemplazará todas las variables según lo solicitado (probablemente ya sepa todo esto).

Ahora hablemos de AJAX . Las llamadas AJAX son código del lado del cliente que realiza solicitudes asincrónicas. Eso suena complicado, pero simplemente significa que hace una solicitud en segundo plano y luego maneja la respuesta. Entonces, cuando haces una llamada AJAX para alguna URL, obtienes los mismos datos que obtendrías como usuario yendo a ese lugar.

Por ejemplo, una llamada a AJAX 127.0.0.1:8000/hellodevolverá lo mismo que lo haría si la visitara. Solo que esta vez, lo tienes dentro de una función de JavaScript y puedes manejarlo como quieras. Veamos un caso de uso simple:

$.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');
    }
}); 

El proceso general es este:

  1. La llamada va a la URL 127.0.0.1:8000/hellocomo si abriera una nueva pestaña y lo hiciera usted mismo.
  2. Si tiene éxito (código de estado 200), realice la función para el éxito, que alertará a los datos recibidos.
  3. Si falla, realice una función diferente.

¿Y ahora qué pasaría aquí? Recibirías una alerta con 'hola mundo' en él. ¿Qué sucede si haces una llamada AJAX a casa? Lo mismo, recibirá una alerta que indica <h1>Hello world, welcome to my awesome site</h1>.

En otras palabras, no hay nada nuevo sobre las llamadas AJAX. Son solo una forma de permitir que el usuario obtenga datos e información sin salir de la página, y permite un diseño suave y muy ordenado de su sitio web. Algunas pautas que debe tener en cuenta:

  1. Aprende jQuery . No puedo enfatizar esto lo suficiente. Tendrás que entenderlo un poco para saber cómo manejar los datos que recibes. También necesitará comprender alguna sintaxis básica de JavaScript (no muy lejos de Python, se acostumbrará). Recomiendo encarecidamente los videos tutoriales de Envato para jQuery , son geniales y lo pondrán en el camino correcto.
  2. ¿Cuándo usar JSON? . Verá muchos ejemplos en los que los datos enviados por las vistas de Django están en JSON. No entré en detalles sobre eso, porque no es importante cómo hacerlo (hay muchas explicaciones abundantes) y mucho más importante cuando . Y la respuesta a eso es: los datos JSON son datos serializados. Es decir, datos que puede manipular. Como mencioné, una llamada AJAX buscará la respuesta como si el usuario lo hiciera él mismo. Ahora digamos que no desea meterse con todo el html, y en su lugar desea enviar datos (quizás una lista de objetos). JSON es bueno para esto, porque lo envía como un objeto (los datos JSON se ven como un diccionario de Python), y luego puede iterar sobre él o hacer otra cosa que elimine la necesidad de filtrar html inútil.
  3. Añádelo al final . Cuando crea una aplicación web y desea implementar AJAX, hágase un favor. Primero, compila toda la aplicación completamente desprovista de AJAX. Ver que todo está funcionando. Entonces, y solo entonces, comience a escribir las llamadas AJAX. Ese es un buen proceso que también te ayuda a aprender mucho.
  4. Utiliza las herramientas de desarrollador de Chrome . Dado que las llamadas AJAX se realizan en segundo plano, a veces es muy difícil depurarlas. Debe usar las herramientas de desarrollador de Chrome (o herramientas similares como Firebug) y console.logcosas para depurar. No lo explicaré en detalle, solo busque en Google y descubra al respecto. Sería muy útil para ti.
  5. Conciencia CSRF . Finalmente, recuerde que las solicitudes de publicación en Django requieren el csrf_token. Con las llamadas AJAX, muchas veces le gustaría enviar datos sin actualizar la página. Probablemente enfrentará algunos problemas antes de que finalmente lo recuerde: espere, olvidó enviar el csrf_token. Este es un obstáculo para principiantes conocido en la integración de AJAX-Django, pero después de que aprenda cómo hacer que funcione bien, es fácil.

Eso es todo lo que se me ocurre. Es un tema vasto, pero sí, probablemente no haya suficientes ejemplos por ahí. Solo trabaje hasta allí, lentamente, lo obtendrá eventualmente.

Yuvi
fuente
1
Gracias. Simplemente he estado donde estás, conozco el sentimiento. En cuanto a chatear, generalmente sí, pero no en este momento (también, para preguntas específicas que tiene ... bueno ... la totalidad de SO).
yuvi
2
PD: los videos que vinculé tienen una semana entera dedicada a AJAX. En serio, revísalos. Son fantásticos
yuvi el
Gracias @yuvi por esto! Me hago la misma pregunta sobre AJAX. Más aún, no estoy seguro de cuándo debo usar AJAX o no. Por ejemplo, entiendo que necesitaré algunos Javascript para manejar los formularios modales de Bootstrap, pero no entiendo si está relacionado con AJAX o no. Y en serio, tener que aprender todo Jquery solo para hacer aparecer una ventana emergente en mi página ... No puedo ver el retorno de la inversión :( ¿Hay alguna alternativa más simple? :( Gracias de nuevo por su respuesta.
David D.
55
@DavidW. Hola David, estoy feliz de que mi respuesta te haya ayudado. AJAX es una técnica, que puedes hacer con JavaScript simple, pero puede volverse muy complicado. jQuery simplemente tiene accesos directos que lo hacen mucho más fácil. No tiene nada que ver con el modal de Bootstrap (puede obtener formularios a través de AJAX si lo desea, pero por lo demás no está relacionado). De todos modos, te sugiero que trates de encontrar el camino lentamente. jQuery es importante y muy básico en estos días, por lo que es una buena inversión allí. Cuando llegue a un obstáculo, venga a SO y pregunte (no aquí en los comentarios de una pregunta ya respondida, abra una nueva). ¡Buena suerte!
2014
En cuanto a su mención sobre csrf_token, ¿podemos evitar este método? Si tuviéramos una función de ejemplo, ajaxCall()podemos usar el método tradicional de algo así <form onsubmit='ajaxCall();return false;'>, ¿verdad?
ytpillai
22

Además de la excelente respuesta de yuvi, me gustaría agregar un pequeño ejemplo específico sobre cómo lidiar con esto dentro de Django (más allá de cualquier js que se utilizará). El ejemplo usa AjaxableResponseMixiny asume un modelo de Autor.

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

Fuente: documentación de Django, manejo de formularios con vistas basadas en clases

El enlace a la versión 1.6 de Django ya no está disponible actualizado a la versión 1.11

Wtower
fuente
14

Estoy escribiendo esto porque la respuesta aceptada es bastante antigua, necesita un repaso.

Así es como integraría Ajax con Django en 2019 :) Y tomemos un ejemplo real de cuándo necesitaríamos Ajax: -

Digamos que tengo un modelo con nombres de usuario registrados y con la ayuda de Ajax quiero saber si existe un nombre de usuario determinado.

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)

También render_to_response que está en desuso y ha sido reemplazado por render y desde Django 1.7 en adelante en lugar de HttpResponse , usamos JsonResponse para la respuesta ajax. Debido a que viene con un codificador JSON, no necesita serializar los datos antes de devolver el objeto de respuesta, pero HttpResponseno está en desuso.

Ahtisham
fuente
8

Simple y agradable No tiene que cambiar sus puntos de vista. Bjax maneja todos sus enlaces. Mira esto: Bjax

Uso:

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

Finalmente, incluya esto en el HEAD de su html:

$('a').bjax();

Para más configuraciones, vea la demostración de pago aquí: Demo Bjax

endur
fuente
18
Hola, nota rápida: quiero aconsejar a cualquiera que recién esté comenzando a aprender Django y \ o AJAX, por favor no use esto. No aprenderás nada. Manténgalo en sus favoritos y cree sus solicitudes AJAX por su cuenta. Regrese y use Bjax una vez que ya esté familiarizado con cómo funciona en segundo plano. Esto no es como decirle a la gente que aprenda Ensamblaje para codificar: no necesita construir sus solicitudes AJAX con JS puro, solo jQuery, porque si alguna vez quiere ser un profesional, ese es el conocimiento básico mínimo que tendrá necesito tener. Saludos
yuvi
5

AJAX es la mejor manera de hacer tareas asincrónicas. Hacer llamadas asincrónicas es algo común en el uso de cualquier sitio web. Tomaremos un breve ejemplo para aprender cómo podemos implementar AJAX en Django. Necesitamos usar jQuery para escribir menos javascript.

Este es el ejemplo de contacto , que es el ejemplo más simple que estoy usando para explicar los conceptos básicos de AJAX y su implementación en Django. Haremos una solicitud POST en este ejemplo. Estoy siguiendo uno de los ejemplos de esta publicación: https://djangopy.org/learn/step-up-guide-to-implement-ajax-in-django

modelos.py

Primero creemos el modelo de Contacto, que tiene detalles básicos.

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

formas.py

Cree el formulario para el modelo anterior.

from django import forms
from .models import Contact

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

views.py

Las vistas se parecen a la vista de creación basada en funciones básicas, pero en lugar de regresar con render, estamos utilizando la respuesta 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

Creemos la ruta de la vista anterior.

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'),
]

modelo

Pasando a la sección frontend, renderice el formulario que se creó encima de la etiqueta del formulario junto con csrf_token y el botón de enviar. Tenga en cuenta que hemos incluido la biblioteca 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

Hablemos ahora de la parte de JavaScript, en el envío del formulario estamos haciendo una solicitud ajax de tipo POST, tomando los datos del formulario y enviando al lado del servidor.

$("#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)
            }
        });
   });

Este es solo un ejemplo básico para comenzar a usar AJAX con django, si desea sumergirse con varios ejemplos más, puede leer este artículo: https://djangopy.org/learn/step-up-guide-to- implementar-ajax-en-django

Jai Singhal
fuente
2

Intenté usar AjaxableResponseMixin en mi proyecto, pero terminé con el siguiente mensaje de error:

Configuración incorrecta: no hay URL a la que redirigir. Proporcione una url o defina un método get_absolute_url en el Modelo.

Esto se debe a que CreateView devolverá una respuesta de redireccionamiento en lugar de devolver una HttpResponse cuando envíe una solicitud JSON al navegador. Así que he realizado algunos cambios en el AjaxableResponseMixin. Si la solicitud es una solicitud ajax, no llamará al super.form_validmétodo, solo llame al form.save()directamente.

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

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

Si desea conservar datos antiguos, puede hacerlo sin Ajax. (La página se actualizará)

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.

O puede hacerlo con Ajax (la página no se actualizará)

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

Si usa Ajax, debe hacer lo siguiente:

  1. Inicialice una página HTML usando URL1 (generalmente iniciamos la página con la plantilla de Django). Y luego el servidor envía al cliente una página html.
  2. Use Ajax para comunicarse con el servidor usando URL2. Y luego el servidor envía al cliente una estructura de datos.

Django es diferente de Ajax. La razón de esto es la siguiente:

  • Lo que vuelve al cliente es diferente. El caso de Django es la página HTML. El caso de Ajax es la estructura de datos. 
  • Django es bueno creando algo, pero solo puede crear una vez, no puede cambiar nada. Django es como el anime, consiste en muchas imágenes. Por el contrario, Ajax no es bueno para crear algo, pero es bueno para cambiar algo en la página html existente.

En mi opinión, si desea utilizar ajax en todas partes. cuando necesita inicializar una página con datos al principio, puede usar Django con Ajax. Pero en algunos casos, solo necesita una página estática sin nada del servidor, no necesita usar la plantilla Django.

Si no crees que Ajax es la mejor práctica. puedes usar la plantilla de Django para hacer todo, como el anime.

(Mi inglés no es bueno)

kyakya
fuente