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 %}
8
  • It seems that pk has no value passed. Are you sure it has a value? Commented Mar 20, 2017 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<pk>\\d+)/$'] Commented Mar 20, 2017 at 15:52
  • How is this surprising? The Django template tag is rendered on the server side, long before the JS can run. Commented Mar 20, 2017 at 15:52
  • Right...So, what would be a way to pass this parameter in such a case then... Commented Mar 20, 2017 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. Commented Mar 20, 2017 at 15:57

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

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.
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 <a href="javascript:EditDialog(3)">
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...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.