草庐IT

javascript - Django 中是否有一种惯用的方法来编写不引人注目的 JavaScript 和/或进行 AJAX 表单提交?

coder 2023-08-18 原文

我是一名 Ruby/Rails 开发人员,现在在一家 Python/Django 商店工作。我已经开始热衷于 Python,但是,我仍在努力寻找 Django 在我认为重要的某些方面与 Rails 相媲美。我当前和 future 的很多工作都将集中于向我们的 API 发出 AJAX 请求。作为一名 Rails 开发人员,我会使用不显眼的 javascript,特别是在表单提交上添加一个 data-remote 标签,如下所示。

然后我会在 Controller 中编写一个方法来处理请求,并在位于/assets/js 目录中的 JS 文件中使用事件委托(delegate)编写一个 JavaScript/jQuery 函数来处理客户端的响应.我假设来到 Django 时会有类似的方式来实现这种功能。

我想我真正想说的是,我假设 Django 会提供与 Rails 类似的“魔法”,因为每次我想发出 AJAX 请求时都不必写出 jQuery AJAX 函数。我写了一个粗略的比较(非常粗略)我将如何写出这两个。我正在寻找了解这是否是我在 Django 中的 Rails 中所做的不正确方法。我知道 StackOverflow 并不意味着意见,但我认为打破适用于无论您使用什么语言/框架的原则,即通过不一遍又一遍地写出 AJAX 函数来干燥代码,并不是真正反对意见,这更像是打破了公认的规则。

我目前在 Django 中处理 AJAX 请求的方法感觉不对,或者我可能只是习惯了 Rails 通过 data-remote="true"属性提供的“神奇”功能。很想得到有关该主题的一些指导,以帮助我确定可靠的方法,谢谢。

RAILS

views/some_controller/form.html.erb

<form action="<%= endpoint %>" method="post" data-remote="true" id="form">
  FORM FIELDS HERE
</form>

assets/javascripts/some_model.js

$('body').on('ajax:success', '#form', function(event, data) {
  DO SOME STUFF HERE
});

controllers/some_controller.rb

def some_ajax_action
  if request.xhr?
    THIS IS AN AJAX REQUEST RENDER A VIEW PARTIAL & 
    MANIPULATE THE DOM WITH JS OR RESPOND WITH JSON
  else
    THIS ISNT AN AJAX REQUEST
  end
end

DJANGO

some_app/templates/form.html

<form action="{% url 'app:view' %}" method="post" id="form">
   FORM FIELDS HERE OR {{ BUILD_FORM_FROM_CONTEXT }} 
</form>

some_app/static/assets/js/some_app.js

$("#form").on("submit", function(event) {
  $.ajax({
    type: "POST",
    beforeSend: function (request) {
      request.setRequestHeader("X-CSRFToken", csrftoken);
    },
    data: data,
    url: "endpoint",
    dataType: 'json',
    contentType: 'application/json',
    }).done(function(data) {
      cb(null, data)
    }).fail(function(data) {
      cb(data)
    }).always(function(data) {
      cb(data)
    })
  });
});

最佳答案

您的问题的答案是否定的。 Django 没有惯用的 AJAX 方法。它对 AJAX 没有意见,尤其是在前端。

由于基于类的 View (CBV) 的结构方式,后端倾向于遵循更多相似的模式;通常会看到一个简单的 AJAXResponseMixin 混合到 CBV 中,它利用了所有通用 View 通过单一方法 get_context_data 可靠地生成其上下文这一事实。 mixins 可以只获取所述上下文并将其转换为 JSON。

没有强加于 Django 的 AJAX 模式;你只需要按照你喜欢的方式构建你自己的。

如果您喜欢 Rails 示例的处理方式,为什么不呢?

这个练习的目的是向您展示这个想法中真正涉及的框架有多么少。这是几行代码。

首先,让我们使用您概述的语法重现您的 data-remote=True 标记和事件监听器系统。注意,这都是伪代码。

$(function() {
    $("[data-remote=true]").each(function(index, el) {
        $(el).submit(function(ev) {
            ev.preventDefault(); // disable default form submit. We are using ajax.
            $.ajax({
                url: $(this).attr('action') || '',
                data: $(this).serialize(),
                method: $(this).attr('method') || 'get',
                success: function(response) {
                    // on success, trigger an event with the response data
                    $(el).trigger('ajax:success', [response]);
                },
                error: function(xhr) {
                    $(el).trigger('ajax:error', [xhr]);
                }
            })
            return false;
        })
    })
})

完成。现在让我们在模板中使用它:

<form id="my-django-form" method="POST" data-remote="true" action="some-controller">
    {{ form.as_p }}
    <input type="submit" />
</form>

太棒了,现在有一些 JS 来响应这个表单的提交:

$(function() {
    $('body').on('ajax:success', '#my-django-form', function(event, data) {
        alert("My barebones ajax framework was successful!", data);
    })
    $('body').on('error', '#my-django-form', function(event, data) {
        alert("Whoops, error!");
    })
})

Controller /django View :

def some_ajax_action(request):
    """ Some basic AJAX Handler.
    """
    if request.is_ajax():
        return http.HttpResponse(json.dumps({
            'this-is': 'some-json',
        }))
    else:
        print "This isn't an ajax request"

关于如何作为框架和可重用模式应用的想法,包括许多框架通用的部分渲染。

class AJAXFrameworkMixin(object):
    """ A more advanced, reusable pattern for class based views.
    Perhaps also allowing partial rendering via custom header `RENDER_PARTIAL` used by the jQuery request.
    """
    def dispatch(self, request, *args, **kwargs):
        if request.is_ajax():
            partial = request.META.get('X_RENDER_PARTIAL')
            if partial:
                return self.handle_ajax_partial(request, partial)
            return self.handle_ajax(request)

        return super(AJAXFrameworkMixin, self).dispatch(request, *args, **kwargs)

    def handle_ajax(self, request):
        """ Ajax specific handler.
        Convert this view context into JSON.
        """
        ctx = self.get_context_data()
        return http.HttpResponse(json.dumps(ctx))

    def handle_ajax_partial(self, request, partial):
        """ Given a render partial header from the barebones AJAX framework, render said partial with context.
        """
        t = template.loader.get_template(partial)
        return t.render(template.RequestContext(request, self.get_context_data()))

为完成此示例,我们将修改初始 jQuery 脚本以根据新的数据属性(例如数据部分名称)设置 header 。

现在我们的简单框架可以通过 HTML 数据属性在基于类的 View 上调用特定方法。即设置 data-partial="some-template-name.html" 将触发 YourView.handle_ajax_partial 返回呈现的 HTML。

然后,如果已设置 data-partial,您可以通过向 data-remote 函数添加默认处理程序来自动呈现/更新所述调用。

关于javascript - Django 中是否有一种惯用的方法来编写不引人注目的 JavaScript 和/或进行 AJAX 表单提交?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22826113/

有关javascript - Django 中是否有一种惯用的方法来编写不引人注目的 JavaScript 和/或进行 AJAX 表单提交?的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  3. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  4. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  5. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  6. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  7. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  8. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  9. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  10. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

随机推荐