首页 文章

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

提问于
浏览
216

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

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

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

4 回答

  • 554

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

    Django是服务器端 . 这意味着,比如一个客户端转到url,你在视图中有一个函数可以渲染他看到的内容并在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调用时,您将获得与用户前往该位置时相同的数据 .

    例如,对 127.0.0.1:8000/hello 的ajax调用将返回与访问它时相同的内容 . 只有这一次,你有一个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');
        }
    });
    

    一般过程是这样的:

    • 电话会转到网址 127.0.0.1:8000/hello ,就像您打开一个新标签并自行完成一样 .

    • 如果成功(状态代码200),请执行成功功能,该功能将提醒收到的数据 .

    • 如果失败,请执行其他功能 .

    现在这会发生什么?你会收到一条警告'hello world' . 如果你在家里打ajax电话会怎么样?同样的事情,你会得到一个警告,说明 <h1>Hello world, welcome to my awesome site</h1> .

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

    • Learn jQuery . 我不能强调这一点 . 你_1161391_也需要了解一些基本的javascript语法(离python不远,你会习惯它) . 我强烈推荐Envato's video tutorials for jQuery,它们很棒,会让你走上正确的道路 .

    • When to use JSON? . 你详细了解一下,因为如何做到这一点并不重要(有很多解释比比皆是),更重要的是什么时候 . 答案就是 - JSON数据是序列化数据 . 也就是说,您可以操纵的数据 . 就像我提到的,AJAX调用将获取响应,就好像用户自己做了一样 . 现在说你不想搞乱所有的html,而是想发送数据(也许是一个对象列表) . JSON对此有好处,因为它将它作为一个对象发送(JSON数据看起来像一个python字典),然后你可以迭代它或做一些其他的东西,无需筛选无用的html .

    • Add it last . 当您构建一个Web应用程序并想要实现AJAX时 - 帮自己一个忙 . 首先,构建完整的应用程序完全没有任何AJAX . 看到一切正常 . 然后,只有这样,才开始编写AJAX调用 . 这是一个很好的过程,可以帮助你学到很多东西 .

    • Use chrome's developer tools . 由于AJAX调用是在后台完成的,因此有时很难调试它们 . 您应该使用chrome开发人员工具(或类似工具,如firebug)和 console.log 事件进行调试 . 我不会详细解释,只是google并了解它 . 这对你很有帮助 .

    • CSRF awareness . 最后,请记住Django中的发布请求需要 csrf_token . 有了AJAX调用,很多时候你可能会在你终于记住之前遇到一些麻烦 - 等等,你忘了发送 csrf_token . 这是一个已知的初学者AJAX-Django集成中的障碍,但在你学会了如何使它发挥得很好之后,就像馅饼一样简单 .

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

  • 2

    再说一下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 documentation, Form handling with class-based views

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

  • 17

    简单又好看 . 您无需更改视图 . 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

  • 7

    我试图在我的项目中使用AjaxableResponseMixin,但最终出现以下错误消息:

    NotperlyConfigured:没有要重定向到的URL . 在模型上提供url或定义get_absolute_url方法 .

    这是因为当您向浏览器发送JSON请求时,CreateView将返回 redirect response 而不是返回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
    

相关问题