Pass Python Requests (in Django views.py) Json Data to Javascript - javascript

I have this python code, which fetches json and parses it:
from django.http import HttpResponse
import json, requests
def find(request):
context = {}
platformUrl = 'https://www.igdb.com/api/v1/platforms'
platformReq = requests.get(platformUrl, headers={'Authorization': 'Token token="1234"'})
platformData = json.loads(platformReq.text)
platformList = platformData['platforms']
print platformList
It outputs this with the print statement:
[{u'slug': u'saturn', u'id': 32, u'name': u'Sega Saturn'}, {u'slug': u'mac', u'id': 14, u'name': u'Mac'}, {u'slug': u'vc', u'id': 47, u'name': u'Virtual Console (Nintendo)'}
I would like to pass that data to javascript and have the ID and name from the json put in this javascript. (selectize.js) This would probably require some type of for loop, could be javascript, or even djangos?:
options: [
{id: 1, title: 'Spectrometer'},
{id: 2, title: 'Star Chart'},
{id: 3, title: 'Electrical Tape'}
]
Thanks
EDIT:
Following #satoru's link, I looked into it, and updated my code to this:
from django.http import HttpResponse
import json, requests
def find(request):
context = {}
platformUrl = 'https://www.igdb.com/api/v1/platforms'
platformReq = requests.get(platformUrl, headers={'Authorization': 'Token token="1234"'})
platformList = json.dumps(platformData)
print platformList
return render_to_response('find.html',{'platformList':platformList})
It now outputs this:
{"platforms": [{"slug": "saturn", "id": 32, "name": "Sega Saturn"}, {"slug": "mac", "id": 14, "name": "Mac"}, {"slug": "vc", "id": 47, "name": "Virtual Console (Nintendo)"}
How would I then pass that into javascript?

If the API already return a JSON-encoded response, you can just use platformReq.text. After passing it to render_to_response, you have access to a JSON-encoded string in your template.
Now you can design your Javascript module to be configurable with an object, for example:
<script src="my_module.js"></script>
<script>
MyModule.initialize({{ json_encoded }})
</script>

Check out this template library to convert your platform list to a JSON object from within the template
Example(Inside your template):
<script src="your_standalone_js.js">
<script>
var js_variable = {{platformList | jsonify }};
function_in_standalone_js(js_variable);
</script>
your_standalone_js.js:
var function_in_standalone_js = function(js_variable){
var options = js_variable['platforms'];
//What ever you need to do with options
};

Related

convert string array object into array object - Javascript

I have a flask route where I am trying to pipe a list_object [{}] into a template. It works but the data comes out as a string on the front end. How can I convert the string back into a array_object so I can do stuff with it?
Here is the flask route:
app.py
#app.route('/vgmplayer')
def vgmplayer():
musicdata = music.query.order_by(func.random()).first()
musicimgdata = musicimages.query.filter_by(gamealbum = musicdata.gamealbum).order_by(func.random()).first()
if musicimgdata == None:
musicimgdata = "https://media.idownloadblog.com/wp-content/uploads/2018/03/Apple-Music-icon-003.jpg"
else:
musicimgdata = musicimgdata.gameart
musicobject = [{
"name": musicdata.gametrackname,
"path": musicdata.gamelink,
"img": musicimgdata,
"album": musicdata.gamealbum,
"artists": musicdata.artists,
"platform": musicdata.platform,
"year": musicdata.year,
"genre": musicdata.genre
}]
print(musicobject)
return render_template("musicplayer.html",rvgm = musicobject)
but when I get back the template:
musicplayer.html
<script type="text/javascript">
function grvgm(){
All_song = "{{ rvgm|safe }}"
return All_song
}
</script>
it comes in a string:
Example data:
All_song = grvgm()
"[{'name': '10 - M Stage Jungle B', 'path': 'https://vgmsite.com/soundtracks/zhuzhu-pets-quest-for-zhu-20…-nds-gamerip/ebulpznnyw/10%20-%20M%20Stage%20Jungle%20B.mp3', 'img': None, 'album': 'ZhuZhu Pets - Quest for Zhu', 'artists': None, 'platform': 'DS', 'year': '2011', 'genre': None}]"
I would need the list_dict to not have the qoutes at the end so that the javascript can treat it as an array.
EDIT:
I forgot to mention that I tried:
function grvgm(){
All_song = "{{ rvgm }}"
All_song = JSON.parse(All_song)
return All_song
}
SyntaxError: JSON.parse: expected property name or '}' at line 1 column 3 of the JSON data
Turns out the string was not a valid json format as #Andy pointed out. I had to use a different method. Instead of piping the list_dict into the template, I used a get request to get the list_dict into the front end so I can do stuff with it.
app.py
#app.route('/grvgm', methods=['GET'])
def grvgm():
musicdata = music.query.order_by(func.random()).first()
musicimgdata = musicimages.query.filter_by(gamealbum = musicdata.gamealbum).order_by(func.random()).first()
if musicimgdata == None:
musicimgdata = "https://media.idownloadblog.com/wp-content/uploads/2018/03/Apple-Music-icon-003.jpg"
else:
musicimgdata = musicimgdata.gameart
musicobject = [{
"name": musicdata.gametrackname,
"path": musicdata.gamelink,
"img": musicimgdata,
"album": musicdata.gamealbum,
"artists": musicdata.artists,
"platform": musicdata.platform,
"year": musicdata.year,
"genre": musicdata.genre
}]
print(musicobject)
musicobject = json.dumps(musicobject)
return musicobject
musicplayer.js
async function load_track(index_no){
fetch('/grvgm')
.then(response => response.json())
.then(All_song => {
console.log(All_song)
// stuff goes here
})
By using the JSON.parse() method, you can easily parse the string.
Example:
JSON.parse(All_song)
// returns an array

how do we send file from django to reactjs where i dont need RESTFRame work?

I am new to ReactJS,I am using a django as backend, React as frontend i need to send a dict/json to reactjs which is locally created by choices not from data base. is there a way to send Data from django to reactjs without restframe work?
you can easily convert dic to json using json.dumps() method.
import json
# Data to be written
dictionary ={
"id": "04",
"name": "sunil",
"department": "HR"
}
# Serializing json
json_object = json.dumps(dictionary, indent = 4)
You can use JsonResponse instead of ordinary HttpResponse:
from django.http import JsonResponse
def hello_dictionary(request):
data = {'name': 'Alison', 'grade': 9}
return JsonResponse(data)
def hello_list(request):
data = [{'name': 'Alison', 'grade':9}, {'name': 'Alice', 'grade': 8}, {'name': 'Tom', 'grade': 10}]
return JsonResponse(data, safe=False)
If you pass something that is not a dictionary remember to add safe=false
Reference:
https://docs.djangoproject.com/en/4.1/ref/request-response/#jsonresponse-objects

How to handle nested files with FastAPI?

I'm working on a website where the frontend is done in React and the backend in Python with FastAPI. I made a form which takes a some data and sends it to the backend with axios. It looks like this
{
name='Jonathan',
aliases=["Johnny"],
birthdate='2-15-1980',
gender='male',
height=178
weight=90
nationalities=["American", "French"],
occupations=["Programmer", "Comedian"],
status='single',
images=[
{'attachment': FileList,
'location': 'Berlin',
'date': '10-14-2019'
}
]
}
However, when I submit it, FastAPI seems to remove the images from the form.
name='Jonathan',
aliases=["Johnny"],
birthdate='2-15-1980',
gender='male',
height=178
weight=90
nationalities=["American", "French"],
occupations=["Programmer", "Comedian"],
status='single',
images=[
{'attachment': {'0': {}}, 'location': 'Berlin', 'date': '10-14-2019'}
]
This is what the route currently looks like
#router.post("/register/user")
def register_user(user_data: UserCreate):
print(user_data)
I'm not entirely sure what's going on. I'm guessing it has something to do with how the data is send and its encryption. I'm at a dead end here. Thanks in advance.
Edit: This is what the UserCreate Schema looks like
class CharacterCreate(BaseModel):
name: str
aliases: list
birthdate: Optional[str]
gender: str
height: Optional[float]
weight: Optional[float]
nationalities: Optional[set[str]]
occupations: Optional[set[str]]
status: str
images: Optional[list]
As per the documentation, you can't have both JSON and Files / form-data in the same request, as the body is encoded using multipart/form-data (when files are included) or application/x-www-form-urlencoded (if only Form data included) instead of application/json. Have a look at this answer.
Thus, one way to solve this is to use a single parameter to hold the various "metadata" and have a second one for the files/images. Using Dependency Injection you can check the received data against the Pydantic model using parse_raw method, before proceeding to the endpoint. If a ValidationError is thrown, then an HTTPException (HTTP_422_UNPROCESSABLE_ENTITY) should be raised, including the errors. Example below. Alternatively, have a look at Method 4 in this answer.
app.py
from fastapi import FastAPI, Form, File, UploadFile, status
import pydantic
from pydantic import BaseModel
from typing import Optional, List
from fastapi.exceptions import HTTPException
from fastapi.encoders import jsonable_encoder
from fastapi import Depends
app = FastAPI()
class User(BaseModel):
name: str
aliases: List[str]
height: Optional[float]
weight: Optional[float]
def checker(data: str = Form(...)):
try:
user = User.parse_raw(data)
except pydantic.ValidationError as e:
raise HTTPException(detail=jsonable_encoder(e.errors()), status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
return user
#app.post("/submit")
def submit(user: User = Depends(checker), files: List[UploadFile] = File(...)):
return {"User": user, "Uploaded Files": [file.filename for file in files]}
test.py
import requests
url = 'http://127.0.0.1:8000/submit'
files = [('files', open('test_files/a.txt', 'rb')), ('files', open('test_files/b.txt', 'rb'))]
data = {'data' : '{"name": "foo", "aliases": ["alias_1", "alias_2"], "height": 1.80, "weight": 80.5}'}
resp = requests.post(url=url, data=data, files=files)
print(resp.json())

How to access JSON property values in handlebars template

I'm creating a view in an Ember.js App and want to display some values from a JSON object. In my route's model hook, I'm calling an API endpoint that returns the JSON object which contains two arrays.
I thought I'd be able to simply reference the JSON properties in my handlebars template and it'd output the value, but that isn't working as expected. Instead, it looks like I'm getting a string description of the JSON object:
[object Object],[object Object]
How can I access the JSON object's property values in my handlebars template?
route:
var CompareRoute = Ember.Route.extend({
model: function(params) {
return $.getJSON('/api/compare_segments?' + params.ids).then(function(payload) {
return payload;
});
},
});
export default CompareRoute;
Handlebars template:
{{item_summaries}}
Example of JSON formatted returned from API endpoint (truncated):
{
"item_summaries": [
{
"item_desc": "example",
"item_id": 1,
"item_summary": [
{
"children": [
{
"measure": "% users clicking",
"value": null
}
...
{
"item_desc": "example2",
"item_id": 2,
"item_summary": [
{
"children": [
{
"children": [
...
}
you should use the each helper because you have a collection which needs to be printed out.
{{#each item_summaries}}
//access the properties of a single item_summary and write your html code
{{/each}}

Ember-Data: How do "mappings" work

I'm currently trying to put something together with ember + emberdata + router + asp.net web api. Most of it seem to work, however I stuck in an error message I get when ember-data tries to findAll through the adapter for my models.
In my backend I have a model like this (C#):
public class Genre {
[Key]
public int Id { get; set; }
[Required]
[StringLength(50, MinimumLength=3)]
public string Name { get; set; }
}
Which in my app I represent it like this using ember-data:
App.Genre = DS.Model.extend({
id: DS.attr("number"),
name: DS.attr("string")
}).reopenClass({
url: 'api/genre'
});
I have also a Store defined in my App using the RESTAdapter like so:
App.store = DS.Store.create({
revision: 4,
adapter: DS.RESTAdapter.create({
bulkCommit: false
})
});
And the store is used in my controller as below:
App.GenreController = Ember.ArrayController.extend({
content: App.store.findAll(App.Genre),
selectedGenre: null
});
The router is defined as
App.router = Em.Router.create({
enableLogging: true,
location: 'hash',
root: Ember.Route.extend({
//...
genre: Em.Route.extend({
route: '/genre',
index: Ember.Route.extend({
connectOutlets: function (router, context) {
router.get('applicationController').connectOutlet('genre');
}
})
}),
//...
})
})
When I run my application, I get the following message for every object that has this same structure:
Uncaught Error: assertion failed: Your server returned a hash with the
key 0 but you have no mappings
For reference, here's the json the service is returning:
[
{
"id": 1,
"name": "Action"
},
{
"id": 2,
"name": "Drama"
},
{
"id": 3,
"name": "Comedy"
},
{
"id": 4,
"name": "Romance"
}
]
I cannot tell exactly what the problem is and since the assertion is mentioning that I need mapping, I'd like to know:
What this mapping is and how to use it.
Since the returned json is an array, should I be using a different type of controller in my app ,or is there anything I should know about when working with this type of json in ember-data? or should I change the JsonFormatter options in the server?
Any help is welcome.
I can definitely add more information if you feel this isn't enough to understand the problem.
EDIT: I've changed a few things in my backend and now my findAll() equivalent action in the server serializes the the output as the following json:
{
"genres": [
{ "id": 1, "name": "Action" },
{ "id": 2, "name": "Drama" },
{ "id": 3, "name": "Comedy" },
{ "id": 4, "name": "Romance" }
]
}
But I still can't get it to populate my models in the client and my error message has changed to this:
Uncaught Error: assertion failed: Your server returned a hash with the
key genres but you have no mappings
Not sure what else I might be doing wrong.
The method that throws this exception is sideload and checks for the mappings like this:
sideload: function (store, type, json, root) {
var sideloadedType, mappings, loaded = {};
loaded[root] = true;
for (var prop in json) {
if (!json.hasOwnProperty(prop)) { continue; }
if (prop === root) { continue; }
sideloadedType = type.typeForAssociation(prop);
if (!sideloadedType) {
mappings = get(this, 'mappings');
Ember.assert("Your server returned a hash with the key " + prop + " but you have no mappings", !!mappings);
//...
This call sideloadedType = type.typeForAssociation(prop); returns undefined and then I get the error message. The method typeForAssociation() checks for the for 'associationsByName' key which returns an empty Ember.Map.
Still no solution for this at the moment.
By the way...
My action is now like this:
// GET api/genres
public object GetGenres() {
return new { genres = context.Genres.AsQueryable() };
}
// GET api/genres
//[Queryable]
//public IQueryable<Genre> GetGenres()
//{
// return context.Genres.AsQueryable();
//}
I had to remove the original implementation which gets serialized by json.NET as I could not find config options to produce a json output as Ember-Data expects ( as in {resource_name : [json, json,...]}). Side effect of this is that I've lost built-in OData support, but I'd like to keep it. Does anyone know how could I configure it to produce different json for a collection?
The mapping can be defined in the DS.RESTAdapter. I think you could try to define something like this:
App.Store = DS.Store.extend({
adapter: DS.RESTAdapter.create({
bulkCommit: true,
mappings: {
genres: App.Genre
},
// you can also define plurals, if there is a unregular plural
// usually, RESTAdapter simply add a 's' for plurals.
// for example at work we have to define something like this
plurals: {
business_process: 'business_processes'
//else it tries to fetch business_processs
}
}),
revision: 4
});
Hope this resolves your problem.
Update:
At this time, this is not well documented, I don't remember if we found it by ourself reading the code, or perhaps Tom Dale pointed on it.
Anyway, here is the point for plurals
For the mappings, I think we were driven by the same error as you, and either we tried, either Tom teached us about this.
The RESTAdapter expects the returned JSON to be of the form:
{
"genres": [{
"id": 1,
"name": "action"
},{
"id": 2,
"name": "Drama"
}]
}
The tests are a good source of documentation, see https://github.com/emberjs/data/blob/master/packages/ember-data/tests/unit/rest_adapter_test.js#L315-329
I'm using Ember Data rev. 11 and it seems that the plurals config in DS.RESTAdapter.create never works. I looked into the codes and found a solution as following:
App.Adapter = DS.RESTAdapter.extend({
bulkCommit: false
})
App.Adapter.configure('plurals', {
series: 'series'
})

Categories