Comment intégrer Ajax aux applications Django?

264

Je suis nouveau à Django et assez nouveau à Ajax. Je travaille sur un projet où je dois intégrer les deux. Je crois que je comprends les principes qui les sous-tendent, mais je n'ai pas trouvé ensemble une bonne explication des deux.

Quelqu'un pourrait-il me donner une explication rapide de la façon dont la base de code doit changer avec les deux intégrant ensemble?

Par exemple, puis-je toujours utiliser HttpResponseavec Ajax, ou mes réponses doivent-elles changer avec l'utilisation d'Ajax? Si oui, pourriez-vous donner un exemple de la façon dont les réponses aux demandes doivent changer? Si cela fait une différence, les données que je renvoie sont JSON.

tjons
la source

Réponses:

637

Même si ce n'est pas entièrement dans l'esprit SO, j'adore cette question, car j'ai eu le même problème quand j'ai commencé, alors je vais vous donner un petit guide. De toute évidence, vous ne comprenez pas les principes qui les sous-tendent (ne le prenez pas comme une offense, mais si vous le faisiez, vous ne le demanderiez pas).

Django est côté serveur . Cela signifie, disons qu'un client accède à une URL, que vous avez une fonction à l'intérieur viewsqui rend ce qu'il voit et renvoie une réponse en HTML. Décomposons-le en exemples:

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

C'est un exemple des utilisations les plus simples. Aller à 127.0.0.1:8000/hellosignifie une requête à la hello()fonction, va 127.0.0.1:8000/homeretourner index.htmlet remplacer toutes les variables comme demandé (vous savez probablement tout cela maintenant).

Parlons maintenant d' AJAX . Les appels AJAX sont du code côté client qui effectue des requêtes asynchrones. Cela semble compliqué, mais cela signifie simplement qu'il fait une demande pour vous en arrière-plan, puis gère la réponse. Ainsi, lorsque vous effectuez un appel AJAX pour une URL, vous obtenez les mêmes données que celles que vous obtiendriez en tant qu'utilisateur se rendant à cet endroit.

Par exemple, un appel AJAX à 127.0.0.1:8000/helloretournera la même chose que si vous le visitiez. Seulement cette fois, vous l'avez dans une fonction JavaScript et vous pouvez le gérer comme vous le souhaitez. Regardons un cas d'utilisation 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');
    }
}); 

Le processus général est le suivant:

  1. L'appel est dirigé vers l'URL 127.0.0.1:8000/hellocomme si vous aviez ouvert un nouvel onglet et l'aviez fait vous-même.
  2. S'il réussit (code d'état 200), effectuez la fonction de réussite, qui alertera les données reçues.
  3. En cas d'échec, effectuez une fonction différente.

Maintenant, que se passerait-il ici? Vous obtiendrez une alerte avec «bonjour le monde». Que se passe-t-il si vous passez un appel AJAX à domicile? Même chose, vous recevrez une alerte indiquant <h1>Hello world, welcome to my awesome site</h1>.

En d'autres termes, les appels AJAX n'ont rien de nouveau. Ils ne sont qu'un moyen pour vous de permettre à l'utilisateur d'obtenir des données et des informations sans quitter la page, et cela permet une conception fluide et très soignée de votre site Web. Quelques lignes directrices dont vous devriez prendre note:

  1. Apprenez jQuery . Je ne peux insister assez sur ce point. Il va falloir que vous le compreniez un peu pour savoir comment gérer les données que vous recevez. Vous aurez également besoin de comprendre une syntaxe JavaScript de base (non loin de python, vous vous y habituerez). Je recommande fortement les didacticiels vidéo d'Envato pour jQuery , ils sont excellents et vous mettront sur la bonne voie.
  2. Quand utiliser JSON? . Vous allez voir de nombreux exemples où les données envoyées par les vues Django sont en JSON. Je ne suis pas entré dans les détails à ce sujet, car il n'est pas important de savoir comment le faire (il y a beaucoup d'explications) et beaucoup plus important quand . Et la réponse est: les données JSON sont des données sérialisées. Autrement dit, les données que vous pouvez manipuler. Comme je l'ai mentionné, un appel AJAX récupère la réponse comme si l'utilisateur l'avait fait lui-même. Supposons maintenant que vous ne vouliez pas jouer avec tout le code HTML et que vous souhaitiez envoyer des données (une liste d'objets peut-être). JSON est bon pour cela, car il l'envoie en tant qu'objet (les données JSON ressemblent à un dictionnaire python), puis vous pouvez itérer dessus ou faire autre chose qui supprime la nécessité de passer au crible le html inutile.
  3. Ajoutez-le en dernier . Lorsque vous créez une application Web et que vous souhaitez implémenter AJAX, faites-vous plaisir. Tout d'abord, créez l'application entière complètement dépourvue de tout AJAX. Assurez-vous que tout fonctionne. Ensuite, et alors seulement, commencez à écrire les appels AJAX. C'est un bon processus qui vous aide également à apprendre beaucoup.
  4. Utilisez les outils de développement de Chrome . Étant donné que les appels AJAX sont effectués en arrière-plan, il est parfois très difficile de les déboguer. Vous devez utiliser les outils de développement Chrome (ou des outils similaires tels que Firebug) et des console.logchoses à déboguer. Je ne vais pas expliquer en détail, juste google autour et découvrir à ce sujet. Ce serait très utile pour vous.
  5. Sensibilisation à la CSRF . Enfin, n'oubliez pas que les demandes de publication dans Django nécessitent le csrf_token. Avec les appels AJAX, vous souhaitez souvent envoyer des données sans rafraîchir la page. Vous rencontrerez probablement des problèmes avant de vous en souvenir - attendez, vous avez oublié d'envoyer le csrf_token. Il s'agit d'un barrage routier débutant connu dans l'intégration AJAX-Django, mais après avoir appris à le rendre agréable à jouer, c'est aussi simple que ça.

