Get relative path in Django - javascript

I've created a map where I want to implement some kml files into it . If i harcode the url it works but im trying to pass it through a variable because Im dealing with many kml files in a for loop.
Even though the url path im getting in console is right i dont get the result i need.Any idea how to fix that?
view:
def map(request):
field_list = models.Field.objects.all()
context = {
"title": "Map",
"field_list": field_list,
}
template = 'agriculture/map.html'
return render(request, template, context)
If i hardcode the url it goes like this :
var polygon = omnivore.kml("{% static '../media/kml/user_admin/2022-04-07-2-Arnissa_cherry.kml' %}", ... );
I've tried doing it like this but even though the path Im getting is correct it seems django does not read the path(kml is the FileField in my model):
map.html
{% for field in field_list %}
$(".search_area").append(new Option("{{field.friendly_name}}")); //friendly name
var kmldir = "../media/" + "{{field.kml.name}}"
console.log(kmldir) // ../media/kml/user_admin/2022-04-07-2-Arnissa_cherry.kml
var polygon = omnivore.kml("{% static 'kmldir' %}", null, new L.GeoJSON(null, { //file url
style: function() {
return {
color: 'red',
transparent: true,
opacity: 1,
fillOpacity: 0.05
}}
}));
kml_arr.push([polygon, "{% static 'kmldir' %}"]); //file url
{% endfor %}

I tried a different approach and it worked
{% for field in field_list %}
{% with "../media/"|add:field.kml.name as fieldname %}
$(".search_area").append(new Option("{{ field.friendly_name }}")); //friendly name
var polygon = omnivore.kml('{% static fieldname %}', null, new L.GeoJSON(null, { //file url
style: function() {
return {
color: 'red',
transparent: true,
opacity: 1,
fillOpacity: 0.05
}
}
}));
kml_arr.push([polygon, '{% static fieldname %}']); //file url
{% endwith %}
{% endfor %}

Related

nunjucks fetch data from input

I am trying to retrieve below field values in nunjucks following below template
Json data -
{
"user": {
"custom": [
{
"payload": "{ f_name=user, l_name=name, source=facebook, contact=email }"
}
]
}
}
Nunjucks Template -
{% set u = user %}
{% set data = u['custom'][0]['payload'] %}
Hello {{ data }}
This returns the below output
Hello { f_name=user, l_name=name, source=facebook, contact=email }
However, I would like to get the individual elements from the {{data}}
How can I fetch the f_name, l_name, source, contact fields from the above json data.
Please note the payload is a string and not a json object
You don't show us how user is pulling your JSON data into nunjucks, so I'll just spill out my take on this. Take advantage of the JavaScript split method, and the template engine loops and filters to give you the results you need.
I'm assuming there is more to your JSON data. If so, here is a short guide to help pull your 4 string items out of payload.
The JSON Data:
//sample JSON Data
const sampleData = [{
"user": {
"custom": [{
"payload": "{ f_name=user, l_name=name, source=facebook, contact=email }"
}]
}
}];
module.exports = sampleData;
The View:
{% for string in mSampleData %} //mSampleData is similar to your "user" template object.
{% for mval in string['user']['custom'] %}
{% set mstring = mval['payload'].replace('{', '').replace('}', '') %}
{% set marray = mstring.split(",") %}
{% set fname = marray[0].replace('f_name=', '') %}
{% set lname = marray[1].replace('l_name=','') %}
{% set source = marray[2].replace('source=','') %}
{% set contact = marray[3].replace('contact=','') %}
<p>{{fname}}</p>
<p>{{lname}}</p>
<p>{{source}}</p>
<p>{{contact}}</p>
{% endfor %}
{% endfor %}
The results:
user
name
facebook
email

how can I add a django array element into a js array using an if condition

