How to access a Django many-to-many model, from Javascript? - javascript

Given a Django template variable with a many-to-many model, is it possible to pass that to a Javascript function, and access it?
(What I'm trying to get, is a list of the groups, including pk, that the current user belongs to).
For example, if I have a user jsmith that belongs to two groups, alpha and beta:
<html>
<script type="text/javascript">
mangle_data("{{ user.name }}", "{{ user.groups }}", "{{ user.groups.all }"");
</script>
</html>
function mangle_data(username, groups, all) {
alert("username = " + username); // works. output = "jsmith"
alert("user.groups = " + groups); // output = "django.db.models.fields.related.ManyRelatedManager object"
alert("all = " + all); // output = "[Group alpha; Group beta;]"
}
In all cases, the parameter passed to Javascript, is a single flattened string. Ideally, I'd get an object, or even a list that contained both group names, and group pk.
Granted, I could find the pk of a group, given its name - but that's a lot more steps. If I can get the data from the Django template directly into Javascript, it would be much cleaner.

What about serializing user.groups in a context variable?
If you serialize these to JSON, you can easily retrieve parse it from your page's JS.

How I wound up solving this, was to use a Context Processor to format the data, and pass it to a template variable:
context_processors.py
def site_settings(request):
if request.user.is_authenticated():
user_groups = "+".join(['{"id":%s, "name":"%s"}' %
(grp['id'], grp['name']) for grp in rquest.user.groups.values()])
else:
user_groups = ''
return {'USER_GROUPS': user_groups, }
template.html
<html>
<script type="text/javascript">
mangle_data("{{ USER_GROUPS|safe }"");
</script>
</html>
handle_data.js
function mangle_data(groups) {
var groups_json = '[' + groups.split('+').join(',') + ']';
var groups_OBJ = JSON.parse(groups_json); // this is now a Javascript object.
}

Related

get variable from python into js

I'm creating an app that shows a webpage search according to a random word that is chosen by the program. I uploaded a dictionary into python to get a random word and now I want to put this word into the src= in my javascript code. What I need is some kind of placeholder that connects the 2 languages
Python
if request.method == 'GET':
#create an empty dictionary
d = {}
key = 0
#open dictionary file and store it in 'dic'
with open('dictionaries/nouns.rtf',encoding="utf8", errors='ignore') as dic:
#read every line and give it a number
for line in dic:
value = line.replace('\\', '')
key += 1
d[key] = value
#select a random number in the range of the dictionary (and store it in a variable)
rand = random.randrange(1, len(d) + 1)
#get the word with that number (and store it in a variable)
word = d[rand]
#print(word)
return render_template('/player.html', word = word)
Javascript
<script>
let is = document.getElementById('innerSpace');
query = encodeURI({{word}})
is.src = `https://www.bing.com/images/search?q=weirdest+${query}&form=QBLH&sp=-1&pq=cats&sc=8-4&qs=n&cvid=20659354CDFD49C6B03ED29A4F35EC64&first=1&tsc=ImageBasicHover`
</script>
To get the randomly generated word from Python to Javascript, you need to return a JSON response from your view.
from django.http import JsonResponse
if request.method == 'GET':
...
data = { 'word': word}
return JsonResponse(data)
You can then access the word within JavaScript using AJAX or Fetch. I will use Jquery as an example.
let is = document.getElementById('innerSpace');
$.ajax({
url: '/URL_for_your_view/',
action: 'GET',
// when the server returns data, the success method is run
success: function (data) {
query = encodeURI({{data.word}})
is.src = `https://www.bing.com/images/search?q=weirdest+${query}&form=QBLH&sp=-1&pq=cats&sc=8-4&qs=n&cvid=20659354CDFD49C6B03ED29A4F35EC64&first=1&tsc=ImageBasicHover`
}})
Now, the problem with this solution is that the view will no longer return the template player.html which seems essential in your code.
return render_template('/player.html', word = word)
To my knowledge, you cannot return a JSON response and a template in the same view. It's impossible.
So you need to use JavaScript to recreate the player.html code inside the success method and append it to the DOM.

resolving a javascript and database table logic situation

When I query a database table, I get back values "yes" or "no" for records that represent whether an item is present or not (the item is the column name). I want to create a string that represents the products that are available by name (rather than what I am doing now "kitchen table =" + kitchenTable;
I am thinking this can be solved (poorly) by a series of if statements setting variables to either the product name or to "" and then include all variables in the string
var kt;
if (kitchenTable == yes) kt = "kitchen table";
else kt = "";
if (kitchenCabinet == yes) kc = "kitchen cabinet";
else ka = "";
output = kt + ', ' + kc;
There are about 50 items that can be presented to the user, is there a more efficient way of accomplishing this task?? One option is to change how values are entered into the datbase table such that instead of yes, its the item name but this seems like a poorer way to resolve the issue
Of course you don't give all the details about how do you make query so that is an imaginary mockup of a function simulating query
var available = [];
var result = query("kitchen table");
result === "yes" && ( available.push("kitchen table") );
......
var output = available.join();
What you want is actually built into javascript itself.
I would say using an object literal will really simply your life in this situation by organizing your code and turning it into a more readable format.
I would also recommend turning your server data into true and false as this is a standardized way to communicated a Boolean and allows for the method below to work as it does:
// From server response
var results = {
kitchenCabinet: true,
kitchenTable: true
}
// Use this for your storage of all related items
var kitchenProps = {
kitchenCabinet: 'kitchen cabinet',
kitchenTable: 'kitchen table'
}
// Reuse this function for each time your need a new category (masterBathroomProps...)
function getItemDataIfExists(results, hashTable){
'use strict';
var output = 'Your total is: ';
for (var item in results) {
if (!results.hasOwnProperty(item)) return;
if (results[item]) output += 'A '+hashTable[item]+' ';
}
return output;
}
getItemDataIfExists(results, kitchenProps);
Explanation:
You loop through a result set of an object containing keys names and true false values. In the loop, if the keyname's value is true, then use that keyname to access the properties (in this case a string of your choice. The "key" here is that the key names in each object must line up.
Here is a live demo:
http://codepen.io/nicholasabrams/pen/JXXbYz?editors=0010

Infinite recursion issue with Json object (using Java/Javascript)

I'm using Javascript/Java to query an MSSQL database, and then use the CachedRowSet received from the query to add some information to a Json object. Here's the code that's querying the database and adding the results to the object.
var sqlGetVariables = "SELECT MappingVariable.Id as Id, MappingVariable.Name AS Name, MappingVariable.Value AS Value FROM MappingGroup LEFT JOIN MappingVariable ON MappingGroup.Id = MappingVariable.MappingGroupId WHERE MappingGroup.Id = " + mappingGroupId + " AND MappingVariable.Id IS NOT NULL";
var resultVariables = uberfaceDB.executeCachedQuery(sqlGetVariables);
while (resultVariables.next()) {
var variableId = resultVariables.getObject("Id");
var variableName = resultVariables.getObject("Name");
var variableMapping = resultVariables.getObject("Value");
jsonArray["Segments"][seg]["Variables"][variableName] = {};
jsonArray["Segments"][seg]["Variables"][variableName]["Mapping"] = variableMapping;
}
The issue I'm having is that there's something goofy going on with the last line where I assign "variableMapping" to the Json object. The line of code executes just fine, but when I go to iterate through the Json object later, I get stuck in an infinite recursion that keeps cycling through "class" "package" and "specificationversion".
Here's the code I'm using to iterate through the object.
function echoJson (jsonArray, strStuff) {
var strJson = "" + strStuff;
for (var item in jsonArray) {
logger.error(strJson + " --> " + item);
echoJson(jsonArray[item], strJson + " --> " + item);
}
}
The logger.error function is built in to the application I'm coding in (called Mirth Connect). It simply outputs the message to a console for error/debugging purposes. Here's an example of what I would EXPECT to get with the echoJson function:
Segments --> MSH --> Segments --> PID --> Variables --> PatientFirstName --> Mapping --> variableMappingValue
But here's what I'm actually getting:
Segments --> MSH --> Segments --> PID --> Variables --> PatientFirstName --> Mapping --> class --> package --> specificationVersion --> class --> package --> specificationVersion --> class --> package --> specificationVersion...
It continues repeating the "class --> package --> specificationVersion" portion infinitely until I stop the application.
If I replace the following line of code:
jsonArray["Segments"][seg]["Variables"][variableName]["Mapping"] = variableMapping;
With a hard coded string, like
jsonArray["Segments"][seg]["Variables"][variableName]["Mapping"] = "test";
Then it works without any problems.
Thanks in advance for taking a look at this!!
Your function echoJson is calling itself. This is called recursion. From here, "the first thing when calling a function recursively is that you need to make sure that there is some form of exit condition where the function will not call itself recursively." It appears that your function does not have an exit condition. In other words, before calling echoJson inside echoJson, check first if you ought to.
function echoJson (jsonArray, strStuff) {
var strJson = "" + strStuff;
for (var item in jsonArray) {
logger.error(strJson + " --> " + item);
if (isGoodAndNice(jsonArray[item]))
echoJson(jsonArray[item], strJson + " --> " + item);
}
}
I found the solution, as explained on another programmer's blog.
There was an issue with the data type being stored in the CachedRowSet. I don't know the exact data type, but from what I gathered the "variableMapping" variable is a byte array, and I'm needing to add it to my Json object as a string. I had to do "new String(variableMapping)" to convert the array into a string, and that fixed my problem.
How I found the problem: I decided to try using JSON.stringify() to output my Json object, and received the following error:
Java class "[B" has no public instance field or method named "toJSON"
Googling that led me to the blog post I linked to above.

extract single variable from JSON array

I hope my question is not as stupid as I think it is...
I want to extract (the value of) a single variable from an JSONarray. I have this jquery code
$(document).ready(function(){
$("#gb_form").submit(function(e){
e.preventDefault();
$.post("guestbook1.php",$("#gb_form").serialize(),function(data){
if(data !== false) {
var entry = data;
$('.entries').prepend(entry);
}
});
});
});
the content of data looks like this ("MyMessage" and "MyName" are values written in a simple form from user):
[{"message":"MyMessage","name":"MyName"}]
the var "entry" should give (more or less) following output at the end:
"Send from -MyName- : -MyMessage-"
I'm not able to extract the single array values from data. I tried things like that:
var message = data['message'];
var name = data['name']
var entry = "Send from" + name + ":" +message;
but that gives "Send from undefined: undefined"
Hope you can help me with that.
you can do like this to get first item of array:
var msg = "Send from"+data[0].name + " "+data[0].message;
console.log(msg );
SAMPLE FIDDLE
UPDATE:
as you are using $.post you will need to explicitly parse response as json:
$.post("guestbook1.php",$("#gb_form").serialize(),function(data){
var response = jQuery.parseJSON(data);
var msg = "Send from"+response [0].name + " "+response [0].message;
console.log(msg );
});
To access an array you use the [] notation
To access an object you use the . notation
So in case of [{JSON_OBJECT}, {JSON_OBJECT}]
if we have the above array of JSON objects in a variable called data, you will first need to access a particular Json Object in the array:
data[0] // First JSON Object in array
data[1] // Second JSON Object in array.. and so on
Then to access the properties of the JSON Object we need to do it like so:
data[0].name // Will return the value of the `name` property from the first JSON Object inside the data array
data[1].name // Will return the value of the `name` property from the second JSON Object inside the data array

covert large array of objects into smaller array objects using javascript

I have an list of values like this from a sql database.
UserName Email ComputerName DateIssued
jjsmith jjsmith#example.com JTComputer 9/14/2013
ltjoseph ltjoseph#example.com LTComputer1 10/21/2013
KTsmith KevinTem#example.com KTComputer1 01/25/2012
ltjoseph ltjoseph#example.com LTComputer2 01/11/2013
KTsmith KevinTem#example.com KTComputer2 01/25/2012
I transform my list into an array of objects.
var user_array = [
{"username":"jjsmith", "email":"jjsmith#example.com", "computerName":"JTComputer", "dateissued":"10/21/2013"}
{"username":"ltjoseph", "email":"ltjoseph#example.com", "computerName":"LTComputer1", "dateissued":"10/21/2013"}
{"username":"KTsmith", "email":"KevinTem#example.com", "computerName":"KTComputer1", "dateissued":"01/25/2012"}
{"username":"ltjoseph", "email":"ltjoseph#example.com", "computerName":"LTComputer2", "dateissued":"01/11/2013"}
{"username":"KTsmith", "email":"KevinTem#example.com", "computerName":"KTComputer2", "dateissued":"01/25/2012"}]
A function has been created by someone else that sends emails to users, it only accepts two parameters which are strings.
So I don't want to send more than 1 email per user. So I am trying to figure out how to combine the items together so that my an example set of strings look like this.
var str1 = "ltjoseph#example.com";
var str2 = "ltjoseph, LTComputer1-10/21/2013, LTComputer2-01/11/2013";
and then fire the other user function to send emails for each of the items in the list.
function sendEmails(str1, str2);
If anyone has any ideas how i can do this. Please advise..
var by_user = {};
for (var i = 0; i < user_array.length; i++) {
if (by_user[user_array[i].username]) {
// Found user, add another computer
by_user[user_array[i].username].str2 += ', ' + user_array[i].computerName + '-' + user_array[i].dateissued;
} else {
// First entry for user, create initial object
by_user[user_array[i].username] = {
str1: user_array[i].email,
str2: user_array[i].username + ', ' + user_array[i].computerName + '-' + user_array[i].dateissued
};
}
}
Now you have the by_user object, which has a single sub-object for each user, whose str1 and str2 properties are the variables you want.
by_user['ltjoseph'].str1 => ltjoseph#example.com
by_user['ltjoseph'].str2 => ltjoseph, LTComputer1-10/21/2013, LTComputer2-01/11/2013
something like this:
var str1=array[0].email
var str2=array[0].username+", "+array[0].computerName+array[0].dateissued
or use a loop and iterate through the array
I strongly recommend bringing in a library like lodash for this sort of thing and using uniq (sample here: http://jsfiddle.net/MwYtU/):
var uniqs = lodash(user_array).pluck('email').uniq().value();
If you're doing javascript and aren't acquainted with lodash or underscore, go do that because it'll save you a lot of time. Using tried and true code is a good idea. Added bonus: if you want to see how the pros are doing something like uniq you can just look at the source code.

Categories

Resources