web-dev-qa-db-ja.com

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

私はDjangoに慣れていないし、Ajaxについてはかなり新しいです。私は2つを統合する必要があるプロジェクトに取り組んでいます。私は両方の背後にある原則を理解していると思いますが、この2つの良い説明を一緒に見つけていません。

2人が一緒に統合したときにコードベースがどのように変更される必要があるかについて、誰かが私に簡単に説明してもらえますか?

たとえば、AjaxでHttpResponseを使用することはできますか。それとも、Ajaxを使用することで回答を変更する必要がありますか。もしそうなら、あなたは要求への応答がどのように変化しなければならないかの例を教えてください。違いがある場合、私が返すデータはJSONです。

236
tjons

これは完全には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. 呼び出しは、あたかも新しいタブを開いて自分で行ったかのように、URL 127.0.0.1:8000/helloに移動します。
  2. 成功した場合(ステータスコード200)、成功した場合は機能を実行し、受信したデータを警告します。
  3. 失敗した場合は、別の機能を実行してください。

今ここで何が起こるでしょうか?あなたはその中に「こんにちは世界」と警告を受けるでしょう。あなたが家にAJAX電話をかけるとどうなりますか?同じこと、<h1>Hello world, welcome to my awesome site</h1>という警告が表示されるでしょう。

言い換えれば - AJAX呼び出しについて新しいことは何もありません。それらはあなたがページを離れることなくユーザーにデータと情報を手に入れることを可能にするためのちょうど方法であり、そしてそれはあなたのウェブサイトの滑らかで非常にきれいなデザインに役立ちます。注意すべきガイドラインがいくつかあります。

  1. jQueryを学んでください。私はこれを十分に強調することはできません。受信したデータを処理する方法を知るためには、少し理解する必要があります。また、基本的なJavaScriptシンタックスを理解する必要があります(pythonからそれほど遠くない、慣れることができます)。私は強くお勧めします jQueryのためのEnvatoのビデオチュートリアル 、それらは素晴らしくて正しい道にあなたを置くでしょう。
  2. いつJSONを使うのですか?。 Djangoのビューによって送信されたデータがJSONにある例がたくさんあります。 how でそれを行うことは重要ではないので(多くの説明がたくさんあります)、もっと重要な when の場合は、詳細については説明しませんでした。その答えは、JSONデータはシリアル化されたデータです。つまり、操作できるデータです。私が言ったように、AJAX呼び出しは、あたかもユーザーがそれをしたかのように応答を取得します。今、あなたはすべてのhtmlを台無しにしたくないで、その代わりにデータ(おそらくオブジェクトのリスト)を送りたいと思ってください。 JSONはこれをオブジェクトとして送信するので(JSONデータはPython辞書のように見えます)、これを繰り返すか、または無駄なHTMLをふるいにかける必要性を排除する何か他のことができるので、これに適しています。
  3. 最後に追加してください。 Webアプリを作成してAJAXを実装したい場合 - 自分で好きなようにしてください。まず、AJAXをまったく含まないアプリ全体を構築します。すべてがうまくいっていることを確認してください。それから、それから初めて、AJAX呼び出しを書き始めます。それはあなたが多くを学ぶのを助ける良い過程です。
  4. chromeの開発者ツールを使用してください。 AJAX呼び出しはバックグラウンドで行われるため、デバッグが困難な場合があります。デバッグには、クロム開発者ツール(またはfirebugなどの同様のツール)とconsole.logのものを使用してください。私は詳細に説明するのではなく、ただグーグルの周りでそれについて調べる。それはあなたにとって非常に役に立つでしょう。
  5. CSRFの認識。最後に、Djangoでの投稿リクエストにはcsrf_tokenが必要であることを忘れないでください。 AJAX呼び出しでは、ページを更新せずにデータを送信したいことがよくあります。最後に覚えておく前に、おそらく何らかのトラブルに直面するでしょう - 待って、あなたはcsrf_tokenを送るのを忘れていました。これはAJAX-Djangoの統合における既知の初心者の障害ですが、あなたがそれを素晴らしいものにする方法を学んだ後、それはパイのように簡単です。

それが私の頭に浮かんだすべてです。それは広大な主題ですが、ええ、おそらくそこに十分な例はありません。ゆっくりとそこに向かって進むだけで、最終的にはうまくいくでしょう。

582
yuvi

Yuviの優れた答えからさらに、私はDjangoの中でこれをどのように扱うかについての小さな特定の例を追加したいと思います(使用されるどんなjsを超えても)。この例ではAjaxableResponseMixinを使用し、作成者モデルを想定しています。

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に更新されて利用できなくなりました

19
Wtower

シンプルでいいです。あなたはあなたの見解を変える必要はありません。 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

9
endur

私はこれを書いています。なぜなら、受け入れられた答えはかなり古いからです。

だから、これは私が2019年にDjangoにAjaxを統合する方法です:)そして、私たちがAjaxを必要とする時の本当の例を見てみましょう: -

登録されたユーザー名と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 は非推奨となり、 render およびDjangoから置き換えられました1.7以降 HttpResponse ではなくajaxレスポンスに JsonResponse を使います。 JSONエンコーダが付属しているので、レスポンスオブジェクトを返す前にデータをシリアル化する必要はありませんが、HttpResponsename__は推奨されません。

3
Ahtisham

AJAXは非同期タスクを実行するための最良の方法です。非同期呼び出しを行うことは、どのWebサイト構築でも一般的に使用されていることです。 DjangoでAJAXを実装する方法を学ぶために短い例を取ります。 javascriptを少なくするために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

ビューは基本的な関数ベースのcreateビューに似ていますが、renderで返される代わりに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および送信ボタンと共に、囲むformタグの上に作成されたフォームをレンダリングします。 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/) ajax-in-Djangoを学ぶ/ステップアップするためのガイド

2
Jai Singhal

私は自分のプロジェクトで 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
2
Enix