I need the config variables in javascript in my flask application. Currently, I access the config variables via:
#app.route('/api/getconfigs/')
def get_config_variable():
return config['VARIABLENAME']
Is this the only way to get the flask config in javascript? What would be the best practice to do this?
If you need the value as part of an API call, then yes, sending the value from an endpoint is correct. If you're rendering templates, then you can render the values in the JavaScript sent to the client.
Flask injects its config into the template context. Within a template, config['key'] or config.key will access any value in the config. Since you're rendering it as JavaScript, use the tojson filter to render valid values.
var debug = {{ config['DEBUG']|tojson }};
You could load the specific variable into your jinja2 globals like so:
app.jinja_env.globals.update(VARIABLENAME=config['VARIABLENAME'])
Then in an always included base-template load the variable into your javascript like so.
<script>
var config = {};
config.VARIABLENAME = {{VARIABLENAME}};
</script>
Or just throw the whole config into your jinja2 env like so:
app.jinja_env.globals.update(config=app.config)
And then insert the specific Variable only if it is found in config.
{% if config['VARIABLENAME'] %}
<script>
var config = {};
config.VARIABLENAME = {{config['VARIABLENAME']}};
</script>
{% endif %}
Related
If I have custom filters and write {% load file_name %} into index.html, How to write:
<script>
const x = 10;
const y = "{{ obj|function:x }}";
</script>
This isn't possible, because the expression {{ obj|function:x }} is parsed by Django on the server before the javascript is run by the browser, so Django can't access the javascript variable x. You can verify this yourself by looking at the page's HTML response in your browser's network tab
-- you will see that any template expression enclosed in {{ }} is replaced by whatever value it resolves to.
If you need to use a javascript variable in Django, an alternative could be to send the variable's value to a Django view on your server and run the function there. Then you can do any computation involving that value on the server and return the appropriate response to the browser to be displayed.
I have a Django template filter to retrieve dictionary items based on the key passed.
{% with data=dict_data|get_data:key %}
I have separately made a template_tag.py file which returns those items.
def get_domain_data(dictionary, key):
p = ast.literal_eval(dictionary)
return p[key]
# data being returned successfully
The issue is in passing the dynamic value of the key in the filter function.
<script>
var key_val = $('#input_id').val();
'{% with data=dict_data|get_domain_data:"'+key_val+'" %}'; //encountering error here
// rest of the code
'{% endwith %}';
</script>
If I hardcode a string value the entire operation works, but I am unable to use the JavaScript variable within the Django {% filter %} function.
As mentionned by Matt Ellen in a comment, the template code is executed on the server, then the generated result is sent to the browser which interprets the javascript parts - so this just can not work this way.
If your data dict is small enough and doesn't depend on javascipt user interactions (ie the javascript only reads it), then the solution is to serialize it to json (in the view itself or using a template filter - one might already exists FWIW), bind it to a javascript variable (in the template) and then let the javascript code use it as just any js object, ie (assuming a "jsonify" template filter):
<script>
var data_dict = {% data_dict|jsonify %};
function do_something() {
var key_val = $('#input_id').val();
var data = data_dict[key_val];
// rest of the code
}
// and you'll probably want to bind do_something to
// some js event handler
</script>
There is a similar issue at Get javascript variable's value in Django url template tag
Providing arg1 can be numeric and the reversed url doesn't contain other instances of the string /12345/ then you can use,
var url_mask = "{% url 'someview' arg1=12345 %}".replace(/12345/, tmp.toString());
I know that the Jinja2 library allows me to pass datastore models from my python code to html and access this data from inside the html code as shown in this example . However Jinja2 isn't compatible with javascript and I want to access the data inside my Javascript code . What is the simplest templating library which allows to iterate over my datastore entities in Javascript ? I've heard about things like Mustache and Jquery , I think they look a bit too complicated. Is there anything simpler?
You should create a python controller which serves JSON formatted data, which any Javascript library (especially jQuery) can consume from. Then, setup the Jinja2 template to contain some Javascript which calls, loads and displays said data.
One more approach to consider: If the Python object is not dynamic, you may want to use json.dumps() to store it as a TextProperty, and simply JSON.parse(unescape(model_text)) on the JS side. Reduces the overhead, and memory hit which can be important when trying to stay within an F1 limit. For example, I run an instance that very easily runs inside an F1. There is one large dictionary object that we deliver. Were this object to exist as a Python dictionary inside the instance we would kill the instance due to the soft memory limit. Using the TextProperty approach we can pass this large dict to the client without any issues. (Note: we did have to momentarily boost our instance up to an F4 when initially creating this object -- something incredibly easy inside the Admin web page.) With more dynamic objects, answers above apply.
Jinja2 and Javascript play fine together. You need to arrange to have template expansion emit your Python data structures into a JS-friendly form.
https://sites.google.com/a/khanacademy.org/forge/technical/autoescape-in-jinja2-templates covers it fairly well. (Note the use of the escapejs filter.)
It works. I had to serialize(convert) my datastore entities to json format, which Javascript understands well. I created a function which converts every instance of my datastore into a dictionnary then encapsulates all these instances into a list which is then converted to Json using json.dumps. When I pass this result to the Java script , I can then easily access my values as seen below.
import json
import webapp2
from google.appengine.ext import db
import jinja2
JINJA_ENVIRONMENT = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
extensions=['jinja2.ext.autoescape'],
autoescape=True)
# serialize datastore model to JSON format
def serialize(model):
allInstances = model.all() # fetching every instance of model
itemsList = [] #initial empty list
for p in allInstances:
d = db.to_dict(p)
itemsList.append(d)
return json.dumps(itemsList)
class myModel(db.Model):
v = db.FloatProperty()
c = db.FloatProperty()
tdate = db.DateTimeProperty(auto_now_add=True)
class MainPage(webapp2.RequestHandler):
def get(self):
myModel(v=4.5, c=3.0).put()
#creating template variables
template_values = {
'json_data': serialize(myModel)
}
template = JINJA_ENVIRONMENT.get_template('index.html')
self.response.write(template.render(template_values))
Inside my 'index.html' file, I have:
{% autoescape true %}
<!DOCTYPE html>
<html>
<head>
<title> webpage </title>
<script type="text/javascript">
// I retrieve my data here
var results = "{{ json_data }}";
for(var i = 0; i < db_results.length; i++) {
document.write("myModel instance:" + i + results[i] + "<br>");
}
</script>
</head>
<body>
</body>
</html>
{% endautoescape %}
It has nothing to do with compatibility. Jinja is server side templating. You can use javascript for client side coding.
Using Jinja you can create HTML, which can be accessed by javascript like normal HTML.
To send datastore entities to your client you can use Jinja to pass a Python list or use a json webservice.
In django, I can render a html template from a view action like this:
return render_to_response('video_handle/view.html', {'filename': filename, \
'frame_count': frame_count, 'folder': folder})
This would render the "view.html" template and would give me access to the variables filename, frame_count and folder inside the template, so doing this works perfectly:
<script type="text/javascript">
file_name = '{{filename}}'
frame_count = '{{frame_count}}'
folder = '{{folder}}'
</script>
Now, when i try the same in a coffescrip file, compile the file to javascript and load it to my view.html template, the values of python's variables are not assigned to javascript variables and instead, these variables keep the string value meaning that form example file_name variable keeps the value of this string '{{filename}}' instead of the actual value of the python's variable called filename.
Any idea on what's happening and how to solve it?
If I understand your question right, then what is happening is that CoffeeScript files aren't being processed (only your template is being processed and therefore being passed the variables).
If you absolutely need to pass data from backend to frontend in such a fashion you can just use what you have, JavaScript variables will be accessible to you, so if you load your JavaScript below this <script> tag, you will have access to file_name, frame_count etc.
I'd suggest putting this data in an object, in order to not pollute global namespace with these variables:
<script>
var options = {
fileName : '{{file_name}}',
frameCount : '{{frame_count}}'
// more options here
};
</script>
And then you can use them with dot notation (also in CoffeeScript):
alert options.fileName # should alert the file name
I'm working on an app that uses Django and jQuery for various things. I'm trying to assemble an AJAX request with jQuery that requires that I use Django's {% url %} template function. One of the arguments needed for the url call is stored in a JavaScript variable. Is it possible to insert the value of the JS var into the {% url %} tag? Something like
var jsvar = somestuff;
{% url some.view arg1=jsvar %}
No. Pass a sentinel (e.g. %s) to url which you replace in JavaScript with the actual value.