AjaxをDjangoアプリケーションと統合するにはどうすればよいですか?


264

私はDjangoは初めてで、Ajaxはかなり新しいです。2つを統合する必要があるプロジェクトに取り組んでいます。私はそれらの両方の背後にある原則を理解していると信じていますが、2つを一緒にうまく説明できていません。

誰かがコードベースを2つに統合してどのように変更する必要があるかを簡単に説明してもらえますか?

たとえば、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/homeを返し、要求されたindex.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呼び出しについては何も新しいことはありません。これらは、ユーザーがページを離れることなくデータや情報を取得できるようにするための方法であり、スムーズで非常にきちんとしたWebサイトのデザインを実現します。注意すべきいくつかのガイドライン:

  1. jQueryを学んでください。私はこれを十分に強調することはできません。受け取ったデータの処理方法を知るには、少し理解する必要があります。また、いくつかの基本的なJavaScript構文を理解する必要があります(Pythonからそれほど遠くないので、慣れます)。EnvatoのjQueryのビデオチュートリアルを強くお勧めします。すばらしいチュートリアルであり、正しい道に進むことができます。
  2. いつJSONを使用するのですか?。Djangoビューによって送信されたデータがJSONである多くの例を見ていきます。詳細については説明しませんでした。その方法は重要ではないため(説明はたくさんあります)、の場合はさらに重要です。そしてその答えは-JSONデータはシリアル化されたデータです。つまり、操作できるデータです。前述のように、AJAX呼び出しは、ユーザーが自分で行った場合と同じように応答をフェッチします。ここで、すべてのhtmlを台無しにしたくはなく、代わりにデータ(おそらくオブジェクトのリスト)を送信したいとします。JSONはオブジェクトとして送信するため(JSONデータはpython辞書のように見えます)、これを反復処理したり、役に立たないhtmlをふるいにかけたりする必要がないため、JSONはこれに適しています。
  3. 最後に追加します。Webアプリを作成してAJAXを実装したい場合は、ご自分でお願いします。まず、AJAXをまったく含まないアプリ全体をビルドします。すべてが機能していることを確認してください。次に、そのときだけ、AJAX呼び出しの記述を開始します。これは多くのことを学ぶのに役立つ良いプロセスです。
  4. Chromeのデベロッパーツールを使用します。AJAX呼び出しはバックグラウンドで行われるため、デバッグが非常に困難な場合があります。console.logデバッグするには、Chrome開発者ツール(またはfirebugなどの同様のツール)を使用する必要があります。詳細は説明せず、ググってみてください。それはあなたにとても役立つでしょう。
  5. CSRFの認識。最後に、Djangoの投稿リクエストにはが必要であることを覚えておいてくださいcsrf_token。AJAX呼び出しでは、ページを更新せずにデータを送信したい場合がよくあります。最終的にそれを思い出す前に、おそらくいくつかの問題に直面するでしょう-待って、あなたはを送るのを忘れましたcsrf_token。これは、AJAXとDjangoの統合における既知の初心者向けロードブロッキングですが、見栄えを良くする方法を学んだ後は、簡単です。

それが私の頭に浮かぶすべてです。それは広大な主題ですが、ええ、おそらくそこには十分な例がありません。ゆっくりと、そこに向かって作業するだけで、最終的にはそれが得られます。


1
ありがとう。私は単にあなたがいるところに行ってきました、私は気持ちを知っています。チャットに関しては、一般的にはそうですが、現在はそうではありません(また、特定の質問については...まあ... SO全体)。
yuvi 2013

2
PS私がリンクしたビデオは1週間丸ごとAJAXに捧げられています。真剣に、それらを通過します。彼らは素晴らしいです
ユビ

