Ajax와 Django 애플리케이션을 어떻게 통합합니까?


264

저는 Django를 처음 사용하고 Ajax를 처음 사용합니다. 두 가지를 통합 해야하는 프로젝트를 진행 중입니다. 나는 그 두 가지의 원리를 이해한다고 믿지만 두 가지에 대한 좋은 설명을 찾지 못했습니다.

누군가 코드베이스가 두 개의 통합으로 어떻게 바뀌어야하는지에 대해 간략하게 설명해 주시겠습니까?

예를 들어, HttpResponseAjax와 함께 계속 사용할 수 있습니까, 아니면 Ajax를 사용하여 응답을 변경해야합니까? 그렇다면 요청에 대한 응답이 어떻게 변경되어야하는지에 대한 예를 제공해 주시겠습니까? 차이가 있다면 반환하는 데이터는 JSON입니다.

답변:


637

이것이 완전히 SO 정신이 아니더라도 시작했을 때 같은 문제가 발생했기 때문에이 질문을 좋아합니다. 그래서 나는 당신에게 빠른 가이드를 줄 것입니다. 분명히 당신은 그들 뒤에있는 원칙을 이해하지 못합니다 (범죄로 생각하지 마십시오. 그렇지 않으면 요청하지 않을 것입니다).

Django는 서버 측 입니다. 즉, 클라이언트가 URL로 이동하면 내부에 함수 views를보고 HTML로 응답을 반환한다는 의미입니다. 예를 들어 보자.

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

가장 간단한 사용법의 예입니다. 간다는 것은 함수에 127.0.0.1:8000/hello대한 요청 을 의미 하며을 반환하고 요청 된대로 모든 변수를 대체합니다 (아마도 지금까지이 모든 것을 알고있을 것입니다).hello()127.0.0.1:8000/homeindex.html

이제 AJAX 에 대해 이야기 해 보자 . AJAX 호출은 비동기 요청을 수행하는 클라이언트 측 코드입니다. 복잡해 보이지만 백그라운드에서 요청을 한 다음 응답을 처리한다는 의미입니다. 따라서 일부 URL에 대해 AJAX 호출을 수행하면 사용자가 해당 위치로 갈 때와 동일한 데이터를 얻게됩니다.

예를 들어, AJAX 호출 127.0.0.1:8000/hello은 방문한 것과 동일한 것을 반환합니다. 이번에는 JavaScript 함수 안에 있으며 원하는대로 처리 할 수 ​​있습니다. 간단한 사용 사례를 살펴 보겠습니다.

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

일반적인 과정은 다음과 같습니다.

  1. 전화는 127.0.0.1:8000/hello마치 새 탭을 열고 직접 수행 한 것처럼 URL 로 이동합니다 .
  2. 성공하면 (상태 코드 200) 성공을위한 기능을 수행하면 수신 된 데이터에 경고합니다.
  3. 실패하면 다른 기능을 수행하십시오.

이제 어떻게 될까요? 'hello world'라는 경고가 표시됩니다. 집에 AJAX 통화를하면 어떻게됩니까? 똑같은 경고 메시지가 나타납니다 <h1>Hello world, welcome to my awesome site</h1>.

