Làm cách nào để tích hợp Ajax với các ứng dụng Django?


264

Tôi mới biết về Django và khá mới với Ajax. Tôi đang làm việc trên một dự án mà tôi cần tích hợp cả hai. Tôi tin rằng tôi hiểu các nguyên tắc đằng sau cả hai, nhưng chưa tìm thấy lời giải thích tốt cho cả hai.

Ai đó có thể cho tôi một lời giải thích nhanh về cách codebase phải thay đổi khi hai người họ hòa nhập với nhau không?

Ví dụ: tôi vẫn có thể sử dụng HttpResponsevới Ajax hay các phản hồi của tôi có phải thay đổi khi sử dụng Ajax không? Nếu vậy, bạn có thể vui lòng cung cấp một ví dụ về cách các câu trả lời cho các yêu cầu phải thay đổi không? Nếu nó làm cho bất kỳ sự khác biệt, dữ liệu tôi đang trả lại là JSON.

Câu trả lời:


637

Mặc dù điều này không hoàn toàn theo tinh thần SO, tôi thích câu hỏi này, bởi vì tôi đã gặp rắc rối tương tự khi tôi bắt đầu, vì vậy tôi sẽ hướng dẫn nhanh cho bạn. Rõ ràng là bạn không hiểu các nguyên tắc đằng sau chúng (đừng coi đó là một hành vi phạm tội, nhưng nếu bạn đã không yêu cầu).

Django là phía máy chủ . Điều đó có nghĩa là, giả sử một khách hàng truy cập URL, bạn có một chức năng bên trongviews hiển thị những gì anh ta nhìn thấy và trả về phản hồi trong HTML. Hãy chia nó thành các ví dụ:

lượt xem:

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>

url:

url(r'^hello/', 'myapp.views.hello'),
url(r'^home/', 'myapp.views.home'),

Đó là một ví dụ về cách sử dụng đơn giản nhất. Đi đến 127.0.0.1:8000/hellocó nghĩa là một yêu cầu cho hello()chức năng, 127.0.0.1:8000/homesẽ trả lạiindex.html và thay thế tất cả các biến như đã hỏi (bây giờ bạn có thể biết tất cả điều này).

Bây giờ hãy nói về AJAX . Các cuộc gọi AJAX là mã phía máy khách thực hiện các yêu cầu không đồng bộ. Nghe có vẻ phức tạp, nhưng nó đơn giản có nghĩa là nó thực hiện một yêu cầu cho bạn trong nền và sau đó xử lý phản hồi. Vì vậy, khi bạn thực hiện cuộc gọi AJAX cho một số URL, bạn sẽ nhận được cùng một dữ liệu bạn sẽ nhận được khi người dùng đến địa điểm đó.

Ví dụ, một cuộc gọi AJAX 127.0.0.1:8000/hellosẽ trả lại điều tương tự như khi bạn truy cập nó. Chỉ lần này, bạn có nó bên trong một hàm JavaScript và bạn có thể xử lý nó theo cách bạn muốn. Hãy xem xét một trường hợp sử dụng đơn giản:

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

Quy trình chung là thế này:

  1. Cuộc gọi đến URL 127.0.0.1:8000/hellonhư thể bạn đã mở một tab mới và tự thực hiện.
  2. Nếu nó thành công (mã trạng thái 200), hãy thực hiện chức năng để thành công, nó sẽ cảnh báo dữ liệu nhận được.
  3. Nếu thất bại, làm một chức năng khác.

Bây giờ chuyện gì sẽ xảy ra ở đây? Bạn sẽ nhận được một cảnh báo với 'xin chào thế giới' trong đó. Điều gì xảy ra nếu bạn thực hiện cuộc gọi AJAX đến nhà? Điều tương tự, bạn sẽ nhận được một cảnh báo nêu rõ <h1>Hello world, welcome to my awesome site</h1>.