これを@yuviに感謝します!私はAJAXについて同じ質問をしています。さらに、AJAXを使用する必要があるかどうかはわかりません。たとえば、Bootstrapモーダルフォームを処理するためにJavascriptが必要になることは理解していますが、AJAXに関連しているかどうかはわかりません。そして真剣に、ちょうどポップアップ私のページで表示されるようにするために、全体のjQueryを学ぶこと...私は投資のリターンを見ることができません:(任意のシンプルな代替はあります:(あなたの答えのためにもう一度感謝?。
デビッドD.

5
@DavidW。こんにちはデビッド、私の答えがあなたを助けてくれて嬉しいです。AJAXは単純なJavaScriptで実行できる手法ですが、非常に複雑になる可能性があります。jQueryには、非常に簡単なショートカットがあります。これは、Bootstrapのモーダルとは関係ありません(必要に応じて、AJAXを介してフォームをフェッチできますが、それ以外は無関係です)。とにかく、ゆっくりと自分のやり方を考えてみることを強くお勧めします。最近のjQueryは重要で非常に基本的なものであるため、そこに十分な投資を行っています。障害にぶつかったときは、SOにアクセスして質問してください(既に回答済みの質問のコメントにはここではなく、新しい質問を開いてください)。幸運を!
yuvi 2014年

についてのあなたの言及に関して、csrf_tokenこの方法を回避できますか?サンプル関数がある場合ajaxCall()、のような従来の方法を使用でき<form onsubmit='ajaxCall();return false;'>ますよね?
ytpillai 2016年

22

yuviの優れた回答からさらに、私はDjango内でこれを処理する方法について(使用されるjsを超えて)小さな具体例を追加したいと思います。この例AjaxableResponseMixinでは、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']

ソース:Djangoドキュメント、クラスベースのビューでのフォーム処理

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>   

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)

また、非推奨でrenderに置き換えられたrender_to_responseも、HttpResponseの代わりにDjango 1.7以降では、ajax応答に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、jQueryだけでAJAXリクエストを構築する必要はありません。専門家になりたい場合、それは最低限の基本知識だからです。持つ必要がある。乾杯
yuvi

5

AJAXは非同期タスクを実行する最良の方法です。非同期呼び出しを行うことは、どのWebサイト構築でも一般的に使用されています。DjangoにAJAXを実装する方法を学ぶために短い例をとります。JavaScriptを少なくするために、jQueryを使用する必要があります。

これは最も簡単な例であるContactの例です。AJAXの基本とDjangoでの実装の説明に使用しています。この例ではPOSTリクエストを作成します。私はこの投稿の例の1つに従っています:https : //djangopy.org/learn/step-up-guide-to-implement-ajax-in-django

models.py

まず、基本的な詳細を備えた連絡先のモデルを作成しましょう。

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

次に、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- implement-ajax-in-django


2

プロジェクトでAjaxableResponseMixinを使用しようとしましたが、次のエラーメッセージが表示されていました。

ImproperlyConfigured:リダイレクト先の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

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

古いデータを保持したい場合は、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. Ajaxを使用して、URL2を使用するサーバーと通信します。そして、サーバーはクライアントにデータ構造を送信します。

DjangoはAjaxとは異なります。この理由は次のとおりです。

  • クライアントに返すものは違います。Djangoの場合はHTMLページです。Ajaxの場合はデータ構造です。 
  • Djangoは何かを作成するのが得意ですが、作成できるのは1回だけであり、何も変更することはできません。Djangoはアニメのようなもので、多くの画像で構成されています。対照的に、Ajaxはsthの作成は得意ではありませんが、exist htmlページのsthの変更は得意です。

私の意見では、どこでもajaxを使用したい場合。最初にデータを含むページを初期化する必要がある場合は、AjaxでDjangoを使用できます。しかし、場合によっては、サーバーから何もない静的ページが必要なだけで、Djangoテンプレートを使用する必要はありません。

Ajaxがベストプラクティスと思わない場合。Djangoテンプレートを使用して、アニメなどのすべてを行うことができます。

(私の英語は下手です)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.