如何将Ajax与Django应用程序集成?

tjo*_*ons 247 python django ajax

我是Django的新手,也是Ajax的新手.我正在开展一个项目,我需要整合这两个项目.我相信我理解他们背后的原则,但没有找到两者的良好解释.

有人可以快速解释一下代码库如何随着它们中的两个集成在一起而改变吗?

例如,我是否仍然可以使用HttpResponseAjax,或者我的响应是否必须使用Ajax进行更改?如果是这样,请您提供一个示例,说明请求的响应必须如何变化?如果它有任何区别,我返回的数据是JSON.

yuv*_*uvi 598

虽然这并非完全符合SO的精神,但我喜欢这个问题,因为我在开始时遇到了同样的麻烦,所以我会给你一个快速指南.显然你不理解他们背后的原则(不要把它作为一种冒犯,但如果你这样做,你就不会问).

Django是服务器端.这意味着,比如一个客户端转到url,你在视图中有一个函数可以渲染他看到的内容并在html中返回一个响应.让我们把它分解成例子:

views.py

def hello(request):
    return HttpResponse('Hello World!')

def home(request):
    return render_to_response('index.html', {'variable': 'world'})
Run Code Online (Sandbox Code Playgroud)

index.html的:

<h1>Hello {{ variable }}, welcome to my awesome site</h1>
Run Code Online (Sandbox Code Playgroud)

urls.py

url(r'^hello/', 'myapp.views.hello'),
url(r'^home/', 'myapp.views.home'),
Run Code Online (Sandbox Code Playgroud)

这是最简单的用法的一个例子.去views意味着对hello函数的请求,127.0.0.1:8000/hello将返回hello()并替换所提出的所有变量(你现在可能已经知道了所有这些).

现在让我们谈谈AJAX.AJAX调用是执行异步请求的客户端代码.这听起来很复杂,但它只是意味着它在后台为您提出请求,然后处理响应.因此,当您对某个URL执行AJAX调用时,您将获得与用户前往该位置时相同的数据.

例如,ajax调用127.0.0.1:8000/home将返回与访问它时相同的内容.只有这一次,你有一个js函数,你可以随意处理它.让我们看一个简单的用例:

$.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');
    }
}); 
Run Code Online (Sandbox Code Playgroud)

一般过程是这样的:

  1. 该呼叫转到该URL index.html,就像您打开一个新选项卡并自己完成一样.
  2. 如果成功(状态代码200),请执行成功功能,该功能将提醒收到的数据.
  3. 如果失败,请执行其他功能.

现在这会发生什么?你会收到一个警告"hello world".如果你在家里打ajax电话会怎么样?同样的事情,你会得到一个警报说明127.0.0.1:8000/hello.

换句话说 - AJAX调用并没有什么新内容.它们只是让您在不离开页面的情况下让用户获取数据和信息的一种方式,它使您的网站设计流畅,非常整洁.您应该注意的一些指导原则:

  1. 学习jQuery.我不能强调这一点.你必须要了解它以了解如何处理你收到的数据.你还需要了解一些基本的javascript语法(离python不远,你会习惯它).我强烈推荐Envato的jQuery视频教程,它们很棒,会让你走上正确的道路.
  2. 什么时候使用JSON?.您将看到很多示例,其中Django视图发送的数据是JSON格式.我没有进入细节上,因为它不是重要的是如何做到这一点(有很多的解释,比比皆是)和很多更重要的时候.答案就是 - JSON数据是序列化数据.也就是说,您可以操纵的数据.就像我提到的,AJAX调用将获取响应,就好像用户自己做了一样.现在说你不想搞乱所有的html,而是想发送数据(也许是一个对象列表).JSON对此有好处,因为它将它作为一个对象发送(JSON数据看起来像一个python字典),然后你可以迭代它或做一些其他的东西,无需筛选无用的html.
  3. 最后添加它.当您构建一个Web应用程序并想要实现AJAX时 - 帮自己一个忙.首先,构建完整的应用程序完全没有任何AJAX.看到一切正常.然后,只有这样,才开始编写AJAX调用.这是一个很好的过程,可以帮助你学到很多东西.
  4. 使用chrome的开发人员工具.由于AJAX调用是在后台完成的,因此有时很难调试它们.您应该使用chrome开发人员工具(或类似工具,如firebug)和127.0.0.1:8000/hello要调试的东西.我不会详细解释,只是google并了解它.这对你很有帮助.
  5. CSRF意识.最后,请记住Django中的帖子请求需要<h1>Hello world, welcome to my awesome site</h1>.使用AJAX调用时,很多时候您希望在不刷新页面的情况下发送数据.在你终于记住之前,你可能会遇到一些麻烦 - 等等,你忘记发送了console.log.这是AJAX-Django集成中一个众所周知的初学者障碍,但是在你学会了如何使它发挥得很好之后,就像馅饼一样简单.