Nói cách khác - không có gì mới về các cuộc gọi AJAX. Chúng chỉ là một cách để bạn cho phép người dùng lấy dữ liệu và thông tin mà không cần rời khỏi trang, và nó làm cho một thiết kế trơn tru và rất gọn gàng của trang web của bạn. Một vài hướng dẫn bạn cần lưu ý:

  1. Tìm hiểu jQuery . Tôi không thể nhấn mạnh điều này đủ. Bạn sẽ phải hiểu nó một chút để biết cách xử lý dữ liệu bạn nhận được. Bạn cũng cần hiểu một số cú pháp JavaScript cơ bản (không xa python, bạn sẽ quen với nó). Tôi thực sự khuyên bạn nên hướng dẫn bằng video của Envato cho jQuery , chúng rất tuyệt và sẽ đưa bạn đi đúng hướng.
  2. Khi nào nên sử dụng JSON? . Bạn sẽ thấy rất nhiều ví dụ trong đó dữ liệu được gửi bởi các khung nhìn Django trong JSON. Tôi đã không đi sâu vào chi tiết về điều đó, bởi vì nó không quan trọng bằng cách nào để làm điều đó (có rất nhiều lời giải thích đầy đủ) và quan trọng hơn rất nhiều khi . Và câu trả lời cho điều đó là - dữ liệu JSON là dữ liệu tuần tự. Đó là, dữ liệu bạn có thể thao tác. Giống như tôi đã đề cập, một cuộc gọi AJAX sẽ lấy phản hồi như thể người dùng tự thực hiện. Bây giờ hãy nói rằng bạn không muốn gây rối với tất cả các html và thay vào đó muốn gửi dữ liệu (có thể là một danh sách các đối tượng). JSON tốt cho việc này, bởi vì nó gửi nó dưới dạng một đối tượng (dữ liệu JSON trông giống như một từ điển python), và sau đó bạn có thể lặp lại nó hoặc làm một cái gì đó khác mà không cần phải lọc qua html vô dụng.
  3. Thêm nó cuối cùng . Khi bạn xây dựng một ứng dụng web và muốn triển khai AJAX - hãy tự giúp mình. Đầu tiên, xây dựng toàn bộ ứng dụng hoàn toàn không có bất kỳ AJAX nào. Xem mọi thứ đang hoạt động. Sau đó, và chỉ sau đó, bắt đầu viết các cuộc gọi AJAX. Đó là một quá trình tốt giúp bạn học hỏi rất nhiều.
  4. Sử dụng các công cụ phát triển của chrome . Vì các cuộc gọi AJAX được thực hiện ở chế độ nền nên đôi khi rất khó để gỡ lỗi chúng. Bạn nên sử dụng các công cụ dành cho nhà phát triển chrome (hoặc các công cụ tương tự như fireorms) và console.lognhững thứ để gỡ lỗi. Tôi sẽ không giải thích chi tiết, chỉ cần google xung quanh và tìm hiểu về nó. Nó sẽ rất hữu ích cho bạn.
  5. Nhận thức về CSRF . Cuối cùng, hãy nhớ rằng yêu cầu bài trong Django yêu cầu csrf_token. Với các cuộc gọi AJAX, rất nhiều lần bạn muốn gửi dữ liệu mà không cần làm mới trang. Bạn có thể sẽ phải đối mặt với một số rắc rối trước khi cuối cùng bạn nhớ điều đó - chờ đã, bạn quên gửi csrf_token. Đây là một rào cản dành cho người mới bắt đầu được biết đến trong tích hợp AJAX-Django, nhưng sau khi bạn học cách làm cho nó chơi tốt, nó dễ như một chiếc bánh.

Đó là tất cả mọi thứ xuất hiện trong đầu tôi. Đó là một chủ đề rộng lớn, nhưng vâng, có lẽ không có đủ ví dụ ngoài đó. Chỉ cần làm việc theo cách của bạn ở đó, từ từ, cuối cùng bạn sẽ nhận được nó.


1
Cảm ơn. Tôi chỉ đơn giản là bạn đang ở đâu, tôi biết cảm giác. Đối với trò chuyện - nói chung là có, nhưng không phải bây giờ (cũng vậy, đối với các câu hỏi cụ thể mà bạn có ... à ... toàn bộ SO).
yuvi

2
PS các video tôi liên kết có cả tuần dành riêng cho AJAX. Nghiêm túc, đi qua chúng. Chúng thật tuyệt vời
yuvi

