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.
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:
127.0.0.1:8000/hello
comme si vous aviez ouvert un nouvel onglet et l'aviez fait vous-même.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:
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.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.
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
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
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
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
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.