web-dev-qa-db-fra.com

Comment intégrer Ajax aux applications Django?

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

Quelqu'un pourrait-il m'expliquer rapidement comment la base de code doit évoluer et s'intégrer ensemble?

Par exemple, puis-je quand même utiliser la variable HttpResponse avec Ajax ou dois-je modifier mes réponses avec 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 retourne sont JSON. 

226
tjons

Même si cela n’est pas tout à fait dans l’esprit SO, j’adore cette question, car j’avais le même problème quand j’ai commencé, je vais donc vous donner un guide rapide. De toute évidence, vous ne comprenez pas les principes qui les sous-tendent (ne le prenez pas comme une infraction, mais si vous le faisiez, vous ne le demanderiez pas). 

Django est côté serveur. Cela signifie, disons qu'un client accède à l'URL que vous avez une fonction dans les vues qui rend ce qu'il voit et renvoie une réponse au format HTML. Brisons-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/hello signifie une demande à la fonction hello, aller à 127.0.0.1:8000/home renverra le index.html et remplacera toutes les variables comme demandé (vous savez probablement tout cela à ce jour).

Parlons maintenant d'AJAX. Les appels AJAX sont un code côté client qui effectue des demandes asynchrones. Cela semble compliqué, mais cela signifie simplement qu’il fait une demande pour vous en arrière-plan et traite ensuite la réponse. Ainsi, lorsque vous effectuez un appel AJAX pour obtenir 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/hello renverra la même chose que si vous le visitiez. Seulement cette fois, vous l’avez dans une fonction js 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 va à l'URL 127.0.0.1:8000/hello comme si vous aviez ouvert un nouvel onglet et l'aviez fait vous-même.
  2. S'il réussit (code d'état 200), exécutez la fonction succès qui alertera les données reçues.
  3. Si échoue, faire une autre fonction.

Maintenant que se passerait-il ici? Vous obtiendrez une alerte avec «hello world» dedans. Qu'advient-il si vous faites un appel ajax à la maison? Même chose, vous recevrez une alerte indiquant <h1>Hello world, welcome to my awesome site</h1>.

En d'autres termes, il n'y a rien de nouveau sur les appels AJAX. C’est simplement un moyen pour vous de laisser l’utilisateur obtenir des données et des informations sans quitter la page, ce qui permet une conception fluide et très soignée de votre site Web. Quelques directives à prendre en compte:

  1. Apprenez jQuery. Je ne peux insister assez sur ce point. Il va falloir que vous compreniez un peu pour savoir comment gérer les données que vous recevez. Vous aurez également besoin de comprendre quelques syntaxes 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 beaucoup d'exemples où les données envoyées par les vues Django sont en JSON. Je ne suis pas entré dans les détails là-dessus, parce que ce n’est pas important de le fairecomment (il ya beaucoup d’explications qui abondent) et beaucoup plus important de quand. Et la réponse à cette question est: les données JSON sont des données sérialisées. C'est-à-dire des données que vous pouvez manipuler. Comme je l'ai mentionné, un appel AJAX récupérera la réponse comme si l'utilisateur l'avait fait lui-même. Maintenant, disons que vous ne voulez pas jouer avec tout le code HTML, mais que vous voulez plutôt 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), et vous pouvez ensuite le parcourir ou faire autre chose qui supprime la nécessité de filtrer le code HTML inutile.
  3. Ajoute le dernier. Lorsque vous créez une application Web et souhaitez implémenter AJAX, faites-vous plaisir. Tout d'abord, créez l'application dans son intégralité, sans AJAX. Voir que tout fonctionne. Ensuite, et seulement ensuite, 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. Comme les appels de 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 les éléments console.log à 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, rappelez-vous que les demandes de publication dans Django nécessitent le csrf_token. Avec les appels AJAX, vous souhaitez souvent envoyer des données sans actualiser la page. Vous rencontrerez probablement des problèmes avant de vous en souvenir enfin - attendez, vous avez oublié d’envoyer le csrf_token. C'est un obstacle connu pour les débutants dans l'intégration AJAX-Django, mais après avoir appris à le faire jouer à Nice, c'est simple comme bonjour.

C'est tout ce qui me passe à la tête. C'est un vaste sujet, mais oui, il n'y a probablement pas assez d'exemples. Travaillez simplement, lentement, vous finirez par l’obtenir.

566
yuvi

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 au sein de Django (au-delà des js utilisés). L'exemple utilise AjaxableResponseMixin et suppose un modèle 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']

Source: Documentation Django, Gestion des formulaires avec des vues basées sur des classes

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

18
Wtower

Simple et gentil. Vous n'êtes pas obligé de changer d'avis. Bjax gère tous vos liens. Vérifiez 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 code HTML:

$('a').bjax();

Pour plus de réglages, consultez la démo ici: Bjax Demo

7
endur

J'ai essayé d'utiliser AjaxableResponseMixin dans mon projet, mais j'avais reçu le message d'erreur suivant:

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

En effet, CreateView renverra une réponse redirect au lieu de renvoyer un HttpResponse lorsque vous enverrez 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 méthode super.form_valid, appelez simplement la 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
2
Enix

AJAX est le meilleur moyen d'effectuer des tâches asynchrones. Faire des appels asynchrones est une chose courante dans n'importe quel site Web. Nous prendrons un court exemple pour apprendre comment implémenter AJAX dans Django. Nous devons utiliser jQuery pour écrire moins de javascript.

Ceci est Contact example, qui est l'exemple le plus simple que j'utilise pour expliquer les bases de AJAX et de son implémentation dans Django. Nous allons faire la demande POST dans cet exemple. Je suis l'un des exemples de ce post: https://djangopy.org/learn/step-up-guide-to-implement-ajax-in-Django

models.py

Commençons par créer le modèle de Contact, avec les 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 base basée sur les fonctions, mais au lieu de renvoyer avec 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'),
]

template

En passant à la section frontend, restituez le formulaire créé au-dessus de la balise de formulaire, ainsi que csrf_token et le bouton d'envoi. 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 de soumission que nous effectuons une requête ajax de type POST, prenant les données de formulaire et 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 commencer avec AJAX avec Django. Si vous voulez plonger avec plusieurs autres exemples, vous pouvez consulter cet article: https://djangopy.org/learn/ guide-pas-à-mettre en oeuvre-ajax-in-Django

1
Jai Singhal

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

C'est ainsi que j'intégrerais Ajax à Django en 2019 :) Et prenons un exemple concret du moment où nous aurions besoin d'Ajax: - 

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

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 déconseillé et a été remplacé par render et à partir de Django 1.7 au lieu de HttpResponse nous utilisons JsonResponse pour la réponse ajax. Comme il est fourni 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 HttpResponse n’est pas obsolète.

0
Ahtisham