在客户端Javascript中调用Django`reverse`

在客户端Javascript中调用Django`reverse`,javascript,ajax,django,google-app-engine,dry,Javascript,Ajax,Django,Google App Engine,Dry,我在Appengine上使用Django。我在任何地方都使用djangoreverse()函数,尽可能保持一切干燥 但是,我在将其应用于客户端javascript时遇到了问题。有一个JS类根据传入的ID加载一些数据。是否有一种标准方法不硬编码这些数据应该来自的URL var rq = new Request.HTML({ 'update':this.element, }).get('/template/'+template_id+'/preview'); //The part that

我在Appengine上使用Django。我在任何地方都使用django
reverse()
函数,尽可能保持一切干燥

但是,我在将其应用于客户端javascript时遇到了问题。有一个JS类根据传入的ID加载一些数据。是否有一种标准方法不硬编码这些数据应该来自的URL

var rq = new Request.HTML({
    'update':this.element,
}).get('/template/'+template_id+'/preview'); //The part that bothers me.

最合理的解决方案似乎是在JavaScript文件中传递URL列表,并在客户端提供与reverse()等效的JavaScript。唯一的反对意见可能是整个URL结构都被公开了


这里就是这样一个例子。

好的事情是假设从JavaScript到Django的所有参数都将作为request.GET或request.POST传递。在大多数情况下都可以这样做,因为JavaScript查询不需要格式良好的URL

然后唯一的问题是将url从Django传递到JavaScript。我为此出版了图书馆。示例代码:

url.py

def javascript_settings():
    return {
        'template_preview_url': reverse('template-preview'),
    }
def xzy(stuff=None):
  if not stuff:
    raise Http404
  ... < rest of the view code> ...
javascript

$.ajax({
  type: 'POST',
  url: configuration['my_rendering_app']['template_preview_url'],
  data: { template: 'foo.html' },
});

还有另一种方法,它不需要公开整个url结构或解析每个url的ajax请求。虽然它不是很漂亮,但它比其他的简单:

var url = '{% url blog_view_post 999 %}'.replace (999, post_id);

blog\u view\u post
URL当然不能包含神奇的
999
数字本身。)

与Anatoly的答案类似,但更灵活一些。将以下内容放在页面顶部:

<script type="text/javascript">
window.myviewURL = '{% url myview foobar %}';
</script>

或者别的什么。如果url包含多个变量,只需多次运行replace方法。

我发现了一个简单的技巧。如果您的url是如下模式:

"xyz/(?P<stuff>.*)$"
“xyz/(?P.*)”
如果您希望在JS中进行反向操作,而不实际提供任何内容(请根据JS运行时提供),您可以执行以下操作:

更改视图,为参数指定默认值-无,如果未设置,则通过响应错误来处理该值:

视图.py

def javascript_settings():
    return {
        'template_preview_url': reverse('template-preview'),
    }
def xzy(stuff=None):
  if not stuff:
    raise Http404
  ... < rest of the view code> ...
def xzy(stuff=None):
如果不是什么东西:
提高Http404
... < 视图代码的其余部分>。。。
  • 更改URL匹配以使参数可选:
    “xyz/(?P.*)?$”
  • 在模板js代码中:

    .阿贾克斯({ url:“{url views.xyz}}”+js_stuff, ... ... })


生成的模板应该在JS中包含不带参数的URL,在JS中,您可以简单地在参数上串联。

我喜欢Anatoly的想法,但我认为使用特定的整数是危险的。我通常希望指定一个值,比如说一个对象id,它总是要求为正,所以我只使用负整数作为占位符。这意味着向url定义中添加
-?
,如下所示:

url(r'^events/(?P<event_id>-?\d+)/$', events.views.event_details),
并在javascript中使用
replace
替换占位符
-1
,以便在模板中编写如下内容

url = window.myviewURL.replace('foobar','my_id');
<script type="text/javascript">
var actual_event_id = 123;
var url = "{% url 'events.views.event_details' event_id=-1 %}".replace('-1', actual_event_id);
</script>