Cảm ơn @yuvi vì điều này! Tôi đang tự hỏi mình câu hỏi tương tự về AJAX. Hơn nữa, tôi không chắc chắn khi nào tôi phải sử dụng AJAX hay không. Ví dụ: tôi hiểu rằng tôi sẽ cần một số Javascript để xử lý các hình thức phương thức Bootstrap nhưng tôi không hiểu liệu nó có liên quan đến AJAX hay không. Và nghiêm túc, phải học toàn bộ Jquery chỉ để xuất hiện một cửa sổ bật lên trong trang của tôi ... Tôi không thể thấy lợi tức đầu tư :( Có cách nào đơn giản hơn không? :( Cảm ơn lần nữa vì câu trả lời của bạn.
David D.

5
@DavidW. Xin chào David, tôi rất vui vì câu trả lời của tôi đã giúp bạn. AJAX là một kỹ thuật, bạn có thể làm với javascript đơn giản, nhưng có thể trở nên rất phức tạp. jQuery chỉ đơn giản là có các phím tắt làm cho nó dễ dàng hơn nhiều. Nó không liên quan gì đến phương thức của Bootstrap (bạn có thể tìm nạp các biểu mẫu thông qua AJAX nếu bạn muốn, nhưng nếu không thì nó không liên quan). Dù sao, tôi rất khuyên bạn nên thử và tìm cách từ từ. jQuery là quan trọng và rất cơ bản những ngày này, vì vậy đầu tư tốt ở đó. Khi bạn gặp một rào cản, hãy đến với SO và hỏi (không phải ở đây trong phần bình luận của một câu hỏi đã được trả lời, hãy mở một câu hỏi mới). Chúc may mắn!
yuvi

Liên quan đến đề cập của bạn về csrf_token, chúng ta có thể làm việc xung quanh phương pháp này? Nếu chúng ta có một hàm ví dụ, ajaxCall()chúng ta chỉ có thể sử dụng phương thức truyền thống của một cái gì đó như <form onsubmit='ajaxCall();return false;'>, phải không?
ytpillai

22

Ngoài câu trả lời xuất sắc của yuvi, tôi muốn thêm một ví dụ cụ thể nhỏ về cách giải quyết vấn đề này trong Django (ngoài bất kỳ js nào sẽ được sử dụng). Ví dụ sử dụng AjaxableResponseMixinvà giả định một mô hình Tác giả.

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

Nguồn: Tài liệu Django, Xử lý biểu mẫu với các khung nhìn dựa trên lớp

Liên kết đến phiên bản 1.6 của Django không còn được cập nhật lên phiên bản 1.11


14

Tôi viết thư này vì câu trả lời được chấp nhận là khá cũ, nó cần phải ôn lại.

Vì vậy, đây là cách tôi sẽ tích hợp Ajax với Django vào năm 2019 :) Và hãy lấy một ví dụ thực tế về việc khi nào chúng ta sẽ cần Ajax: -

Hãy nói rằng tôi có một mô hình với tên người dùng đã đăng ký và với sự trợ giúp của Ajax, tôi muốn biết liệu tên người dùng đã cho có tồn tại hay không.

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

url:

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

lượt xem:

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)

Cũng render_to_response mà bị phản đối và đã được thay thế bởi làm và từ Django 1,7 trở đi thay vì HttpResponse chúng tôi sử dụng JsonResponse cho ajax phản ứng. Vì nó đi kèm với bộ mã hóa JSON, vì vậy bạn không cần phải tuần tự hóa dữ liệu trước khi trả về đối tượng phản hồi nhưng HttpResponsekhông được phản đối.


8

Đơn giản và tốt đẹp. Bạn không phải thay đổi quan điểm của mình. Bjax xử lý tất cả các liên kết của bạn. Kiểm tra này: Bjax

Sử dụng:

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

Cuối cùng, bao gồm điều này trong ĐẦU của html của bạn:

$('a').bjax();

Để biết thêm cài đặt, hãy kiểm tra bản demo tại đây: Bjax Demo


18
Xin chào, lưu ý nhanh - Tôi muốn khuyên bất kỳ ai mới bắt đầu học Django và \ hoặc AJAX - vui lòng không sử dụng điều này. Bạn sẽ không học được gì. Giữ nó trong mục yêu thích của bạn và tự xây dựng các yêu cầu AJAX của bạn. Quay lại và sử dụng Bjax khi bạn đã quen với cách thức hoạt động của nó trong nền. Điều này không giống như bảo mọi người học hội để viết mã - bạn không cần xây dựng các yêu cầu AJAX của mình bằng JS thuần túy, chỉ cần jQuery, bởi vì nếu bạn muốn trở thành một chuyên gia, đó là kiến ​​thức cơ bản tối thiểu bạn sẽ cần phải có. Chúc mừng
yuvi

5

AJAX là cách tốt nhất để thực hiện các tác vụ không đồng bộ. Thực hiện cuộc gọi không đồng bộ là điều phổ biến được sử dụng trong bất kỳ công trình xây dựng trang web nào. Chúng tôi sẽ lấy một ví dụ ngắn để tìm hiểu cách chúng tôi có thể triển khai AJAX trong Django. Chúng ta cần sử dụng jQuery để viết ít javascript hơn.

