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

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 los dos integrándose juntos?

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

Aunque esto no está del todo 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 preguntarías).

Django es del lado del servidor. Significa que, digamos que un cliente va a la URL, tiene una función dentro de las vistas que muestra lo que ve y devuelve una respuesta en html. vamos a dividirlo en ejemplos:

vistas.py

 def hello(request): return HttpResponse('Hello World!') def home(request): return render_to_response('index.html', {'variable': 'world'}) 

index.html:

 

Hello {{ variable }}, welcome to my awesome site

urls.py

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

Ese es un ejemplo de los usos más simples. Ir a 127.0.0.1:8000/hello significa una solicitud a la función de saludo, ir a 127.0.0.1:8000/home devolverá el index.html y reemplazará todas las variables según lo solicitado (probablemente ya sepa todo esto).

Ahora hablemos de AJAX. Las llamadas AJAX son códigos del lado del cliente que realizan solicitudes asíncronas. Eso suena complicado, pero simplemente significa que realiza una solicitud en segundo plano y luego maneja la respuesta. Entonces, cuando hace una llamada AJAX para obtener una URL, obtiene los mismos datos que obtendría cuando un usuario vaya a ese lugar.

Por ejemplo, una llamada ajax al 127.0.0.1:8000/hello devolverá lo mismo que lo haría como si lo hubiera visitado. Solo que esta vez, la tienes dentro de una función js y puedes lidiar con ella 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 al url 127.0.0.1:8000/hello como si abrieras una nueva pestaña y lo hicieras tú mismo.
  2. Si tiene éxito (código de estado 200), realice la función para el éxito, lo que alertará a los datos recibidos.
  3. Si falla, haz una función diferente.

Ahora, ¿qué pasaría aquí? Obtendrías una alerta con ‘hola mundo’ en él. ¿Qué pasa si haces una llamada ajax a casa? Lo mismo, recibirá una alerta indicando

Hello world, welcome to my awesome site

.

En otras palabras, no hay nada nuevo acerca de las llamadas AJAX. Son solo una forma de permitirle al usuario obtener datos e información sin salir de la página, y esto hace que el diseño de su sitio web sea suave y muy ordenado. Algunas pautas que debes tener en cuenta son:

  1. Aprende jQuery . No puedo enfatizar esto lo suficiente. Vas a tener que entenderlo un poco para saber cómo manejar los datos que recibes. También deberás entender algo de syntax básica de javascript (no muy lejos de python, te acostumbrarás). Recomiendo los tutoriales en video de Envato para jQuery , son geniales y te 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 (abundan las explicaciones) y mucho más importante cuando . Y la respuesta es: los datos JSON son datos serializados. Es decir, datos que puedes manipular. Como mencioné, una llamada AJAX buscará la respuesta como si el usuario lo hiciera él mismo. Ahora diga que no quiere meterse con todo el html, y en su lugar desea enviar datos (tal vez una lista de objetos). JSON es bueno para esto, porque lo envía como un objeto (los datos JSON parecen un diccionario de Python), y luego puede iterar sobre él o hacer otra cosa que elimine la necesidad de filtrar html inútiles.
  3. Añadirlo al final . Cuando creas una aplicación web y quieres implementar AJAX, hazte un favor. En primer lugar, cree la aplicación completa sin ningún AJAX. Ver que todo está funcionando. Entonces, y solo entonces, comienza a escribir las llamadas AJAX. Ese es un buen proceso que también te ayuda a aprender mucho.
  4. Usa las herramientas de desarrollo de Chrome . Dado que las llamadas AJAX se realizan en segundo plano, a veces es muy difícil depurarlas. Debes usar las herramientas de desarrollo de Chrome (o herramientas similares como firebug) y las cosas de console.log para depurar. No lo explicaré en detalle, solo busco un poco y lo averiguo. Sería muy útil para usted.
  5. Conciencia de 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, se le olvidó enviar el csrf_token . Este es un roadblock para principiantes conocido en la integración AJAX-Django, pero después de que aprendas a hacer que funcione bien, es fácil como un pastel.

Eso es todo lo que viene a mi cabeza. Es un gran tema, pero sí, probablemente no haya suficientes ejemplos ahí fuera. Solo trabaja en tu camino, lentamente, lo conseguirás eventualmente.

Además de la excelente respuesta de Yuvi, me gustaría agregar un pequeño ejemplo específico sobre cómo tratar esto dentro de Django (más allá de cualquier js que se usará). El ejemplo utiliza AjaxableResponseMixin y 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 (eg 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

Sencillo y agradable. No tienes que cambiar tus puntos de vista. Bjax maneja todos tus enlaces. Mira esto: Bjax

Uso:

   

Finalmente, incluye esto en la CABEZA de tu html:

 $('a').bjax(); 

Para más configuraciones, verifique la demostración aquí: Demo Bjax

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

Configurado incorrectamente: no hay URL para redireccionar a. Proporcione una url o defina un método get_absolute_url en el modelo.

Esto se debe a que CreateView devolverá una respuesta de redirección en lugar de devolver una HttpResponse cuando envíe una solicitud JSON al navegador. Así que he hecho algunos cambios en el AjaxableResponseMixin . Si la solicitud es una solicitud ajax, no llamará al método super.form_valid , simplemente llame a 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 (eg 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 

Estoy escribiendo esto porque la respuesta aceptada es bastante antigua, necesita una actualización.

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:

 

Name:

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 HttpResponse no está en desuso.

AJAX es la mejor manera de hacer tareas asíncronas. Hacer llamadas asíncronas es algo común en el uso en 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 creamos el modelo de Contacto, teniendo 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 

forms.py

Crear el formulario para el modelo anterior.

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

vistas.py

Las vistas son similares a la vista básica basada en la función crear, pero en lugar de regresar con render, estamos usando 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

Vamos a crear 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 de frontend, renderice el formulario que se creó arriba encerrando la etiqueta del formulario junto con csrf_token y el botón de envío. Tenga en cuenta que hemos incluido la biblioteca jquery.

 
{% csrf_token %} {{ contactForm.as_p }}

Javascript

Ahora hablemos de la parte de javascript, en el envío de formulario estamos realizando una solicitud ajax de tipo POST, tomando los datos del formulario y enviándolos al 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 con AJAX con django. Si desea bucear con varios ejemplos más, puede consultar este artículo: https://djangopy.org/learn/step-up-guide-to- implementar-ajax-en-django