Django | JS variable inside dynamic URL - javascript

I'm trying to pass a javascript variable inside a dynamic url using Django. I have the following path
path('task-update/<str:pk>/', updateTask, name='task-update'),
I'm able to retrieve the "Task" fields I created (id, title, description, ...) depending on what task I select inside the HTML (this is done using AJAX and the Django-REST Framework). However, I'm having some trouble on rendering javascript values inside dynamic urls
var url = `{% url 'task-update' pk=${activeItem.id} %}`
The ${activeItem.id} is where I'm having some trouble, I tried assigning it to a variable and passing that into the URL but it doesn't work.
A workaround I've been using is
var url = `http://127.0.0.1:8000/task-update/${activeItem.id}/`
however I'd like to use django's template tags

After searching for quite a bit this was the best neat-looking solution I found (also the only one): django-js-urls.
Just pip install django-js-urls and add 'js_urls' to your INSTALLED APPS.
Afterwards add simply add JS_URLS to your settings.py file and put the names of the paths you'd like to use. In my case I only added task-update, it looks something like this
JS_URLS = (
'task-update',
)
Then, all you need to do is add the following in the URLs root module
from js_urls.views import JsUrlsView
urlpatterns = [
# other urls
url(r'^js-urls/$', JsUrlsView.as_view(), name='js_urls'),
]
And include the following js in the template
<script src="{% url 'js_urls' %}" type="text/javascript"></script>
URLs can be used using the window.reverse function
var url = window.reverse('task-update', { pk: activeItem.id });

I found a trick that might work under most circumstances:
var url = "{% url 'task-update' pk=12345 %}".replace(/12345/, ${activeItem.id});
It's clean, and it doesn't break DRY principle.

Related

Concatenate twig path in javascript string

I'm working on a PHP site with Slim and Twig-View. Within this site I'm working on live search with Ajax. The idea is for the user to search for a string and for search results to appear as the user types. Everything is working fine so far. I'm able to get the results and render them with the appropriate image and text. The problem comes when creating the link for each result. With Slim Twig-view, when you create a link, you use the path_for() function:
{{ path_for('episode', { 'show_slug': path, 'episode_slug': episode }) }}';
In this case, the values for path and episode are being generated by Javascript. The problem is that if I try the following:
var path = '{{ path_for('episode', { 'show_slug': results[i].showPath, 'episode_slug': results[i].url }) }}';
I have also tried using double quotes:
var path = "{{ path_for('episode', { 'show_slug': results[i].showPath, 'episode_slug': results[i].url }) }}";
The resulting link is myurl/shows// instead of myurl/shows/show-slug/episode-slug
So, path_for() is actually working, but it's not reading the values for results[i].showPath and results[i].url. It looks like this is just a concatenation issue, but I can't figure out how to do it correctly.

How can I get the url working from js html builder in Django?