I have a Django project with data being submitted by form , I am trying to use chart.js to display the data. I need to check whether an array exists() if so then add an item to 'labels' array in 'mycharts.js' . Heres what I have so far
django views.py
ing1 = request.POST.getlist('ingredients1')
ing2 = request.POST.getlist('ingredients2')
ing3 = request.POST.getlist('ingredients3')
( I've passed the above into my context )
mycharts.js
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {chart.js
labels: ['{{ing1.0}}', '{{ing2.0}}', {% if ing3|length > 1 %} '{{ing3.0}}', {% endif %}],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
(etc...)
if I take out the if statement inside of 'labels' array , then it shows the 'ing1' and 'ing2' headings , but I can't get it to work with this if statement , whats the correct way of doing it.
I put 'ing1, 'ing2' and 'ing3' into a list called 'title' inside my views , then put that list into the context , then did the following inside the chart.js script :
{% for item in title %} '{{ item }}', {% endfor %}
now it adds the correct data to the labels array.

Sending .py -> .html value to .js (Django, Mapbox)

Below is my code in my main.html file:
<body>
<h1>mappymappy</h1>
<div id='map'></div>
<script>
mapboxgl.accessToken = '{{ mapbox_access_token }}'
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-73.9911, 40.7051],
zoom: 9.5
})
</script>
{% for center in drop_in_centers %}
<script>
new mapboxgl.Marker({ "color": 'red' })
.setLngLat([{{ center.longitude }}, {{ center.latitude }}])
.setPopup(new mapboxgl.Popup({ offset: 25 })
.setHTML("<h2>Drop-in Center</h2><h3>{{center.center_name}}</h3>"))
.addTo(map)
</script>
{% endfor %}
I want to move the scripts to a separate .js file.
However, in order to do that I have to figure out a way to
send the values mapbox_access_token and drop_in_centers to .js file
and make the values able to be used in the .js file.
How can I do this?
+) both mapbox_access_token and drop_in_centers are from views.py file.
Option 1) define vars in the template, pass them to js
views.py:
def my_view_function(request):
# define variables:
map_box_token = 'the_token'
drop_in_centers = 'the_drop_ins'
# pack context:
context = {
'map_box_token' : map_box_token,
'drop_in_centers' : drop_in_centers,
}
return render(request, 'template.html', context)
template.html:
<body>
...
<script>
var map_box_token='{{map_box_token}}';
var drop_in_centers='{{drop_in_centers}}';
</script>
<!-- include script.js after vars are defined -->
<script src="{% static 'script.js' %}"></script>
</body>
script.js:
console.log(map_box_token) // ex: use as needed
console.log(drop_in_centers) // ex: use as needed
Option 2) use ajax to retrieve data from views.py
views.py:
def my_view_function(request):
# define variables:
map_box_token = 'the_token'
drop_in_centers = 'the_drop_ins'
# pack context:
context = json.dumps({
'map_box_token' : map_box_token,
'drop_in_centers' : drop_in_centers,
})
return HttpResponse(context)
script.js:
function get_vars() {
// conduct ajax request:
$.ajax({
url : 'the_url',
success : get_vars_success, // reference to function below:
})
} $(document).ready(get_vars) // or call as needed
function get_vars_success(response) {
// unpack context:
var map_box_token = response.map_box_token;
var drop_in_centers = response.drop_in_centers;
// use as needed:
...
}

Generate multiple line charts in Django with ChartJS

