Come posso integrare Ajax con le applicazioni Django?


264

Sono nuovo di Django e abbastanza nuovo di Ajax. Sto lavorando a un progetto in cui ho bisogno di integrare i due. Credo di comprendere i principi alla base di entrambi, ma non ho trovato una buona spiegazione dei due insieme.

Qualcuno potrebbe darmi una rapida spiegazione di come la base di codice deve cambiare con i due che si integrano insieme?

Ad esempio, posso ancora utilizzare l' HttpResponseAjax o le mie risposte devono cambiare con l'uso dell'Ajax? In tal caso, potresti fornire un esempio di come devono cambiare le risposte alle richieste? Se fa alcuna differenza, i dati che sto restituendo sono JSON.

Risposte:


637

Anche se questo non è interamente nello spirito SO, adoro questa domanda, perché ho avuto lo stesso problema quando ho iniziato, quindi ti darò una guida rapida. Ovviamente non capisci i principi dietro di loro (non prenderlo come un'offesa, ma se lo facessi non te lo chiederesti).

Django è lato server . Significa, ad esempio, che un client passa a un URL, al suo interno ha una funzione viewsche rende ciò che vede e restituisce una risposta in HTML. Dividiamolo in esempi:

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

Questo è un esempio del più semplice degli usi. Andare a 127.0.0.1:8000/hellosignifica una richiesta alla hello()funzione, andare a 127.0.0.1:8000/homerestituirà index.htmle sostituirà tutte le variabili come richiesto (probabilmente saprete già tutto questo).

Ora parliamo di AJAX . Le chiamate AJAX sono codice lato client che esegue richieste asincrone. Sembra complicato, ma significa semplicemente che ti fa una richiesta in background e quindi gestisce la risposta. Quindi, quando esegui una chiamata AJAX per alcuni URL, ottieni gli stessi dati che otterresti quando un utente si reca in quel luogo.

Ad esempio, una chiamata AJAX 127.0.0.1:8000/hellorestituirà la stessa cosa che se la visitassi. Solo che questa volta ce l'hai all'interno di una funzione JavaScript e puoi gestirla come preferisci. Diamo un'occhiata a un semplice caso d'uso:

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

Il processo generale è questo:

  1. La chiamata va all'URL 127.0.0.1:8000/hellocome se avessi aperto una nuova scheda e l'hai fatto tu stesso.
  2. Se ha esito positivo (codice di stato 200), eseguire correttamente la funzione, che avviserà i dati ricevuti.
  3. In caso contrario, eseguire una funzione diversa.

Cosa sarebbe successo qui? Riceverai un avviso con "ciao mondo". Cosa succede se si effettua una chiamata AJAX a casa? Stessa cosa, riceverai un avviso indicante <h1>Hello world, welcome to my awesome site</h1>.

In altre parole: non c'è nulla di nuovo nelle chiamate AJAX. Sono solo un modo per consentire all'utente di ottenere dati e informazioni senza uscire dalla pagina e consentono un design fluido e molto ordinato del tuo sito Web. Alcune linee guida che dovresti prendere in considerazione:

  1. Scopri jQuery . Non posso sottolineare abbastanza. Dovrai capirlo un po 'per sapere come gestire i dati che ricevi. Dovrai anche comprendere alcune sintassi JavaScript di base (non lontano da Python, ti ci abituerai). Consiglio vivamente i tutorial video di Envato per jQuery , sono fantastici e ti metteranno sulla buona strada.
  2. Quando usare JSON? . Vedrai molti esempi in cui i dati inviati dalle viste Django sono in JSON. Non sono entrato nei dettagli, perché non è importante come farlo (ci sono molte spiegazioni abbondanti) e molto più importante quando . E la risposta è: i dati JSON sono dati serializzati. Cioè, i dati che puoi manipolare. Come ho già detto, una chiamata AJAX recupererà la risposta come se l'utente l'avesse fatto da solo. Ora dì che non vuoi scherzare con tutto l'html e invece vuoi inviare dati (forse un elenco di oggetti). JSON è utile per questo, perché lo invia come oggetto (i dati JSON sembrano un dizionario Python), quindi puoi iterare su di esso o fare qualcos'altro che elimina la necessità di setacciare HTML inutili.
  3. Aggiungilo per ultimo . Quando crei un'app Web e desideri implementare AJAX, fatti un favore. Innanzitutto, crea l'intera app completamente priva di qualsiasi AJAX. Vedi che tutto funziona. Quindi, e solo allora, inizia a scrivere le chiamate AJAX. È un buon processo che ti aiuta anche a imparare molto.
  4. Utilizza gli strumenti per sviluppatori di Chrome . Poiché le chiamate AJAX vengono eseguite in background, a volte è molto difficile eseguirne il debug. Dovresti usare gli strumenti di sviluppo di Chrome (o strumenti simili come firebug) e console.logcose per eseguire il debug. Non spiegherò in dettaglio, basta google in giro e scoprirlo. Ti sarebbe molto utile.
  5. Consapevolezza CSRF . Infine, ricorda che le richieste di post in Django richiedono il csrf_token. Con le chiamate AJAX, molte volte ti piacerebbe inviare dati senza aggiornare la pagina. Probabilmente dovrai affrontare alcuni problemi prima di ricordartelo finalmente: aspetta, hai dimenticato di inviare il csrf_token. Questo è un noto blocco per principianti nell'integrazione AJAX-Django, ma dopo aver imparato a farlo funzionare bene, è facile come una torta.

Questo è tutto ciò che mi viene in mente. È un argomento vasto, ma sì, probabilmente non ci sono abbastanza esempi là fuori. Lavora lì, lentamente, alla fine ce la farai.


1
Grazie. Sono semplicemente stato dove sei, conosco la sensazione. Per quanto riguarda le chat - generalmente sì, ma non adesso (anche, per domande specifiche hai ... beh ... l'intero SO).
yuvi

2
PS i video che ho collegato hanno un'intera settimana dedicata ad AJAX. Seriamente, esaminali. Sono fantastici
yuvi

Grazie @yuvi per questo! Mi sto ponendo la stessa domanda su AJAX. Inoltre, non sono sicuro quando devo usare AJAX o no. Ad esempio, capisco che avrò bisogno di Javascript per gestire i moduli modali Bootstrap, ma non capisco se è legato ad AJAX o no. E seriamente, dover imparare l'intero Jquery solo per far apparire un pop-up nella mia pagina ... Non riesco a vedere il ritorno sull'investimento :( C'è qualche alternativa più semplice? :( Grazie ancora per la tua risposta.
David D.

5
@DavidW. Ciao David, sono felice che la mia risposta ti abbia aiutato. AJAX è una tecnica, che puoi fare con javascript semplice, ma può diventare molto complicato. jQuery ha semplicemente delle scorciatoie che lo rendono molto più semplice. Non ha nulla a che fare con il modale di Bootstrap (se lo desideri, puoi recuperare i moduli tramite AJAX, ma per il resto non è correlato). Ad ogni modo, ti consiglio vivamente di provare a capire lentamente la tua strada. jQuery è importante e molto semplice in questi giorni, quindi un buon investimento lì. Quando raggiungi un blocco stradale, vieni su SO e chiedi (non qui nei commenti di una domanda già risposta, aprine una nuova). In bocca al lupo!
yuvi,

Per quanto riguarda la tua menzione csrf_token, possiamo aggirare questo metodo? Se avessimo una funzione di esempio, ajaxCall()possiamo semplicemente usare il metodo tradizionale di qualcosa del genere <form onsubmit='ajaxCall();return false;'>, giusto?
ytpillai,

22

Oltre all'eccellente risposta di yuvi, vorrei aggiungere un piccolo esempio specifico su come gestirlo all'interno di Django (oltre ogni js che verrà utilizzato). L'esempio utilizza AjaxableResponseMixine presuppone un modello di autore.

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

Fonte: documentazione Django, gestione moduli con viste basate su classi

Il collegamento alla versione 1.6 di Django non è più disponibile aggiornato alla versione 1.11


14

Sto scrivendo questo perché la risposta accettata è piuttosto vecchia, ha bisogno di un aggiornamento.

Quindi è così che integrerei Ajax con Django nel 2019 :) E facciamo un esempio reale di quando avremmo bisogno di Ajax: -

Diciamo che ho un modello con nomi utente registrati e con l'aiuto di Ajax voglio sapere se esiste un determinato nome utente.

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)

Inoltre render_to_response che è deprecato ed è stato sostituito da render e da Django 1.7 in poi invece di HttpResponse usiamo JsonResponse per la risposta ajax. Perché viene fornito con un codificatore JSON, quindi non è necessario serializzare i dati prima di restituire l'oggetto risposta ma HttpResponsenon è obsoleto.


8

Semplice e piacevole. Non è necessario modificare le visualizzazioni. Bjax gestisce tutti i tuoi collegamenti. Dai un'occhiata: Bjax

Uso:

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

Infine, includi questo nell'HEAD del tuo html:

$('a').bjax();

Per ulteriori impostazioni, controlla la demo qui: Bjax Demo


18
Ciao, nota veloce - Voglio avvisare chiunque abbia appena iniziato a studiare Django e \ o AJAX - per favore non usarlo. Non imparerai nulla. Conservalo tra i tuoi preferiti e crea le tue richieste AJAX da solo. Torna e usa Bjax quando hai già familiarità con il funzionamento in background. Non è come dire alle persone di imparare Assembly per programmare: non è necessario creare le tue richieste AJAX con JS puro, solo jQuery, perché se vuoi essere un professionista, questa è la conoscenza di base minima che bisogno di avere. Saluti
yuvi,

5

AJAX è il modo migliore per eseguire attività asincrone. Effettuare chiamate asincrone è qualcosa di comune in uso in qualsiasi costruzione di siti Web. Faremo un breve esempio per imparare come implementare AJAX in Django. Dobbiamo usare jQuery per scrivere meno javascript.

Questo è l' esempio di Contact , che è l'esempio più semplice, che sto usando per spiegare le basi di AJAX e la sua implementazione in Django. In questo esempio faremo una richiesta POST. Sto seguendo uno degli esempi di questo post: https://djangopy.org/learn/step-up-guide-to-implement-ajax-in-django

models.py

Per prima cosa creiamo il modello di contatto, con i dettagli di 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

Crea il modulo per il modello sopra.

from django import forms
from .models import Contact

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

views.py

Le viste sono simili alla vista di creazione basata sulle funzioni di base, ma invece di tornare con render, stiamo usando la risposta 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

Creiamo il percorso della vista sopra.

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

modello

Passando alla sezione frontend, renderizza il modulo che è stato creato sopra il tag del modulo allegato insieme a csrf_token e il pulsante di invio. Nota che abbiamo incluso la libreria 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

Parliamo ora della parte javascript, sul modulo invia stiamo facendo una richiesta Ajax di tipo POST, prendendo i dati del modulo e inviandoli al lato server.

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

Questo è solo un esempio di base per iniziare con AJAX con django, se vuoi immergerti con molti altri esempi, puoi leggere questo articolo: https://djangopy.org/learn/step-up-guide-to- attuare-ajax-in-django


2

Ho provato ad usare AjaxableResponseMixin nel mio progetto, ma ho finito con il seguente messaggio di errore:

ImproprlyConfigured: nessun URL a cui reindirizzare. Fornire un URL o definire un metodo get_absolute_url sul modello.

Questo perché CreateView restituirà una risposta di reindirizzamento invece di restituire un HttpResponse quando si invia una richiesta JSON al browser. Quindi ho apportato alcune modifiche a AjaxableResponseMixin. Se la richiesta è una richiesta Ajax, non chiamerà il super.form_validmetodo, basta chiamare form.save()direttamente.

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

0

Quando usiamo 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
----------------------------

Se vuoi conservare vecchi dati, puoi farlo senza Ajax. (La pagina verrà aggiornata)

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.

Oppure puoi fare con Ajax (la pagina non verrà aggiornata)

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

Se si utilizza Ajax, è necessario eseguire queste operazioni:

  1. Iniziale una pagina HTML usando URL1 (di solito iniziamo la pagina dal modello Django). E quindi il server invia al client una pagina html.
  2. Utilizzare Ajax per comunicare con il server tramite URL2. E quindi il server invia al client una struttura dati.

Django è diverso dall'Ajax. La ragione di ciò è la seguente:

  • La cosa che ritorna al client è diversa. Il caso di Django è la pagina HTML. Il caso di Ajax è la struttura dei dati. 
  • Django è bravo a creare qualcosa, ma può creare solo una volta, non può cambiare nulla. Django è come un anime, composto da molte immagini. Al contrario, Ajax non è bravo a creare sth ma è bravo a cambiare sth nella pagina html esistente.

Secondo me, se desideri usare Ajax ovunque. quando devi prima inizializzare una pagina con i dati, puoi usare Django con Ajax. Ma in alcuni casi, hai solo bisogno di una pagina statica senza nulla dal server, non è necessario utilizzare il modello Django.

Se non pensi che l'Ajax sia la migliore pratica. puoi usare il modello Django per fare tutto, come gli anime.

(Il mio inglese non è buono)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.