C'est tout ce qui me vient à l'esprit. C'est un vaste sujet, mais oui, il n'y a probablement pas assez d'exemples. Il vous suffit de vous y rendre, lentement, vous finirez par l'obtenir.

yuvi
la source
1
Merci. J'ai simplement été là où tu es, je connais le sentiment. En ce qui concerne le chat - généralement oui, mais pas en ce moment (aussi, pour des questions spécifiques que vous avez ... enfin ... l'intégralité de SO).
yuvi
2
PS les vidéos que j'ai liées ont une semaine entière dédiée à AJAX. Sérieusement, passez par eux. Ils sont fantastiques
Yuvi
Merci @yuvi pour cela! Je me pose la même question sur AJAX. De plus, je ne sais pas quand je dois utiliser AJAX ou non. Par exemple, je comprends que j'aurai besoin de Javascript pour gérer les formulaires modaux Bootstrap mais je ne comprends pas si c'est lié à AJAX ou non. Et sérieusement, avoir à apprendre tout le Jquery juste pour faire apparaître un pop-up dans ma page ... Je ne vois pas le retour sur investissement :( Y a-t-il une alternative plus simple? :( Merci encore pour votre réponse.
David D.
5
@DavidW. Bonjour David, je suis heureux que ma réponse vous ait aidé. AJAX est une technique que vous pouvez faire avec du javascript simple, mais qui peut devenir très compliquée. jQuery a simplement des raccourcis qui le rendent beaucoup plus facile. Cela n'a rien à voir avec le modal de Bootstrap (vous pouvez récupérer des formulaires via AJAX si vous le souhaitez, mais cela n'est pas lié par ailleurs). Quoi qu'il en soit, je vous suggère fortement d'essayer de trouver votre chemin lentement. jQuery est important et très basique de nos jours, donc bon investissement là-bas. Lorsque vous rencontrez un barrage routier, venez à SO et demandez (pas ici dans les commentaires d'une question déjà répondue, ouvrez-en une nouvelle). Bonne chance!
yuvi
En ce qui concerne votre mention csrf_token, pouvons-nous contourner cette méthode? Si nous avions un exemple de fonction, ajaxCall()nous pouvons simplement utiliser la méthode traditionnelle de quelque chose comme <form onsubmit='ajaxCall();return false;'>, non?
ytpillai
22

Plus loin de l'excellente réponse de yuvi, je voudrais ajouter un petit exemple spécifique sur la façon de gérer cela dans Django (au-delà de tout js qui sera utilisé). L'exemple utilise AjaxableResponseMixinet suppose un modèle d'auteur.

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

Source: documentation Django, gestion des formulaires avec des vues basées sur les classes

Le lien vers la version 1.6 de Django n'est plus disponible mis à jour vers la version 1.11

Wtower
la source
14

J'écris ceci parce que la réponse acceptée est assez ancienne, elle a besoin d'un rafraîchissement.

Voici donc comment j'intégrerais Ajax à Django en 2019 :) Et prenons un exemple réel de quand nous aurions besoin d'Ajax: -

Disons que j'ai un modèle avec des noms d'utilisateur enregistrés et avec l'aide d'Ajax, je veux savoir s'il existe un nom d'utilisateur donné.

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)

Aussi render_to_response qui est obsolète et a été remplacé par render et à partir de Django 1.7 et au lieu de HttpResponse, nous utilisons JsonResponse pour la réponse ajax. Parce qu'il est livré avec un encodeur JSON, vous n'avez donc pas besoin de sérialiser les données avant de renvoyer l'objet de réponse, mais il HttpResponsen'est pas obsolète.

Ahtisham
la source
8

Simple et sympa. Vous n'avez pas besoin de changer vos vues. Bjax gère tous vos liens. Découvrez ceci: Bjax

Usage:

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

Enfin, incluez ceci dans le HEAD de votre html:

$('a').bjax();

Pour plus de paramètres, consultez la démo ici: Bjax Demo

endurer
la source
18
Salut, note rapide - je veux conseiller à tous ceux qui commencent tout juste à apprendre Django et / ou AJAX - veuillez ne pas l' utiliser. Tu n'apprendras rien. Gardez-le dans vos favoris et créez vous-même vos demandes AJAX. Revenez et utilisez Bjax une fois que vous savez déjà comment cela fonctionne en arrière-plan. Ce n'est pas comme dire aux gens d'apprendre Assembly pour coder - vous n'avez pas besoin de construire vos requêtes AJAX avec JS pur, juste jQuery, parce que si vous voulez être un professionnel, c'est la connaissance de base minimale que vous aurez besoin d'avoir. Cheers
yuvi
5

AJAX est le meilleur moyen d'effectuer des tâches asynchrones. Faire des appels asynchrones est quelque chose de courant dans tout bâtiment de site Web. Nous prendrons un court exemple pour savoir comment implémenter AJAX dans Django. Nous devons utiliser jQuery pour écrire moins de javascript.

Il s'agit de l' exemple Contact , qui est l'exemple le plus simple que j'utilise pour expliquer les bases d'AJAX et son implémentation dans Django. Nous allons faire une demande POST dans cet exemple. Je suis un exemple de cet article: https://djangopy.org/learn/step-up-guide-to-implement-ajax-in-django

models.py

Créons d'abord le modèle de Contact, avec des détails de base.

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

Créez le formulaire pour le modèle ci-dessus.

from django import forms
from .models import Contact

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

views.py

Les vues ressemblent à la vue de création basée sur une fonction de base, mais au lieu de revenir avec le rendu, nous utilisons la réponse 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

Créons l'itinéraire de la vue ci-dessus.

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

modèle

En passant à la section frontend, restituez le formulaire créé au-dessus de la balise de formulaire englobante avec csrf_token et cliquez sur le bouton Soumettre. Notez que nous avons inclus la bibliothèque 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

Parlons maintenant de la partie javascript, sur le formulaire soumis, nous faisons une demande ajax de type POST, en prenant les données du formulaire et en les envoyant côté serveur.

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

Ceci est juste un exemple de base pour démarrer avec AJAX avec django, si vous voulez plonger avec plusieurs autres exemples, vous pouvez parcourir cet article: https://djangopy.org/learn/step-up-guide-to- implement-ajax-in-django

Jai Singhal
la source
2

J'ai essayé d'utiliser AjaxableResponseMixin dans mon projet, mais je me suis retrouvé avec le message d'erreur suivant:

ImproperlyConfigured: Aucune URL vers laquelle rediriger. Fournissez une URL ou définissez une méthode get_absolute_url sur le modèle.

En effet, CreateView renvoie une réponse de redirection au lieu de renvoyer une réponse HttpResponse lorsque vous envoyez une demande JSON au navigateur. J'ai donc apporté quelques modifications à la AjaxableResponseMixin. Si la requête est une requête ajax, elle n'appellera pas la super.form_validméthode, il suffit d'appeler form.save()directement.

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
la source
0

Lorsque nous utilisons 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 vous souhaitez conserver les anciennes données, vous pouvez le faire sans Ajax. (La page sera rafraîchie)

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.

Ou vous pouvez le faire avec Ajax (la page ne sera pas actualisée)

--------------------------
<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 vous utilisez Ajax, vous devez le faire:

  1. Initialisez une page HTML en utilisant URL1 (nous initialisons généralement la page par le modèle Django). Et puis le serveur envoie au client une page html.
  2. Utilisez Ajax pour communiquer avec le serveur en utilisant URL2. Et puis le serveur envoie au client une structure de données.

Django est différent d'Ajax. La raison pour cela est la suivante:

  • La chose qui revient au client est différente. Le cas de Django est la page HTML. Le cas d'Ajax est la structure de données. 
  • Django est bon pour créer quelque chose, mais il ne peut créer qu'une seule fois, il ne peut rien changer. Django est comme un anime, composé de nombreuses images. En revanche, Ajax n'est pas bon pour créer qch mais bon pour changer qch dans la page html existante.

À mon avis, si vous souhaitez utiliser ajax partout. lorsque vous devez d'abord initialiser une page avec des données, vous pouvez utiliser Django avec Ajax. Mais dans certains cas, vous avez juste besoin d'une page statique sans rien du serveur, vous n'avez pas besoin d'utiliser le modèle Django.

Si vous ne pensez pas que l'Ajax est la meilleure pratique. vous pouvez utiliser le modèle Django pour tout faire, comme l'anime.

(Mon anglais n'est pas bon)

kyakya
la source