다시 말해 AJAX 호출에 대한 새로운 것은 없습니다. 페이지를 떠나지 않고도 사용자가 데이터와 정보를 얻을 수 있도록하는 방법 일뿐 아니라 웹 사이트를 매끄럽고 깔끔하게 디자인 할 수 있습니다. 다음 사항에 유의하십시오.

  1. jQuery를 배우십시오 . 나는 이것을 충분히 강조 할 수 없다. 수신 한 데이터를 처리하는 방법을 이해하려면 약간 이해해야합니다. 또한 기본적인 JavaScript 구문을 이해해야합니다 (파이썬에서 멀지 않은 곳에 익숙해집니다). 저는 jQuery대한 Envato의 비디오 자습서를 강력히 권장합니다. 훌륭하고 올바른 길로 안내 할 것입니다.
  2. JSON을 언제 사용해야합니까? . Django 뷰가 보낸 데이터가 JSON 인 많은 예를 보게 될 것입니다. 나는 그것을 하는 방법 이 중요 하지 않기 때문에 (많은 설명이 풍부하며) when 훨씬 더 중요 하기 때문에 그것에 대해 자세히 설명하지 않았습니다 . 그리고 그 대답은 JSON 데이터는 직렬화 된 데이터입니다. 즉, 조작 할 수있는 데이터입니다. 앞서 언급했듯이 AJAX 호출은 사용자가 직접 수행 한 것처럼 응답을 가져옵니다. 이제 모든 HTML을 엉망으로 만들고 싶지 않고 대신 데이터 (아마도 객체 목록)를 보내려고한다고 가정하십시오. JSON은 객체 (JSON 데이터가 파이썬 사전처럼 보입니다)로 전송 한 다음이를 반복하거나 쓸모없는 html을 통해 걸러야 할 필요가없는 다른 작업을 수행 할 수 있기 때문에 좋습니다.
  3. 마지막에 추가하십시오 . 웹 앱을 빌드하고 AJAX를 구현하려는 경우 자신에게 호의를 베푸십시오. 먼저 AJAX가 전혀없는 전체 앱을 빌드하십시오. 모든 것이 작동하는지 확인하십시오. 그런 다음에 만 AJAX 호출 작성을 시작하십시오. 그것은 많은 과정을 배우는 데 도움이되는 좋은 과정입니다.
  4. 크롬 개발자 도구를 사용하십시오 . AJAX 호출은 백그라운드에서 수행되기 때문에 때때로 디버깅하기가 매우 어렵습니다. 크롬 개발자 도구 (또는 파이어 console.log버그 와 같은 유사한 도구)와 디버깅 할 사항을 사용해야합니다 . 나는 자세히 설명하지 않고 단지 구글을 둘러보고 그것에 대해 알아 낸다. 도움이 될 것입니다.
  5. CSRF 인식 . 마지막으로 Django의 게시물 요청에는가 필요합니다 csrf_token. AJAX 호출을 사용하면 페이지를 새로 고치지 않고 데이터를 여러 번 보내려고합니다. 당신은 아마 그것을 기억하기 전에 약간의 어려움에 직면하게 될 것입니다-기다리십시오 csrf_token. 이것은 AJAX-Django 통합에서 알려진 초보로드 블록이지만 잘 재생하는 방법을 배우면 파이처럼 쉽습니다.

그것이 내 머리에 오는 모든 것입니다. 그것은 광대 한 주제이지만, 아마도 충분한 예가 없을 것입니다. 천천히 길을 따라 가십시오. 서서히 얻을 것입니다.


1
감사. 나는 단순히 당신이있는 곳, 느낌을 알고 있습니다. 채팅에 관해서는-일반적으로 그렇습니다. 그러나 지금은 아닙니다.
yuvi

2
PS 연결 한 비디오는 AJAX 전용 일주일 내내 있습니다. 진심으로, 그들을 통해 가십시오. 그들은있는 거 환상적인
yuvi