Đây là ví dụ Liên hệ , đây là ví dụ đơn giản nhất, tôi đang sử dụng để giải thích những điều cơ bản của AJAX và việc triển khai nó trong Django. Chúng tôi sẽ thực hiện yêu cầu POST trong ví dụ này. Tôi đang theo dõi một trong những ví dụ của bài đăng này: https://djangopy.org/learn/step-up-guide-to-im vây-ajax-in-django

mô hình

Trước tiên hãy tạo mô hình Liên hệ, có các chi tiết cơ bản.

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

biểu mẫu

Tạo biểu mẫu cho mô hình trên.

from django import forms
from .models import Contact

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

lượt xem

Các khung nhìn trông tương tự như khung nhìn tạo dựa trên chức năng cơ bản, nhưng thay vì quay lại với kết xuất, chúng tôi đang sử dụng phản hồi của 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)

url

Hãy tạo lộ trình của chế độ xem trên.

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

bản mẫu

Di chuyển đến phần lối vào, hiển thị biểu mẫu đã được tạo ở trên thẻ biểu mẫu kèm theo cùng với nút csrf_token và trình. Lưu ý rằng chúng tôi đã bao gồm thư viện 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

Bây giờ chúng ta hãy nói về phần javascript, trên biểu mẫu gửi, chúng tôi đang thực hiện yêu cầu ajax của loại POST, lấy dữ liệu biểu mẫu và gửi đến phía máy chủ.

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

Đây chỉ là một ví dụ cơ bản để bắt đầu với AJAX với django, nếu bạn muốn lặn với một vài ví dụ khác, bạn có thể xem qua bài viết này: https://djangopy.org/learn/step-up-guide-to- hiện thực-ajax-in-django


2

Tôi đã cố gắng sử dụng AjaxableResponseMixin trong dự án của mình, nhưng đã kết thúc với thông báo lỗi sau:

Không đúng cách Được cấu hình: Không có URL để chuyển hướng đến. Cung cấp url hoặc xác định phương thức get_absolute_url trên Model.

Đó là bởi vì CreatView sẽ trả về phản hồi chuyển hướng thay vì trả lại một HTTPResponse khi bạn gửi yêu cầu JSON đến trình duyệt. Vì vậy, tôi đã thực hiện một số thay đổi cho AjaxableResponseMixin. Nếu yêu cầu là một yêu cầu ajax, nó sẽ không gọi super.form_validphương thức, chỉ cần gọi form.save()trực tiếp.

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

Khi chúng tôi sử dụng 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
----------------------------

Nếu bạn muốn giữ dữ liệu cũ, bạn có thể làm điều đó mà không cần Ajax. (Trang sẽ được làm mới)

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.

Hoặc bạn có thể làm với Ajax (Trang sẽ không được làm mới)

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

Nếu bạn sử dụng Ajax, bạn phải làm như sau:

  1. Ban đầu một trang HTML bằng URL1 (chúng tôi thường trang ban đầu theo mẫu Django). Và sau đó máy chủ gửi cho khách hàng một trang html.
  2. Sử dụng Ajax để liên lạc với máy chủ bằng URL2. Và sau đó máy chủ gửi cho khách hàng một cấu trúc dữ liệu.

Django khác với Ajax. Lý do cho điều này là như sau:

  • Điều trở lại với khách hàng là khác nhau. Trường hợp của Django là trang HTML. Trường hợp của Ajax là cấu trúc dữ liệu. 
  • Django rất giỏi trong việc tạo ra thứ gì đó, nhưng nó chỉ có thể tạo một lần, nó không thể thay đổi bất cứ điều gì. Django giống như anime, bao gồm nhiều hình ảnh. Ngược lại, Ajax không giỏi tạo sth nhưng giỏi thay đổi sth trong trang html tồn tại.

Theo tôi, nếu bạn muốn sử dụng ajax ở mọi nơi. khi bạn cần khởi tạo một trang có dữ liệu lúc đầu, bạn có thể sử dụng Django với Ajax. Nhưng trong một số trường hợp, bạn chỉ cần một trang tĩnh mà không cần bất cứ thứ gì từ máy chủ, bạn không cần sử dụng mẫu Django.

Nếu bạn không nghĩ Ajax là cách tốt nhất. bạn có thể sử dụng mẫu Django để làm mọi thứ, như anime.

(Tiếng Anh của tôi không tốt)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.