这就是我头脑中的一切.这是一个广泛的主题,但是,可能没有足够的例子.只要按照自己的方式工作,慢慢地,你最终会得到它.

  • @DavidW.大卫你好,我很高兴我的回答对你有所帮助.AJAX是一种技术,你可以使用简单的javascript,但可能变得非常复杂.jQuery只是有一些快捷方式,使它更容易.它与Bootstrap的模态无关(如果你愿意,你可以通过AJAX获取表单,但它不相关).无论如何,我强烈建议你尝试慢慢找到自己的方式.jQuery现在非常重要且非常基础,所以那里有很好的投资.当你遇到障碍时,来到SO并询问(不是在已经回答的问题的评论中,打开一个新问题).祝好运! (5认同)
  • 谢谢。我只是去过你所在的地方,我知道那种感觉。至于聊天 - 通常是的,但不是现在(此外,对于您有的特定问题......好吧......整个SO)。 (2认同)
  • PS我链接的视频有整整一周的时间致力于AJAX。认真地,通过他们。他们太棒了 (2认同)

Wto*_*wer 20

再说一下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']
Run Code Online (Sandbox Code Playgroud)

来源:Django文档,基于类视图的表单处理

Django 1.6版的链接不再更新到版本1.11


小智 9

简单又好看.您无需更改视图.Bjax处理您的所有链接.看看这个: Bjax

用法:

<script src="bjax.min.js" type="text/javascript"></script>
<link href="bjax.min.css" rel="stylesheet" type="text/css" />
Run Code Online (Sandbox Code Playgroud)

最后,将此包含在您的html的HEAD中:

$('a').bjax();
Run Code Online (Sandbox Code Playgroud)

有关更多设置,请在此处结帐演示: Bjax Demo

  • 你好,快速注意 - 我想建议任何刚开始学习Django和\或AJAX的人 - 请**不要**使用它.你什么都不会学到的.将它保存在您的收藏夹中并自行构建AJAX请求.一旦你已经熟悉它在后台工作的方式,请回来使用Bjax.这并不像告诉人们学习汇编来编写代码 - 你不需要用纯JS构建你的AJAX请求,只需要jQuery,因为如果你想成为一名专业人士,这就是你需要的最低基础知识.需要有.干杯 (13认同)

Aht*_*ham 7

我写这封信是因为可接受的答案很旧,需要复习。

所以这就是我在2019年将Ajax与Django集成的方式:)让我们举一个实际的例子说明何时需要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>   
Run Code Online (Sandbox Code Playgroud)

阿贾克斯:

$('#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); }
    );
}); 
Run Code Online (Sandbox Code Playgroud)

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'),
]
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

同样,不推荐使用的render_to_response已被render取代,从Django 1.7起,而不是HttpResponse,我们使用JsonResponse进行Ajax响应。因为它带有JSON编码器,所以您不需要在返回响应对象之前对数据进行序列化,但HttpResponse不建议使用。


小智 7

AJAX 是执行异步任务的最佳方式。进行异步调用在任何网站建设中都是常见的。我们将通过一个简短的示例来了解如何在 Django 中实现 AJAX。我们需要使用 jQuery 来编写更少的 javascript。

这是Contact示例,这是最简单的示例,我用来解释 AJAX 的基础知识及其在 Django 中的实现。我们将在这个例子中发出 POST 请求。我正在关注这篇文章的示例之一:https : //djangopy.org/learn/step-up-guide-to-implement-ajax-in-django

模型.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
Run Code Online (Sandbox Code Playgroud)

表格.py

为上述模型创建表单。

from django import forms
from .models import Contact

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
        exclude = ["timestamp", ]
Run Code Online (Sandbox Code Playgroud)

视图.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)
Run Code Online (Sandbox Code Playgroud)

网址.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'),
]
Run Code Online (Sandbox Code Playgroud)

模板

移至前端部分,呈现在封闭表单标记上方创建的表单以及 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>
Run Code Online (Sandbox Code Playgroud)

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