var实际事件id=123;
var url=“{%url”events.views.event_details'event_id=-1%}”。替换('-1',实际_event_id);

这也很容易扩展到多个参数,并且特定参数的映射可以直接在模板中看到。

我提供的解决方案之一是在后端生成URL,并以某种方式将它们传递给浏览器

它可能并不适用于所有情况,但我有一个表(用AJAX填充),单击一行应该可以让用户从该表中找到单个条目

(我正在使用和)

AJAX中的每个条目都附带了url:

class MyObjectSerializer(serializers.ModelSerializer):
    url = SerializerMethodField()
    # other elements

    def get_url(self, obj):
       return reverse("get_my_object", args=(obj.id,))
加载ajax时,每个url作为数据属性附加到行:

var table = $('#my-table').DataTable({
   createdRow: function ( row, data, index ) {
      $(row).data("url", data["url"])
   }
});
单击后,我们将此数据属性用于url:

table.on( 'click', 'tbody tr', function () {
  window.location.href = $(this).data("url");
} );

在与之斗争之后,我想出了一个稍微不同的解决方案

在我的例子中,我需要一个外部JS脚本来在点击按钮时调用AJAX调用(在完成一些其他处理之后)

在HTML中,我使用了一个HTML-5自定义属性

<button ... id="test-button" data-ajax-target="{% url 'named-url' %}">
这意味着Django的模板系统为我完成了所有的
reverse()

您将在JS中拥有一个对象,其中包含django中定义的所有URL。这是迄今为止我发现的最好的方法


您需要做的唯一一件事是在基本模板的头部添加生成的js,并在每次添加url时运行管理命令更新生成的js,我在配置url时总是使用字符串而不是整数,即。 而不是像

... r'^something/(?P<first_integer_parameter>\d+)/something_else/(?P<second_integer_parameter>\d+)/' ...
然后,在javascript中,我可以将字符串作为占位符,django模板引擎也不会抱怨:

...
var url     = `{% url 'myapiname:urlname' 'xxz' 'xxy' %}?first_kwarg=${first_kwarg_value}&second_kwarg=${second_kwarg_value}`.replace('xxz',first_integer_paramater_value).replace('xxy', second_integer_parameter_value);

        var x = new L.GeoJSON.AJAX(url, {
            style: function(feature){ 
...
url将保持不变,即
something/911/something\u else/8/

这样可以避免整数参数替换问题,因为as参数中不需要字符串占位符(a、b、c、d、…z)

我希望看到更多关于这方面的讨论。一、 同样,认为url解析回调太重。有人在这个主题上发现了其他的东西吗?这里有一个类似的问题:奇怪的是,我在发布我的主题时没有找到那个。虽然没有令人满意的答案,呵呵。我一直在这样做,感觉有点脏,但在这里看到它让我感觉稍微好一点。记住URL参数的预期字符类型。如果URL参数接受数字,则此操作有效,但如果它只需要字母,则不起作用。我还建议使用大约000,因为它不应该存在(至少对于object.id而言),这是肮脏的。如果要在javascript中使用url,最好让它接受GET参数,然后不需要替换。GET是多年来的标准,所有javascript框架都支持传递一个数据结构,该结构将被转换为参数(正确转义也与此不同),并且可读性更好。@jpimental如果将
000
传递给Django,它将在URL中呈现为
0
@dalore使用GET参数的一个问题是RESTURL,例如,
/api/model/3/
是与
/api/model/
不同的URL
...
var url     = `{% url 'myapiname:urlname' 'xxz' 'xxy' %}?first_kwarg=${first_kwarg_value}&second_kwarg=${second_kwarg_value}`.replace('xxz',first_integer_paramater_value).replace('xxy', second_integer_parameter_value);

        var x = new L.GeoJSON.AJAX(url, {
            style: function(feature){ 
...