我是一名 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/