Run Code Online (Sandbox Code Playgroud)

这只是使用 django 开始使用 AJAX 的一个基本示例,如果您想深入了解更多示例,可以阅读本文:https : //djangopy.org/learn/step-up-guide-to-在 Django 中实现 ajax


Bee*_*ake 5

使用 Django 轻松进行 ajax 调用

(26.10.2020)
我认为这比正确答案更干净、更简单。这还包括如何添加 csrftoken 以及如何通过 ajax 使用 login_required 方法。

风景

@login_required
def some_view(request):
    """Returns a json response to an ajax call. (request.user is available in view)"""
    # Fetch the attributes from the request body
    data_attribute = request.GET.get('some_attribute')  # Make sure to use POST/GET correctly
    # DO SOMETHING...
    return JsonResponse(data={}, status=200)
Run Code Online (Sandbox Code Playgroud)

urls.py

urlpatterns = [
    path('some-view-does-something/', views.some_view, name='doing-something'),
]
Run Code Online (Sandbox Code Playgroud)

阿贾克斯调用

ajax 调用非常简单,但对于大多数情况来说已经足够了。您可以获取一些值并将它们放入数据对象中,然后在上面描述的视图中您可以通过它们的名称再次获取它们的值。

你可以在django的文档中找到csrftoken函数。基本上只需复制它并确保它在 ajax 调用之前呈现,以便定义csrftoken 变量。

$.ajax({
    url: "{% url 'doing-something' %}",
    headers: {'X-CSRFToken': csrftoken},
    data: {'some_attribute': some_value},
    type: "GET",
    dataType: 'json',
    success: function (data) {
        if (data) {
            console.log(data);
            // call function to do something with data
            process_data_function(data);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

使用ajax将HTML添加到当前页面

这可能有点偏离主题,但我很少看到它被使用,它是最小化窗口重定位以及在 javascript 中手动创建 html 字符串的好方法。

这与上面的非常相似,但这次我们从响应中渲染 html,而不重新加载当前窗口。

如果您打算从作为对 ajax 调用的响应收到的数据中呈现某种 html,那么从视图发送回 HttpResponse 而不是 JsonResponse 可能会更容易。这使您可以轻松创建 html,然后将其插入到元素中。

风景

# The login required part is of course optional
@login_required
def create_some_html(request):
    """In this particular example we are filtering some model by a constraint sent in by 
    ajax and creating html to send back for those models who match the search"""
    # Fetch the attributes from the request body (sent in ajax data)
    search_input = request.GET.get('search_input')

    # Get some data that we want to render to the template
    if search_input:
        data = MyModel.objects.filter(name__contains=search_input) # Example
    else:
        data = []

    # Creating an html string using template and some data
    html_response = render_to_string('path/to/creation_template.html', context = {'models': data})

    return HttpResponse(html_response, status=200)
Run Code Online (Sandbox Code Playgroud)

视图的html创建模板

创建模板.html

{% for model in models %}
   <li class="xyz">{{ model.name }}</li>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

urls.py

urlpatterns = [
    path('get-html/', views.create_some_html, name='get-html'),
]
Run Code Online (Sandbox Code Playgroud)

主模板和ajax调用

这是我们要添加数据的模板。特别是在这个示例中,我们有一个搜索输入和一个将搜索输入的值发送到视图的按钮。然后,视图发送回 HttpResponse,显示与我们可以在元素内呈现的搜索相匹配的数据。

{% extends 'base.html' %}
{% load static %}
{% block content %}
    <input id="search-input" placeholder="Type something..." value="">
    <button id="add-html-button" class="btn btn-primary">Add Html</button>
    <ul id="add-html-here">
        <!-- This is where we want to render new html -->
    </ul>
{% end block %}

{% block extra_js %}
    <script>
        // When button is pressed fetch inner html of ul
        $("#add-html-button").on('click', function (e){
            e.preventDefault();
            let search_input = $('#search-input').val();
            let target_element = $('#add-html-here');
            $.ajax({
                url: "{% url 'get-html' %}",
                headers: {'X-CSRFToken': csrftoken},
                data: {'search_input': search_input},
                type: "GET",
                dataType: 'html',
                success: function (data) {
                    if (data) {
                        console.log(data);
                        // Add the http response to element
                        target_element.html(data);
                    }
                }
            });
        })
    </script>
{% endblock %}
Run Code Online (Sandbox Code Playgroud)