I am currently building a web app using Django.
I've build a calendar using JS and I am building HTML basically from the Js File.
I am trying to include hrefs in each calendar day. For example :
{% url 'calendarDay' day=28 month=12 year=2016 %} is what should have for 28/12/2016 date.
If I try to go to this url from anywhere else in my templates it works. For some reason it is not working when I pass the html from js.
This is what I have in my urls:
url(r'^calendar/$', views.calendar, name='calendar'),
url(r'^calendar/(?P<day>\w+)/(?P<month>\w+)/(?P<year>\w+)/$',views.calendar, name = 'calendarDay'),
This is my js builder function (the part that builds the previous month's days):
if (FirstDay.getDay()==0){
for (var i=LastMonthDays-5; i <= LastMonthDays; i++) {
href="<a href=\"{% url 'calendarDay' day="+i+" month="+(pastMonth.getMonth()+1)+" year="+pastMonth.getFullYear()+" %}\">"
html +=href+ "<li>"+(i)+"</li></a>";
}
}
This is how the html file looks like when I inspect the page:
<li>28</li>
For some reason the urls that it gets is: http://127.0.0.1:8000/calendar/%7B%%20url%20'calendarDay'%20day=28%20month=12%20year=2016%20%%7D
And ofcourse I get the following error:
The current URL, calendar/{% url 'calendarDay' day=28 month=12 year=2016 %}, didn't match any of these.
What might be the issue here?
Templatetags will be rendered in server side, before javascript. you should create a javascript function for generating your calendar urls.

How to pass off dynamically generated xml that is referenced to a url in javascript?

In my Django web application I've got a python script which generates an xml string. I can access this script by the help of Django so that the url 'my_python_script_file/' reference to the script (I do this so that I can dynamically generate it). My question is then simply, how do I pass this XML off to a variable in my javascript code, so that it would look like something like this?
var myXML = magic_function('my_python_script_file');
If you absolutely must reference the resulting XML from a URL, I would suggest getting it using the requests library:
import requests
from django.core.urlresolvers import reverse
from django.shortcuts import render
def my_view(request):
response = requests.get(reverse('your_url_name'))
xml = response.text
return render(request, 'your-template.html', {'xml': xml})
You can inject server-side values from Django into JavaScript like you would any other value, but you would need to do this in a <script> tag that is in your template, not in an external reference:
# your-template.html
<script type="text/javascript">
var xml = "{{ xml }}";
</script>

Django: reverse parametrized url in JavaScript

let's say one of my urlpatterns looks like this.
url('^objects/update/(?P<pk>\d+)$', views.UpdateView.as_view(), name = 'update-object'),
I need to redirect user to the update page depending on the selected object (the list of objects is populated using Ajax). So I'd like to pass that named url pattern to the JavaScript, in order to build the actual url on the client side.
Example of what I want to achieve:
pass the name 'update-objects' to the function
get the actual url pattern, replace (?P<pk>..) with {pk}
pass the result to the javascript, resulting in : objects/update/{pk}
any tips?
thanks
to make it more clear: at the moment of rendering, I can't do url reverse because the PK is not known yet. I need to make kind of javascript-urlpattern which will later be converted to the real url (i.e. my JS code will replace {pk} part with the actual pk value)
The actual URL reversing must happen on the server side. There are several ways to do this, and the most elegant of these probably depends on how exactly your script and markup are set up for this. One thing I've done recently is to attach the URL to a logical element using HTML5 data attributes, which are easy to retrieve using jQuery. If you're not using jQuery, I'll leave it up to you to translate to pure JS. You haven't provided any code or specifics for your client-side, so I'm kind of shooting in the dark here, but maybe this will give you the idea:
Django HTML template:
<ul class="object-list">
{% for object in objectList %}
<li data-update-url="{% url update-objects object.pk %}">object.name</li>
{% endfor %}
</ul>
JS:
$('.object-list').on('click', 'li' function () {
var updateUrl = $(this).data('update-url')
...
});
It sounds like you need to make an additional ajax call once the object has actually been selected. Don't try and second guess your url.conf by trying to work out the url on the client side - you'd just be making trouble for yourself later. Wait till you can get a pk, then use django's reverse function to give you your url (doing anything else violates DRY).
How about creating a simple view that returns the url -
from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseBadRequest
def get_url(request):
if request.is_ajax() and request.method == 'POST':
obj_id = request.POST['obj_id']
url = reverse('object-update', kwargs{'pk': obj_id})
return HttpResponse(obj_id)
return HttpResponseBadRequest()
Then write a javascript function that gets the url using an ajax call to your new view and then redirects. You'd call this function as soon as the object's been selected. I would suggest using JQuery to do this, pure javascript will require you to write more code, and probably write browser specific code (depending on your target). Also it supports dealing with django's csrf protection (you'll need to implement this for ajax calls if you haven't already).
var redirect = function(obj) {
$.ajax({
url: '/your-get-url-view/',
method: 'post',
data: {'obj_id': obj},
success: function(url){
window.location = url;
}
});
}
I'm afraid I don't know how you're getting from the selected object to the pk (For simplicity I've assumed it's available to the redirect function) - you may have to do some processing in the view to get there.
I haven't tested the above code, but it should give you an idea of what I'm suggesting.
Try this one:
Reverse method for generating Django urls
https://github.com/mlouro/django-js-utils
One more
https://github.com/Dimitri-Gnidash/django-js-utils
If you have a URL that only has one PK field in it, you could resolve it with any number (e.g. 0), then substitute the number as required.
In my scenario my URL had a pk then an upload_id, so I had to replace on the right most instance of a 0, with <upload_id>, which the JS would replace this string occurance as required:
detele_url_upload_id_0 = reverse(f'{APP_NAME}:api_upload_delete', args=[pk, 0])
prefix, suffix = detele_url_upload_id_0.rsplit('0', 1)
context['generic_delete_url'] = prefix + '<upload_id>' + suffix
Then in the JS:
const deleteUrl = genericDeleteUrl.replace('<upload_id>', uploadId)

Use Separate js File And use Url Helpers in it with ASP.NEt MVC 3 and Razor View Engine

I ask a similar question here and Darin Dimitrov answer that we can't use Url helper like $.ajax({ url: '#Url.Action("Index")', . . . in separate js file so what is your suggestion to use Url helper in view page and pass it to javascript, I don't want to use hard code url, I need to find it with Url helper.?
Use a hidden field to store your url, then use javascript to read the hidden field, then use that in your code. That way you can keep the JS file separate to the view. Something like this:
//In Your View
#Html.Hidden("MyURL", Url.Action("Index"))
//In Your JS
var myUrl = $("#MyURL").val();
$.ajax({ url: myUrl , . . .
The easiest way is just to create a global variable called something and just reference to it in your external JS
var baseURL = '#Url.Action("Index")';
Inside your external JS
$.ajax({ url: baseURL + "Action"
You can use RazorJS for that purpose. It allows writing Razor-Style C# or VB.NET inside your JavaScript files. There is a short description available here.
There is no need to have hidden field, even this works too in the external .js file.
var myUrl = /ControllerName/ActionName;
$.ajax({ url: myUrl , . .
Take a look at Generating External JavaScript Files Using Partial Razor Views. In this blog post, I describe how you can make use of regular Razor views and a custom action filter to render external JavaScript files that can have Razor code in them.
I used a similar approach to raklos, but was looking to get the root directory path in all places, so I went with the code below.
#Html.Hidden("AppUrl", Url.Content("~"))

Categories