在AJAX调用中使用Django URL标签

9

有很多关于Django和AJAX使用的帖子和页面,我在过去的一天左右阅读了数百篇文章以寻找这个问题的答案。简要概述:

许多示例都显示硬编码的URL,如下所示:

$.post("/projects/create/", {"name" : name}, function(data) {...

有些人使用URL模板标签,但没有参数:

$.post("{% url create_project %}", {"name" : name}, function(data) {...

然而,我想在URL中包含一个Django风格的参数。以下是我的URL定义:

url(r'ajax/entity_name/(?P<pk>\w+)/$',EntityAjaxView.as_view(),name='entity_name'),

是的,我正在使用基于类的视图,并且它是基于DetailView。此视图默认情况下查找URL中提供的pk值,在普通模板中,我会使用:
```html {{ object.pk }} ```
来获取对象的主键值。
{% url entity_name id_number %}

提供一个链接。在我的代码中,我想获取输入框中输入的pk值。以下是我的JavaScript片段(不起作用):

var id_number = $('#id_endowmententity_set-' + rownum + '-id_number').val()
$.ajax({
    type: "GET",
url: '{% url entity_name id_number %}',

所以,我的问题是,我能否使用URL模板标签和来自输入框的值?

(我知道我可以使用POST而不是GET,并在POST数据中传递id_number,但这与DetailView不兼容。)

4个回答

17

Django是一个服务器端应用程序。Javascript是客户端的。Django模板在服务器上进行渲染,因此{% url entity_name id_number %}被在服务器端评估,然后它的值返回给客户端。正因为如此,你不可能将Django模板与javascript结合起来。但是,有几件事情可以做来解决你的问题。

由于您正在进行ajax调用,并且ajax调用依赖于某些用户输入,通常最好的方法是通过查询字符串(URL中?之后的内容)或发送POST数据将任何类型的用户输入发送到服务器。因此,最简单的方法是更改您的URL,不包括pk,而是由视图作为GETPOST数据的一部分获取它。

url(r'ajax/entity_name/$', EntityAjaxView.as_view(), name='entity_name'),

并且视图(抱歉我不熟悉基于类的视图):

def entity_name(request):
    pk = request.GET.get('pk')
    ...

在我看来,那似乎是最优雅的解决方案。但如果你绝对需要在客户端构建URL,你可以在服务器端生成一个模板URL,然后在客户端替换所需的部分以获取完整的URL。不过,这需要更多的维护工作,因此更容易出错。这种方法的简单JS示例:

var id_number = $('#id_endowmententity_set-' + rownum + '-id_number').val(),
    url = '{% url entity_name 0 %}'.replace('0', id_number);
$.ajax({
    type: "GET",
    url: url,
    ...
});

我尝试在我的函数视图中使用带有命名URL的ajax回调,例如err_key="{% url 'pcd_list' %}",并使用它来创建一个链接,如$('#ajxErr').html(var_err + ' <a href=" ' + var_err_url + '">Check</a>');,其中var_err_url是从Ajax调用返回的err_key值的变量。但是它失败了。 但是,如果我在我的函数视图中使用err_key="path_generated_from_named_url",它可以正常工作。是否有一种方法可以像我上面的第一个示例那样使用命名URL? - Love Putin Not War

3

可以使用属性在所选元素上设置Ajax url,并像Django urls一样运作。重要的是,甚至可以在JavaScript文件中访问该URL。我经常使用它。

<div class="card-body" id="js-products" data-url="{% url 'chart-data' %}">
    <div class="chart-area">
      <canvas id="testChart"></canvas>
    </div>
  </div>

注意:设置在父 div 上的 data-url 属性 JAVASCRIPT
$(document).ready(function () {

var endpoint = $("#js-products").attr("data-url");
var defaultData = [];
var labels = []
$.ajax({
    method: 'GET',
    url: endpoint,
    success: function (data) {
        labels = data.labels
        defaultData = data.data_default
        setChart()


    },
    error: function (error_data) {
        console.log(error_data)
    }
})

function setChart() {
    var ctx = document.getElementById('testChart').getContext('2d');
    var myChart = new Chart(ctx, {
        type: 'line',
        responsive: true,
        data: {
            labels: labels,
            datasets: [{
                label: 'Monthly Performance',
                data: defaultData,

            }]
        },
        options: {
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true
                    }
                }]
            }
        }
    });
 }
});

DJANGO VIEWS

我正在使用Django REST框架的类视图,但您也可以使用函数或基于类的视图。

class ChartData(APIView):

authentication_classes = []
permission_classes = []

def get(self, request, format=None):
    labels = ['Products', 'User', 'May']
    data_default = [SeedProduct.objects.all().count(),
                    User.objects.all().count(), 4]
    data = {
        'labels': labels,
        'data_default': data_default,
    }

    return Response(data)

DJANGO URLS: 从views中导入视图类

path('api/chart/data', views.ChartData.as_view(), name="chart-data"),

我认为这是目前许多用例的最佳答案。例如,我有一个<tbody>需要使用ajax调用进行填充。为此,我在需要以此方式填充的表格上使用data-url。在jquery中易于获取和使用。只需确保保护您的端点免受未经身份验证的调用即可。 - logicOnAbstractions

0

这对我有用。

我的URL是:

path('myurl/<str:type>', views.myfunction, name='myfunction')

我的views.py文件:

def myfunction(request,type):
    return render(request, "payment.html", context)

在我的模板中,我通过以下方式解决了这个问题:
<button type="button" class="btn"
    onclick="myfunction('forward');">My Button Name
</button>

<script>
function myfunction(type){
    let url = "{% url 'appName:myfunction' 'ok' %}".replace('ok', type);
    $.ajax({
      method: 'POST',
      url: url,
      data: {
          csrfmiddlewaretoken: '{{ csrf_token }}'
      }
  });
  }

</script>

0

往返服务器以获取URL非常耗时。保持URL干燥并避免这种情况的最佳策略是生成模拟Django本地url reverse函数的javascript,然后将该代码与其余客户端JS一起静态提供。

django-render-static正是如此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接