Como integro o Ajax aos aplicativos Django?

264

Eu sou novo no Django e bastante novo no Ajax. Estou trabalhando em um projeto em que preciso integrar os dois. Acredito que compreendo os princípios por trás dos dois, mas não encontrei uma boa explicação para os dois juntos.

Alguém poderia me dar uma explicação rápida de como a base de código deve mudar com a integração dos dois?

Por exemplo, ainda posso usar o HttpResponseAjax ou minhas respostas precisam mudar com o uso do Ajax? Em caso afirmativo, você poderia fornecer um exemplo de como as respostas às solicitações devem mudar? Se fizer alguma diferença, os dados que estou retornando são JSON.

tjons
fonte

Respostas:

637

Mesmo que isso não esteja inteiramente no espírito da SO, eu amo essa pergunta, porque tive o mesmo problema quando comecei, por isso darei um guia rápido. Obviamente, você não entende os princípios por trás deles (não tome isso como uma ofensa, mas se o fizesse, não estaria perguntando).

O Django é do lado do servidor . Isso significa que, digamos que um cliente acesse um URL, você tem uma função viewsque renderiza o que ele vê e retorna uma resposta em HTML. Vamos dividir em exemplos:

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

Esse é um exemplo do uso mais simples. Ir para 127.0.0.1:8000/hellosignifica uma solicitação para a hello()função, vai 127.0.0.1:8000/homeretornar index.htmle substituir todas as variáveis ​​conforme solicitado (você provavelmente já sabe tudo isso agora).

Agora vamos falar sobre o AJAX . As chamadas AJAX são um código do lado do cliente que faz solicitações assíncronas. Isso parece complicado, mas simplesmente significa que ele faz uma solicitação para você em segundo plano e depois lida com a resposta. Portanto, quando você faz uma chamada AJAX para algum URL, obtém os mesmos dados que obteria quando um usuário fosse para esse local.

Por exemplo, uma chamada AJAX para 127.0.0.1:8000/helloretornará a mesma coisa que faria se você a visitasse. Só que desta vez, você a possui dentro de uma função JavaScript e pode lidar com ela da maneira que desejar. Vejamos um caso de uso simples:

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

O processo geral é este:

  1. A chamada vai para o URL 127.0.0.1:8000/hellocomo se você tivesse aberto uma nova guia e tivesse feito isso sozinho.
  2. Se for bem-sucedido (código de status 200), execute a função para obter sucesso, o que alertará os dados recebidos.
  3. Se falhar, execute uma função diferente.

Agora o que aconteceria aqui? Você receberia um alerta com 'olá mundo'. O que acontece se você fizer uma ligação AJAX para casa? A mesma coisa, você receberá um alerta informando <h1>Hello world, welcome to my awesome site</h1>.

Em outras palavras - não há novidades nas chamadas AJAX. Eles são apenas uma maneira de permitir que o usuário obtenha dados e informações sem sair da página e contribui para um design suave e muito elegante do seu site. Algumas diretrizes que você deve tomar nota:

  1. Aprenda jQuery . Não posso enfatizar isso o suficiente. Você precisará entender um pouco para saber como lidar com os dados que recebe. Você também precisará entender algumas sintaxes básicas do JavaScript (não muito longe do python, você se acostumará). Eu recomendo fortemente os tutoriais em vídeo da Envato para jQuery , eles são ótimos e colocam você no caminho certo.
  2. Quando usar o JSON? . Você verá muitos exemplos em que os dados enviados pelas visualizações do Django estão em JSON. Eu não entrei em detalhes sobre isso, porque não é importante como fazê-lo (há muitas explicações em abundância) e muito mais importante quando . E a resposta é: dados JSON são dados serializados. Ou seja, dados que você pode manipular. Como mencionei, uma chamada AJAX buscará a resposta como se o usuário tivesse feito isso sozinho. Agora diga que você não quer mexer com todo o html e, em vez disso, deseja enviar dados (talvez uma lista de objetos). O JSON é bom para isso, porque ele é enviado como um objeto (os dados JSON se parecem com um dicionário python) e você pode iterá-lo ou fazer outra coisa que elimine a necessidade de examinar o html inútil.
  3. Adicione por último . Quando você cria um aplicativo Web e deseja implementar o AJAX - faça um favor a si mesmo. Primeiro, crie o aplicativo inteiro completamente desprovido de qualquer AJAX. Veja que tudo está funcionando. Então, e somente então, comece a escrever as chamadas AJAX. Esse é um bom processo que ajuda você a aprender muito também.
  4. Use as ferramentas de desenvolvedor do chrome . Como as chamadas AJAX são feitas em segundo plano, às vezes é muito difícil depurá-las. Você deve usar as ferramentas de desenvolvedor do Chrome (ou ferramentas semelhantes, como o firebug) e outras console.logcoisas para depurar. Não vou explicar em detalhes, basta pesquisar no Google e descobrir mais sobre isso. Seria muito útil para você.
  5. Consciência do CSRF . Finalmente, lembre-se de que solicitações de postagem no Django requerem o csrf_token. Com chamadas AJAX, muitas vezes você deseja enviar dados sem atualizar a página. Você provavelmente enfrentará alguns problemas antes de finalmente se lembrar disso - espere, esqueceu de enviar o csrf_token. Esse é um obstáculo conhecido para iniciantes na integração AJAX-Django, mas depois que você aprende como fazê-lo funcionar bem, é fácil.

