Django Javascript中的DRY URL

时间:2010-04-27 19:30:59

标签: javascript ajax django google-app-engine dry

我在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.

10 个答案:

答案 0 :(得分:32)

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

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

blog_view_post网址当然不能包含魔术999号码。)

答案 1 :(得分:9)

刚刚解决这个问题,我提出了一个稍微不同的解决方案。

就我而言,我希望外部JS脚本在按钮点击时调用AJAX调用(在进行其他处理之后)。

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

<button ... id="test-button" data-ajax-target="{% url 'named-url' %}">

然后,在javascript中,只是做了

$.post($("#test-button").attr("data-ajax-target"), ... );

这意味着Django的模板系统为我做了所有reverse()逻辑。

答案 2 :(得分:8)

最合理的解决方案似乎是在JavaScript文件中传递一个URL列表,并在客户端上提供相当于reverse()的JavaScript。唯一的反对意见可能是暴露了整个URL结构。

以下是function(来自此question)。

答案 3 :(得分:4)

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

然后唯一的问题是将URL从Django传递给JavaScript。我已经为此发布了库。示例代码:

<强> urls.py

def javascript_settings():
    return {
        'template_preview_url': reverse('template-preview'),
    }

<强>的javascript

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

答案 4 :(得分:4)

与阿纳托利的答案类似,但更灵活一点。放在页面顶部:

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

然后你可以做类似

的事情
url = window.myviewURL.replace('foobar','my_id');

或其他什么。如果您的网址包含多个变量,则只需多次运行替换方法。

答案 5 :(得分:2)

我喜欢阿纳托利的想法,但我认为使用特定的整数是危险的。我通常想要指定一个对象id,它总是要求为正,所以我只使用负整数作为占位符。这意味着将-?添加到网址定义中,如下所示:

url(r'^events/(?P<event_id>-?\d+)/$', events.views.event_details),

然后我可以通过编写

来获取模板中的反向URL
{% url 'events.views.event_details' event_id=-1 %}

在javascript中使用replace替换占位符-1,以便在模板中我会写出类似

的内容
<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>

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

答案 6 :(得分:1)

我找到了一个简单的技巧。如果你的网址是这样的模式:

"xyz/(?P<stuff>.*)$"

并且您希望在没有实际提供内容的情况下反转JS(推迟到JS运行时提供此功能) - 您可以执行以下操作:

更改视图以给参数一个默认值 - 无,并通过响应错误处理(如果未设置):

<强> views.py

def xzy(stuff=None):
  if not stuff:
    raise Http404
  ... < rest of the view code> ...
  • 更改网址匹配,使参数可选:"xyz/(?P<stuff>.*)?$"
  • 在模板js代码中:

    .ajax的({    url:“{{url views.xyz}}”+ js_stuff,    ...... })

生成的模板应该具有JS中没有参数的URL,而在JS中,您可以简单地连接参数。

答案 7 :(得分:0)

我带来的解决方案之一是在后端生成网址并以某种方式将它们传递给浏览器。

它可能不适用于所有情况,但我有一个表(填充了AJAX)并且单击一行应该将用户带到此表中的单个条目。

(我正在使用django-restframeworkDatatables)。

AJAX的每个条目都附有网址:

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

    def get_url(self, obj):
       return reverse("get_my_object", args=(obj.id,))

在加载ajax时,每个url作为数据属性附加到row:

var table = $('#my-table').DataTable({
   createdRow: function ( row, data, index ) {
      $(row).data("url", data["url"])
   }
});

点击后我们将此数据属性用于网址:

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

答案 8 :(得分:0)

使用此套餐:https://github.com/ierror/django-js-reverse

你的JS中有一个对象,其中包含django中定义的所有url。这是我到目前为止找到的最佳方法。

您唯一需要做的就是在基本模板的头部添加生成的js并运行管理命令以在每次添加URL时更新生成的js

答案 9 :(得分:0)

在配置url时,我总是使用字符串而不是整数,即 而不是

... r'^something/(?P<first_integer_parameter>\d+)/something_else/(?P<second_integer_parameter>\d+)/' ...

例如:something/911/something_else/8/

我会用'w'代替整数的'd',像这样...

... r'^something/(?P<first_integer_parameter>\w+)/something_else/(?P<second_integer_parameter>\w+)/' ...

然后,在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_else/8/。 这样就避免了整数参数替换的问题,因为不希望将字符串占位符(a,b,c,d,... z)作为参数使用