i'm working in Django, to draw some graph in function of my modules. ie: if i have 2 modules, i want 2 charts , if 8 modules, 8 charts.
Modules are integreted in a plugin. so i can list all modules found in a plugin. i did this in Django:
def plugin_graph(request, hub_uid, plugin_uid):
request.session['is_admin'] = True
hub = Hub.objects.get(mac=hub_uid)
fields = []
if request.method == 'GET':
if 'field' in request.GET:
fields.append(request.GET['field'])
plugin = Plugin.objects.get(uid=plugin_uid, hub=Hub.objects.get(mac=hub_uid))
#on recupere lensemble desmodules de ce plug
modules = plugin.get_modules_list()
#pour chak module, tracer son graph
for m in modules:
modules_list = {'uid':m.uid,
'name':m.name,
'version':m.version,
'type':m.type,
'time':m.last_time(),
'rssi':m.rssi(),
'status_icon':m.status_icon()}
module = Module.objects.get(uid=m.uid, plugin=Plugin.objects.get(uid=plugin_uid, hub=Hub.objects.get(mac=hub_uid)))
historic = sorted(ModuleDocument.objects.filter(module=module), key=getKey)
values = get_graph_values(historic=historic, dates=None, fields=fields)
print values
field = None if len(fields) < 1 else fields[0]
return render(request, "admin/graph2.html",
{
'values': values,
'hub': hub_uid,
'plugin': plugin_uid,
'uid': m.uid,
'module': module,
'fields': module.get_number_fields(),
'field': field,
'level': 'module',
}
)
After recovering all my modules i draw the charts like that in javascript:
<script>
var ctx = document.querySelector("#chart");
var data = JSON.parse('{{ values }}'.replace(/"/g, '"'));
var labels = [];
var values = [];
var beginAtZero = true;
for (obj in data) {
labels.push(data[obj].x);
values.push(data[obj].y);
if (data[obj].y < 0) {
beginAtZero = false;
}
}
var lineChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: "{{field}}",
data: values,
borderColor: '#97168F'
}]
},
options: {
scales: {
xAxes: [{
time: {
unit: 'day'
}
}],
yAxes: [{
ticks: {
beginAtZero:beginAtZero
}
}]
}
}
});
</script>
My problem is just one chart is printed. i would like to put it in a for loop to recuperate all data & labels of each module to draw normally all charts i want.
Thank u for your help
You need to utilise the forloop.counter method in the django template to dynamically name a number of items, otherwise the charts will just get overwritten each time and you are just left with the last chart. Its worth noting that I include this code in the block content not a specific js block.
In the example below, the items that are dynamically named are;
The container div
<div id = 'emg-{{forloop.counter}}'>
The canvas
<canvas id="myChart-{{forloop.counter}}">
The chart JS function name
var func_name = "container-{{forloop.counter}}";
func_name = new Chart(
document.getElementById('myChart-{{forloop.counter}}'),{
type: 'scatter',
I've included the full code below. I appreciate my example is different from your posted code, but it demonstrates the concept of dynamically creating certain elements.
{% for time, name_list, value_list, latitude_list, longitude_list, polyline_list in data %}
{% with forloop.counter as track_object_counter %}
<div id = 'emg-{{forloop.counter}}'>
{% for item in emg_data %}
{% if item.loop_id == track_object_counter %}
<div id = "emg-plot" style="height:15rem; padding-top: 1rem;">
<canvas id="myChart-{{forloop.counter}}">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
var y_data = {{item.data|strip_apostrophe}}
var x_data = '{{item.name}}'
var func_name = "container-{{forloop.counter}}";
func_name = new Chart(
document.getElementById('myChart-{{forloop.counter}}'),{
type: 'scatter',
data: {
datasets: [{
showLine: true,
label: x_data,
data: y_data,
backgroundColor: 'rgba(141,49,123,0.7)',
borderWidth: 2,
borderColor: 'rgba(141,49,123,0.7)'
}],
},
});
</script>
</canvas>
</div>
{% endif %}
{% endfor %}
</div>
{% endwith %}
{% endfor %}

how to use symfony controller variables in frontend js?

Say I have a controller like this:
public function showAction(Request $request, $id, $context = array())
{
$url = $this->getPlayUrl($id, $context);
//some code here}
I want to use the variable $url in a frontend js file like this :
var html = '<iframe src=\''+ url +'\' name=\'viewerIframe\' id=\'viewerIframe\' width=\'100%\'allowfullscreen webkitallowfullscreen height=\'100%\' style=\'border:0px\'></iframe>';
How am I supposed to make this happen? For the code above ,it gave me 'undefined url' error.
Thank you.
Another option would be to have your template call a controller action (so you can pass parameters as required), for example, like this example for using highchart.js:
{% block javascripts %}
{{ parent() }}
<script src="/js/highcharts.js"></script>
<script src="/js/exporting.js"></script>
<script type="text/javascript">
{{ render(controller('AppBundle:Default:script')) }}
</script>
{% endblock %}
In the controller it looks like this:
public function scriptAction() {
$reports = $this->get('app.reports');
$chart = $reports->getDistsFYToDate();
return $this->render('Default/script.js.twig', array(
'chart' => $chart,
));
}
and script.js.twig looks like this:
$(document).ready(function () {
var options = {
chart: {
type: 'line'
},
title: {
text: 'Distributions, FY{{ chart.fy }} to date'
},
xAxis: {
categories: [{% for category in chart.categories %}{{category|raw}}{%endfor%}]
},
yAxis: {
title: {
text: 'Distributions'
}
},
series: {{ chart.series|raw }}
};
$('#linechart').highcharts(options);
})
Maybe it's better if you use HTML5 data attributes: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes
In you view add some script tags and assign a javascript vraible to the twig variable. Don't forget to quote the twig (if required).
Firstly, I would ensure that the $url always had a value;
return $this->render('MyWebBundle:Player:show.html.twig', array(
'file' => $file,
'url' => (empty($url)) ? '' : $url,
'context' => $context,
'player' => $player,
'agentInWhiteList' => $agentInWhiteList
));
Something like;
<script>
var jsVar = '{{ url }}';
var html = false;
if (jsVar.length > 0) {
html = '<iframe src=\''+ jsVar +'\' name=\'viewerIframe\' id=\'viewerIframe\' width=\'100%\'allowfullscreen webkitallowfullscreen height=\'100%\' style=\'border:0px\'></iframe>';
}
// test html !== false before using it
</script>

Categories

Resources