Call django urls inside javascript on click event
Asked Answered
L

5

14

I got a javascript onclick event inside a template, and I want to call one of my Django urls with an id parameter from it, like this :

$(document).on('click', '.alink', function () {
        var id = $(this).attr('id');
        document.location.href ="{% url 'myapp:productdetailorder' id %}"
});

Course this is not working at all. Any idea ?

Thanks in advance !!

Lenticularis answered 18/5, 2016 at 22:21 Comment(3)
What exactly is your goal? The variable id referenced inside the Django template tags is not the same one in the javascript. Using Django templating within javascript generally makes for inelegant code, but it sounds like what you're wanting to do is essentially perform string concatenation in the javascript. Think of the Django tags as a function returning a string, and write the corresponding javascript to concatenate.Chandlery
Hi, thanks for commenting, id it's the product id i want to set for the url so my view can process it and show it's info in another template. I know i may be doing wrong but thats exactly what i need : a good way to do itLenticularis
It seems as though the relevant URL is to an endpoint in your API. You would typically hardcode this URL into your javascript code since an API is not dynamic and should remain stable unless you make changes to it. So, I recommend just writing out the URL in your javascript code.Chandlery
O
32

I think the best way to do this is to create a html data-* attribute with the URL rendered in a template and then use javascript to retrieve that.

This way you avoid mixing js/django template stuff together. Also, I keep all of my JS in a separate file outside the view (which is a much better practice in general), and therefore trying to mix these two won't work.

For instance, if you have a url you want, just create an html hidden element:

<input type="hidden" id="Url" data-url="{% url 'myapp:productdetail' id %}" />

Then, in your JS:

$(document).on('click', '.alink', function () {
    var url = $("#Url").attr("data-url");
});      

I frequently use this pattern for dropdown lists so that I don't have to serve all of the options when I first render the page (and this usually speeds it up).

Odelsting answered 13/4, 2018 at 20:29 Comment(1)
Using {% url %}, or any other tags that might add user data, is vulnerable to XSS attacks - the safe way to pass data to JavaScript in templates is the json_script filter: docs.djangoproject.com/en/3.0/ref/templates/builtins/…Sassenach
S
22

You are trying to access javascript variable that is created at user click on frontend within your Django template at the backend. But, you already know that it would not work.

A better option would be to reconstruct the url in javascript:

$(document).on('click', '.alink', function () {
    // Generate URL without "id" bit
    var url = "{% url 'myapp:productdetail' %}";

    var id = $(this).attr('id');

    // Construct the full URL with "id"
    document.location.href = url + "/" + id;
});

If you don't have a django url helper that would return a URL that you need, you can print out just any and simply replace it in javascript like so:

$(document).on('click', '.alink', function () {
    var url = "{% url 'myapp:productdetail' 123 %}";
    var id = $(this).attr('id');

    // Construct the full URL with "id"
    document.location.href = url.replace('123', id);
});
Shrovetide answered 18/5, 2016 at 22:57 Comment(5)
Thanks for your answer, i know we're close, but doing it this way throws me a reverse url error : Reverse for 'productdetail' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['myapp/product/(?P<id_ac>\\d+)/$'] .....and i think it's because the id parameter is required from the beginning, what do you think ?Lenticularis
Yeah, that's django's routes helper. Just call another url helper that would print the value you need. If you don't have one, then you could just print with any id and replace it in js. I'll update my answer.Shrovetide
Using {% url %}, or any other tags that might add user data, is vulnerable to XSS attakcs - the safe way to pass data to JavaScript in templates is the json_script filter: docs.djangoproject.com/en/3.0/ref/templates/builtins/…Sassenach
@AdamJohnson I read the link but due to my lack of knowledge and ignorance cannot understand how to achieve the above in the safer way. So can you write the code showing how to do it. And all this has to be done inside <script></script>. The values cannot be assigned inside the template but JS. Thank youShearwater
This method is not a good idea. What happens if this javascript doesn't go through the django template engine (i.e. you put it in static files where it's supposed to be)? Your url is not rendered.Odelsting
L
6

The problem seems to be in that you using django template language in js static file(am i right?) Try to move that variable to html template file, ex:

<script type=text/javascript>
var a = "{% url'myapp:productdetail' id %}" </script>

And in static js file:

document.location.href = a;
Luxuriate answered 19/5, 2016 at 6:47 Comment(1)
Don't mix JS and Html! Maintenance nightmare!Odelsting
U
-1

You can use javascript code " window.location.origin " , this will give base url and after that you can add "/pathname"

Use answered 25/1, 2021 at 6:41 Comment(1)
What happens when someone refactors the django url config? Broken links all over the place in UI.Odelsting
O
-1

You don't need to pass any of that...

Write.

 location.href = "/" + id

That's all.

Octagon answered 1/6, 2021 at 10:24 Comment(3)
In the accepted answer: document.location.href = url + "/" + id; Isn't it basically the same idea?Zackzackariah
Not really the same.... and it's shorter. And that one is unlikely to work in eternal JavaScript.Octagon
What happens when someone refactors the url config? Broken links all over the place in UI.Odelsting

© 2022 - 2024 — McMap. All rights reserved.