2

I am trying to pass a parameter to a django URL in the template. The URL is configured as:

url(r'^reviewrecord/(?P<pk>\d+)/$', views.MyView, name='reviewrecord')

Now, I am calling this from a ajax block in a javascripyt function. The javascript function is declared as:

function EditDialog(pk) {
    $.ajax(
      {
         url: "{% url 'reviewrecord' pk=pk %}",
         type: "POST",
         data: postData,
       });
}

Doing this results in:

Reverse for 'reviewrecord' with arguments '()' and keyword arguments '{u'pk': ''}' not found. 2 pattern(s) tried: ['reviewrecord/$', 'reviewrecord/(?P<pk>\\d+)/$']

However, I have verified that if I hard-code the pk value, it works. So, replacing the url paranmeter with something like:

url: "{% url 'reviewrecord' pk=5 %}",

This works. So, I am somehow unable to refer to the passed pk value in the JS function in the URL tag.

In light of the comments below, I can do the following:

function EditDialog(pk) {
            $.ajax({
                url: "{% url 'populatereviewform' %}",
                method: 'GET',
                data: {
                pk: pk
            },
            success: function(formHtml){
                //place the populated form HTML in the modal body
                $('.modal-body').html(formHtml);
                $( "#dialog" ).modal({width: 500, height: 500});
            },
            dataType: 'html'
            });

This does show the dialog where everything is populated correctly.

I am not sure how to achieve something similar with this case. I tried something like:

var postData = $("#review-form").serializeArray();
$.ajax(
            {
                url: "{% url 'reviewrecord' pk %}",
                type: "POST",
                data: {
                  data: postData,
                  pk: pk,
            });

This was more like a desperate attempt but it did not work.

EDIT

THE HTML template is as follows:

{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %}Cloud | Review data {% endblock %}

{% block content %}
    {% load static %}
    {% load render_table from django_tables2 %}

    <div id="dialog" class="modal" title="Edit" style="display:none">
        <div class="modal-dialog">
          <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">Review Uploaded Image</h4>
              </div>
              <div class="modal-body">
              </div>
          </div>
        </div>
    </div>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
    <link rel="stylesheet" type="text/css" href="{% static "project.css" %}" />

    <script>

        // using jQuery            
        function EditDialog(pk) {
            $.ajax({
                url: "{% url 'populatereviewform' %}",
                method: 'GET',
                data: {
                pk: pk
            },
            success: function(formHtml){
                //place the populated form HTML in the modal body
                $('.modal-body').html(formHtml);
                $( "#dialog" ).modal({width: 500, height: 500});
            },
            dataType: 'html'
            });

            $("#dialog").submit(function(e)
            {
                $.ajaxSetup({
                    beforeSend: function(xhr, settings) {
                        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                            xhr.setRequestHeader("X-CSRFToken", csrftoken);
                        }
                    }
                });

                var postData = $("#review-form").serializeArray();
                $.ajax(
                {
                    url: "{% url 'reviewrecord' pk=pk %}",
                    type: "POST",
                    data: postData,

                    success:function(data, textStatus, jqXHR)
                    {
                        //var transformed = data.replace('/-1/g', pk.toString())
                        $('.modal-body').html(data);
                    },
                    error: function(jqXHR, textStatus, errorThrown)
                    {
                        alert(errorThrown);
                    }
                });
                e.preventDefault();
                e.unbind(); //unbind. to stop multiple form submit.
            });
            return false;
            }
    </script>

    {% if reviews %}
     <div class="function-page">
         <div class="table-form">
                <div class="function-container">
                    {% render_table reviews %}
                </div>
         </div>
     </div>
    {% else %}
    <div class="form">
                        <div class="figcaption">Looks like you are all caught up! There is nothing to review.</div>
    </div>
    {% endif %}

{% endblock %}
Luca
  • 10,458
  • 24
  • 107
  • 234
  • It seems that pk has no value passed. Are you sure it has a value? – nik_m Mar 20 '17 at 15:51
  • Tried that as well. results in: `Reverse for 'reviewrecord' with arguments '('',)' and keyword arguments '{}' not found. 2 pattern(s) tried: ['reviewrecord/$', 'reviewrecord/(?P\\d+)/$']` – Luca Mar 20 '17 at 15:52
  • How is this surprising? The Django template tag is rendered on the server side, long before the JS can run. – Daniel Roseman Mar 20 '17 at 15:52
  • Right...So, what would be a way to pass this parameter in such a case then... – Luca Mar 20 '17 at 15:54
  • 1
    The way I've done this in the past is to put an impossible value in the template tag - eg `00000` - and then use the string `.replace()` method in the JS to replace it with the actual value. – Daniel Roseman Mar 20 '17 at 15:57
  • @DanielRoseman I also edited the question to show things that worked – Luca Mar 20 '17 at 15:58
  • Well now I'm no longer sure what you're asking. What happened? – Daniel Roseman Mar 20 '17 at 16:01
  • Does this answer your question? [Calling Django \`reverse\` in client-side Javascript](https://stackoverflow.com/questions/2724383/calling-django-reverse-in-client-side-javascript) – Flimm Nov 24 '20 at 08:20

1 Answers1

1

For a template tag like {% url 'reviewrecord' pk=pk %}, whatever is between the brackets, like the pk variable, has to be rendered ahead of time. It can't be passed from javascript.

Now, as you showed in your second example, you can pass the data through a GET or POST request:

function EditDialog(pk) {
        $.ajax({
            url: "{% url 'populatereviewform' %}",
            method: 'GET',
            data: {
            pk: pk
        },
...

which will GET a url like /populatereviewform?pk=5 where pk=5.

If you really want django to give your a url from a javascript call, you have to create another view. Javascript:

function EditDialog(pk) { //pk=5
 $.get("{% url 'geturl' %}",{pk:pk}) // /geturl?pk=5
  .done(function(data){ // url returns data
    var the_url = data; // /reviewrecord/5
    $.ajax({
      url: the_url,
      type: "POST",
      data: postData,
  });
 });
}

urls.py:

url(r'^geturl/$', views.get_url_view, name='get_url'),

views.py:

from django.core.urlresolvers import reverse
from django.http import HttpResponse
...
def get_url_view(request):
  pk = request.GET['pk']
  the_url = reverse('reviewrecord', kwargs{'pk':pk})
  return HttpResponse(the_url)

Though that seems like a lot of work for a variable you could pass through GET or POST data.

Jeremy S.
  • 1,086
  • 8
  • 18
  • Thanks for the reply. the problem is when I open the dialog the first time, it works great. On the second time, the primary key is not updated for the new value. Essentially `$.get("{% url 'geturl' %}",{pk:pk}) // /geturl?pk=5` keeps the primary key to the old value for some reason unknown to me yet. – Luca Mar 21 '17 at 12:26
  • It sounds like it's a problem somewhere in your Javascript. I can't be sure unless I see the whole project. 2 things to test: 1. does `http://yoursite.com/geturl/?pk=5` give the right url? 2. see if you can call the `EditDialog()` function with different pk values. Maybe create some buttons with `` – Jeremy S. Mar 23 '17 at 00:31
  • All those things did work. In the end, I ended up storing the `pk` value in a sessionStore and that worked. The ajax part somehow never had access to the newer `pk` value even though the rest of the JS script did. Maybe it has not been rendered....not sure at all... – Luca Mar 23 '17 at 06:29