Isso é tudo que vem à minha cabeça. É um assunto vasto, mas sim, provavelmente não há exemplos suficientes por aí. Apenas trabalhe seu caminho até lá, devagar, você o conseguirá eventualmente.

yuvi
fonte
1
Obrigado. Eu simplesmente estive onde você está, conheço o sentimento. Quanto ao bate-papo - geralmente sim, mas não agora (também, para perguntas específicas que você tem ... bem ... a totalidade do SO).
Yuvi
2
PS os vídeos que eu vinculei têm uma semana inteira dedicada ao AJAX. Sério, passe por eles. Eles são fantásticos
yuvi
Obrigado @yuvi por isso! Estou me fazendo a mesma pergunta sobre o AJAX. Além disso, não tenho certeza de quando devo usar o AJAX ou não. Por exemplo, eu entendo que precisarei de algum Javascript para manipular os formulários modais do Bootstrap, mas não entendo se está relacionado ao AJAX ou não. E sério, ter que aprender o Jquery inteiro apenas para fazer aparecer uma pop-up na minha página ... Não consigo ver o retorno do investimento :( Existe alguma alternativa mais simples? :( Obrigado novamente por sua resposta.
David D.
5
@DavidW. Olá David, estou feliz que minha resposta tenha ajudado. AJAX é uma técnica, que você pode fazer com javascript simples, mas pode se tornar muito complicado. O jQuery simplesmente possui atalhos que facilitam muito. Não tem nada a ver com o modal do Bootstrap (você pode buscar formulários através do AJAX, se desejar, mas não tem relação alguma). Enfim, eu sugiro que você tente descobrir o seu caminho lentamente. O jQuery é importante e muito básico atualmente, portanto, é um bom investimento. Quando você encontrar um obstáculo, vá para o SO e pergunte (não aqui nos comentários de uma pergunta já respondida, abra uma nova). Boa sorte!
Yuvi 26/05
Em relação à sua menção sobre csrf_token, podemos contornar esse método? Se tivéssemos uma função de exemplo ajaxCall(), podemos simplesmente usar o método tradicional de algo como <form onsubmit='ajaxCall();return false;'>, certo?
precisa saber é
22

Além da excelente resposta do yuvi, gostaria de adicionar um pequeno exemplo específico sobre como lidar com isso no Django (além de qualquer js que será usado). O exemplo usa AjaxableResponseMixine assume um 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 (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: documentação do Django, manipulação de formulários com visualizações baseadas em classe

O link para a versão 1.6 do Django não está mais disponível, atualizado para a versão 1.11

Wtower
fonte
14

Estou escrevendo isso porque a resposta aceita é bastante antiga, precisa de uma atualização.

Então é assim que eu integraria o Ajax ao Django em 2019 :) E vamos dar um exemplo real de quando precisaríamos do Ajax: -

Digamos que eu tenho um modelo com nomes de usuário registrados e com a ajuda do Ajax, quero saber se existe um determinado nome de usuário.

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)

Também render_to_response que está obsoleto e foi substituído pelo render e a partir do Django 1.7 em vez de HttpResponse , usamos JsonResponse para resposta ajax. Como ele vem com um codificador JSON, você não precisa serializar os dados antes de retornar o objeto de resposta, mas HttpResponsenão é preterido.

Ahtisham
fonte
8

Simples e agradável. Você não precisa alterar seus pontos de vista. O Bjax lida com todos os seus links. Confira: Bjax

Uso:

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

Por fim, inclua isso na CABEÇA do seu html:

$('a').bjax();

Para mais configurações, confira a demonstração aqui: Bjax Demo

suportar
fonte
18
Olá, nota rápida - eu quero aconselhar quem está apenas começando a aprender Django e \ ou AJAX - por favor , não use isso. Você não aprenderá nada. Mantenha-o nos seus favoritos e crie suas solicitações AJAX por conta própria. Volte e use o Bjax quando você já estiver familiarizado com o funcionamento em segundo plano. Não é como dizer para as pessoas aprenderem Assembly para codificar - você não precisa criar suas solicitações AJAX com JS puro, apenas jQuery, porque se você quiser ser profissional, esse é o conhecimento básico mínimo que você precisará. Precisa ter. Cheers
yuvi
5

O AJAX é a melhor maneira de executar tarefas assíncronas. Fazer chamadas assíncronas é algo comum em qualquer construção de site. Vamos dar um pequeno exemplo para aprender como podemos implementar o AJAX no Django. Precisamos usar o jQuery para escrever menos javascript.

Este é o exemplo de contato , que é o exemplo mais simples que estou usando para explicar o básico do AJAX e sua implementação no Django. Faremos uma solicitação POST neste exemplo. Estou seguindo um dos exemplos deste post: https://djangopy.org/learn/step-up-guide-to-implement-ajax-in-django

models.py

Vamos primeiro criar o modelo de contato, com detalhes 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

Crie o formulário para o modelo acima.

from django import forms
from .models import Contact

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

views.py

As visualizações parecem semelhantes à visualização de criação baseada em função básica, mas em vez de retornar com renderização, estamos usando a resposta 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 criar a rota da vista acima.

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

Movendo-se para a seção frontend, renderize o formulário que foi criado acima da tag de formulário anexada, juntamente com o botão csrf_token and submit. Observe que incluímos a biblioteca 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

Vamos agora falar sobre a parte javascript, no envio do formulário, estamos fazendo uma solicitação ajax do tipo POST, pegando os dados do formulário e enviando para o lado do 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 é apenas um exemplo básico para começar a usar o AJAX com o django. Se você quiser se aprofundar em vários outros exemplos, poderá seguir este artigo: https://djangopy.org/learn/step-up-guide-to- implement-ajax-in-django

Jai Singhal
fonte
2

Eu tentei usar AjaxableResponseMixin no meu projeto, mas acabei com a seguinte mensagem de erro:

ImproperlyConfigured: nenhum URL para o qual redirecionar. Forneça um URL ou defina um método get_absolute_url no Modelo.

Isso ocorre porque o CreateView retornará uma resposta de redirecionamento em vez de retornar um HttpResponse quando você enviar uma solicitação JSON para o navegador. Então, eu fiz algumas alterações no AjaxableResponseMixin. Se a solicitação for ajax, ela não chamará o super.form_validmétodo, basta chamar form.save()diretamente.

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
fonte
0

Quando usamos o 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 você deseja manter os dados antigos, pode fazê-lo sem o Ajax. (A página será atualizada)

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 você pode fazer com o Ajax (a página não será atualizada)

--------------------------
<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 você usa o Ajax, deve fazer o seguinte:

  1. Inicialize uma página HTML usando URL1 (geralmente inicializamos a página pelo modelo do Django). E então o servidor envia ao cliente uma página html.
  2. Use o Ajax para se comunicar com o servidor usando o URL2. E então o servidor envia ao cliente uma estrutura de dados.

O Django é diferente do Ajax. A razão para isso é a seguinte:

  • A coisa que retorna ao cliente é diferente. O caso do Django é uma página HTML. O caso do Ajax é estrutura de dados. 
  • O Django é bom em criar algo, mas só pode criar uma vez, não pode mudar nada. Django é como anime, consiste em muitas fotos. Por outro lado, o Ajax não é bom em criar sth, mas bom em mudar sth na página html existente.

Na minha opinião, se você gostaria de usar o ajax em qualquer lugar. quando você precisa inicializar uma página com dados primeiro, você pode usar o Django com o Ajax. Mas, em alguns casos, você só precisa de uma página estática sem nada do servidor, não precisa usar o modelo do Django.

Se você não acha que o Ajax é a melhor prática. você pode usar o modelo do Django para fazer tudo, como anime.

(Meu inglês não é bom)

kyakya
fonte