Django中是否有一种惯用的方法来编写不引人注目的JavaScript和/或提交AJAX表单?
我是一名Ruby/Rails开发人员,现在在Python/Django商店工作。我已经开始对Python热身了,但是,我仍然在努力寻找Django在我认为重要的某些方面可以与Rails相媲美。我当前和未来的很多工作都将集中于对API发出AJAX请求。作为一名Rails开发人员,我会使用不引人注目的javascript,尤其是在表单提交中添加一个数据远程标记,如下所示 然后,我将在控制器中编写一个方法来处理请求,并将在位于/assets/JS目录的JS文件中使用事件委托编写一个JavaScript/jQuery函数来处理客户端的响应。我假设来到Django,也会有类似的方法来实现这种功能 我想我真正想说的是,我假设Django会提供与Rails类似的“魔力”,即不必在每次我想要发出AJAX请求时都写出jQueryAjax函数。我写了一个粗略的比较(非常粗略)我将如何写出这两个。我希望了解这是否是一个不正确的方法,我将在Django的Rails中执行。我知道StackOverflow不是用来发表意见的,但我认为不管你使用什么语言/框架,打破适用的原则,即不反复编写AJAX函数而导致代码干涸,这并不是真正违背意见,更像是打破了一条公认的规则 我目前在Django中处理AJAX请求的方法感觉是错误的,或者我只是习惯了Rails通过data remote=“true”属性提供的“神奇”功能。希望您能给我一些关于这个话题的指导,帮助我确定一个可靠的方法,谢谢 导轨 views/some\u controller/form.html.erbDjango中是否有一种惯用的方法来编写不引人注目的JavaScript和/或提交AJAX表单?,javascript,python,ajax,django,Javascript,Python,Ajax,Django,我是一名Ruby/Rails开发人员,现在在Python/Django商店工作。我已经开始对Python热身了,但是,我仍然在努力寻找Django在我认为重要的某些方面可以与Rails相媲美。我当前和未来的很多工作都将集中于对API发出AJAX请求。作为一名Rails开发人员,我会使用不引人注目的javascript,尤其是在表单提交中添加一个数据远程标记,如下所示 然后,我将在控制器中编写一个方法来处理请求,并将在位于/assets/JS目录的JS文件中使用事件委托编写一个JavaScript
<form action="<%= endpoint %>" method="post" data-remote="true" id="form">
FORM FIELDS HERE
</form>
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
控制器/some_controller.rb
<form action="<%= endpoint %>" method="post" data-remote="true" id="form">
FORM FIELDS HERE
</form>
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
一些应用程序/模板/form.html
<form action="{% url 'app:view' %}" method="post" id="form">
FORM FIELDS HERE OR {{ BUILD_FORM_FROM_CONTEXT }}
</form>
这不是在Django中轻松实现的方法,但是通过几个额外的库,您可以更轻松地处理ajax表单帖子 CsrfProtection.js-这将把csrf令牌头附加到ajax请求中
(function() {
var csrfSafeMethod, sameOrigin;
csrfSafeMethod = function(method) {
return /^(GET|HEAD|OPTIONS|TRACE)$/.test(method);
};
sameOrigin = function(url) {
var host, origin, protocol, sr_origin;
host = document.location.host;
protocol = document.location.protocol;
sr_origin = '#' + host;
origin = protocol + sr_origin;
return (url === origin || url.slice(0, origin.length + 1) === origin + '/') || (url === sr_origin || url.slice(0, sr_origin.length + 1) === sr_origin + '/') || !(/^(\/\/|http:|https:).*/.test(url));
};
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
return xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
}
}
});
}).call(this);
然后包括javascript库。使用此库将允许您执行以下操作:
$('#form_id').ajaxSubmit({
success: function(response) {console.log(response);},
error: function(response) {console.log(response);}
});
它可能不像您在Ruby中列出的那样简单,但它确实减少了csrf令牌的重复和表单序列化。我不相信django本身就有一个习惯用法。然而,也有可重用的应用程序,它们确实提供了非常常用的实现 例如,Crispy表单可以简化django ajax表单。在请求之前,无需进行任何csrf处理。他们的例子如下:
您的问题的答案是否定的。使用Django实现AJAX没有惯用的方法。它对AJAX没有意见,尤其是在前端 由于基于类的视图(CBV)的结构,后端倾向于遵循更相似的模式;常见的情况是,CBV中混合了一个简单的
AJAXResponseMixin
,它利用了所有通用视图通过单个方法可靠地生成上下文的事实get\u context\u data
。mixin只需获取所述上下文并将其转换为JSON即可
django没有被迫使用AJAX模式;你只需要按照你喜欢的方式建造自己的房子
如果您喜欢rails示例的工作方式,为什么不呢
本练习的目的是向您展示这个想法中真正涉及的框架是多么少。这是几行代码
首先,让我们使用您概述的语法重现您的dataremote=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;
})
})
})
完成。现在让我们在模板中使用它:
控制器/django视图:
关于如何作为框架和可重用模式应用的想法,包括许多框架共有的部分呈现。
为了完成本例,我们将修改初始jQuery脚本,以基于新的数据属性(如数据部分名称)设置头
现在,我们的简单框架可以通过HTML数据属性在基于类的视图上调用特定方法。i、 e.设置data partial=“some template name.html”
将触发YourView.handle\u ajax\u partial
,它将返回呈现的html
如果设置了
data-partial
,则可以通过向data-remote
函数添加默认处理程序来自动呈现/更新所述调用。“有没有一种惯用的方法将Ruby/Rails惯用表达为惯用Python/Django?”这是一个完全可以接受的问题。这表明你已经做了研究。你看过这个了吗?嘿,杰森,我见过那些医生。这是处理调用是否为AJAX的好方法。但我想我的问题更多的是关于是否有一种类似于Rails使用UJS的惯用方法。我发现了一个Django UJS库,但它似乎没有得到维护。将data remote=“true”
添加到HTML表单或链接会通过AJAX发送请求。我在想也许一个模板过滤器可以用来做同样的事情。我将做更多的研究并找出答案。AFAIK大多数Rails的“魔力”来自Rails提供的JavaScript插件(在您的示例中)。Django只关注Python,不提供太多的内置模板和现成的静态文件(除了在像admin这样的成熟解决方案中),因此您需要以简单的方式完成。但是,如果你想自己实现封装这些内容,没有什么可以阻挡你。@evkline:你能对提供的答案给出一些反馈吗?这有助于我奖励赏金。如果你已经用不同的方式解决了这个问题,你可以写下你的解决方案作为答案。
$(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>
$(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!");
})
})
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()))