감사합니다 @yuvi! AJAX에 대해서도 같은 질문을하고 있습니다. 더구나, AJAX를 언제 사용해야하는지 잘 모르겠습니다. 예를 들어 부트 스트랩 모달 양식 을 처리하기 위해 Javascript가 필요 하지만 AJAX와 관련이 있는지 여부는 이해할 수 없습니다. 그리고 심각하게, 전체 jQuery를 배울 필요 그냥 내가 어떤 간단한 대안이 있는가 :( 투자 수익을 볼 수 없습니다 ... 내 페이지에 팝업이 나타나도록 :( 감사를 다시 대답?.
데이비드을 D.

5
@DavidW. 안녕 데이비드, 나는 내 대답이 당신을 도와 기쁘다. AJAX는 간단한 자바 스크립트로 수행 할 수있는 기술이지만 매우 복잡해질 수 있습니다. jQuery에는 바로 가기가있어 훨씬 쉽게 만들 수 있습니다. Bootstrap의 모달과는 아무런 관련이 없습니다 (원한다면 AJAX를 통해 양식을 가져올 수는 있지만 관련이 없습니다). 어쨌든 천천히 길을 찾아보십시오. jQuery는 요즘 중요하고 매우 기본적이기 때문에 좋은 투자입니다. 장애물에 부딪쳤을 때 SO로 와서 물어보십시오 (이미 답변 된 질문에 대한 의견이 아닌 새 질문을여십시오). 행운을 빕니다!
yuvi

에 대한 귀하의 언급과 관련 csrf_token하여이 방법으로 문제를 해결할 수 있습니까? 예제 함수 ajaxCall()가 있다면 , 전통적인 방법을 사용할 수 있습니다 <form onsubmit='ajaxCall();return false;'>.
ytpillai

22

yuvi의 훌륭한 답변에서 더 나아가 장고 내에서 이것을 처리하는 방법에 대한 작은 구체적인 예를 추가하고 싶습니다 (사용 될 모든 js 제외). 이 예제에서는 AjaxableResponseMixinAuthor 모델을 사용 하고 가정합니다.

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

출처 : 장고 문서, 클래스 기반 뷰를 이용한 폼 처리

Django 버전 1.6에 대한 링크는 더 이상 버전 1.11로 업데이트 할 수 없습니다.


14

허용 된 답변이 꽤 오래되었으므로 새로 작성해야합니다.

2019 년에 Ajax를 Django와 통합하는 방법입니다.

등록 된 사용자 이름을 가진 모델이 있고 Ajax의 도움으로 주어진 사용자 이름이 있는지 알고 싶습니다.

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>   

아약스 :

$('#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)

또한 에는 render_to_response 되지 않으며로 대체 된 렌더링 과 장고 1.7 이후 대신에서 HttpResponse에 우리가 사용 JsonResponse을 아약스 응답. JSON 인코더와 함께 제공되므로 응답 객체를 반환하기 전에 데이터를 직렬화 할 필요 HttpResponse는 없지만 더 이상 사용되지 않습니다.


8

간단하고 좋은. 뷰를 변경할 필요가 없습니다. Bjax는 모든 링크를 처리합니다. 이것을 확인하십시오 : Bjax

용법:

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

마지막으로 html의 HEAD에 이것을 포함하십시오.

$('a').bjax();

더 많은 설정을 원하시면 여기에서 데모를 확인하십시오 : Bjax Demo


18
안녕하세요, 빠른 메모-Django 및 / 또는 AJAX를 배우기 시작한 사람에게 조언하고 싶습니다 . 이것을 사용 하지 마십시오 . 당신은 아무것도 배울 수 없습니다. 즐겨 찾기에 보관하고 AJAX 요청을 직접 작성하십시오. Bjax가 이미 백그라운드에서 작동하는 방식에 익숙해지면 돌아와서 사용하십시오. 이것은 사람들이 코드를 작성하기 위해 어셈블리를 배우라고 말하는 것과는 다릅니다. 순수 JS로 AJAX 요청을 만들 필요가 없습니다. jQuery 만 있으면 전문가가 되려면 최소한 기본 지식이 필요하기 때문입니다. 있어야합니다. 건배
유비

5

AJAX는 비동기 작업을 수행하는 가장 좋은 방법입니다. 비동기식 호출은 모든 웹 사이트 구축에서 일반적으로 사용되는 것입니다. Django에서 AJAX를 구현하는 방법을 배우는 간단한 예를 들어 보겠습니다. 자바 스크립트를 적게 작성하려면 jQuery를 사용해야합니다.

이것은 가장 간단한 예인 Contact 예입니다. AJAX의 기본 사항과 Django에서의 구현을 설명하는 데 사용하고 있습니다. 이 예에서는 POST 요청을합니다. 이 게시물의 예 중 하나를 따르고 있습니다 : https://djangopy.org/learn/step-up-guide-to-implement-ajax-in-django

models.py

먼저 기본 세부 정보가 포함 된 Contact 모델을 작성하겠습니다.

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

위 모델의 양식을 작성하십시오.

from django import forms
from .models import Contact

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

views.py

뷰는 기본 함수 기반 작성 뷰와 비슷해 보이지만 렌더로 리턴하는 대신 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

위 뷰의 경로를 만들어 봅시다.

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

주형

프론트 엔드 섹션으로 이동하여 csrf_token 및 제출 단추와 함께 양식 태그를 둘러싸는 위에 작성된 양식을 렌더링하십시오. 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 부분에 대해 이야기하겠습니다. 양식 제출에서 POST 유형의 ajax 요청을 작성하고 양식 데이터를 가져 와서 서버 측으로 보냅니다.

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

이것은 django와 함께 AJAX를 시작하는 기본 예일뿐입니다. 몇 가지 예를 더보고 싶다면이 기사를 참조하십시오. https://djangopy.org/learn/step-up-guide-to- 장고를 구현하다


2

내 프로젝트에서 AjaxableResponseMixin 을 사용하려고 시도했지만 다음과 같은 오류 메시지가 나타납니다.

잘못 구성됨 : 리디렉션 할 URL이 없습니다. URL을 제공하거나 모델에서 get_absolute_url 메소드를 정의하십시오.

이는 JSON 요청을 브라우저에 보낼 때 CreateView가 HttpResponse를 반환하는 대신 리디렉션 응답 을 반환하기 때문 입니다. 그래서에 몇 가지 사항을 변경했습니다 AjaxableResponseMixin. 요청이 ajax 요청 인 경우 super.form_valid메소드를 호출하지 않고 form.save()직접 호출하십시오 .

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

장고를 사용할 때 :

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

오래된 데이터를 유지하려면 Ajax없이 수행 할 수 있습니다. (페이지가 새로 고침됩니다)

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.

또는 Ajax로 할 수 있습니다 (페이지가 새로 고침되지 않습니다)

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

Ajax를 사용하는 경우 다음을 수행해야합니다.

  1. URL1을 사용하여 HTML 페이지를 초기화합니다 (일반적으로 Django 템플릿에 의한 초기 페이지). 그런 다음 서버는 클라이언트에게 html 페이지를 보냅니다.
  2. URL2를 사용하여 Ajax를 사용하여 서버와 통신하십시오. 그런 다음 서버는 클라이언트에게 데이터 구조체를 보냅니다.

Django는 Ajax와 다릅니다. 그 이유는 다음과 같습니다.

  • 클라이언트로 돌아가는 것은 다릅니다. Django의 경우 HTML 페이지입니다. Ajax의 경우 data struct입니다. 
  • 장고는 무언가를 만드는 데 능숙하지만 한 번만 만들 수 있으며 아무것도 바꿀 수 없습니다. 장고는 애니메이션과 같으며 많은 그림으로 구성되어 있습니다. 대조적으로 Ajax는 sth를 만드는 데는 좋지 않지만 html 페이지에서 sth를 변경하는 데는 좋습니다.

내 의견으로는, 어디서나 아약스를 사용하고 싶다면. 처음에 데이터가있는 페이지를 초기화해야하는 경우 Ajangx와 함께 Django를 사용할 수 있습니다. 그러나 어떤 경우에는 서버에서 아무것도없는 정적 페이지 만 필요하며 Django 템플릿을 사용할 필요가 없습니다.

Ajax가 최선의 방법이라고 생각하지 않는다면. 장고 템플릿을 사용하여 애니메이션과 같은 모든 것을 할 수 있습니다.

(내 영어 실력이 좋지 않습니다)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.