I have desktop application which creates SqLite DB.
I would like to use that data to make reports on a local static web page.
However I'm not sure how to go about connecting to an existing DB - I understand there are security issues with this.
is this possible with JavaScript ? and how would i go about this ?
One option is to pass the data from the templates like so:
def index(request):
# Calculate your precious data here, for example using the django.core.serializers class:
data = serializers.serialize('json', FooModel.objects.all())
return render(request, 'templates/index.html', {'data': data})
Then in your templates/index.html you could do something like this:
<script>
window.data = {{data|default:"{}"|safe}};
</script>
Check out the safe filter.
This way, you get all your data from backend to frontend with your initial request without creating any additional requests, or communicating with your DB directly with JS.
Another option is using fetch:
You could create a view (you could use Django REST framework but that's up to what you're trying to use it for, the main idea remains the same anyway):
from django.http import HttpResponseNotAllowed, JsonResponse
from django.core import serializers
from .models import FooModel # for example
def myview(request):
if request.method != "POST":
return HttpResponseNotAllowed(['POST'], "Only POST is allowed to this URL.")
# Get your precious data, let's use the same example as before:
data = serializers.serialize('json', FooModel.objects.all())
return JsonResponse(data)
Register it in your urls.py:
urlpatterns = [
...
path('api/retrievepreciousdata', views.myview),
...
]
And then we can use fetch to retrieve it:
fetch("/api/retrievepreciousdata", {
method: "POST",
headers: {
//For CSRF protection:
//I use `js-cookie` to get the cookies, it's up to you really
"X-CSRFToken": Cookies.get("csrftoken"),
"X-Requested-With": "XMLHttpRequest",
},
}).then(response => {
if(!response.ok) {
console.log("Dang it, the response isn't OK... Response code is", response.status);
}
return response.json()
}).then(json => {
console.log("I did it! My precious data is:", json);
}).catch(e => {
console.log("Dang it, something went wrong while retrieving my precious data:", e);
});
If you are looking for a way to read data from SQLlite Db from a static webpage I suggest you read the following thread Is it possible to access an SQLite database from JavaScript?
Try this also SQL.js (its mention in the above thread)
Related
I have a POST API view that accepts an image and a style sting and returns a styled image.
It works on postman just fine but I cannot get it to work using fetch API.
Serializer:
class GetImageSerializer(serializers.Serializer):
image = serializers.ImageField()
style = serializers.CharField()
DRF view:
class PostImage(APIView):
serializer_class = GetImageSerializer
parser_classes = [MultiPartParser]
def post(self, request, format=None):
print(request.data) # Debug
img = request.data.get('image')
# Process
response = FileResponse(img)
return response
The fetch call:
json = {}
json["image"] = this.state.image
json["style"] = "models\\wave\\wave200.pth"
console.log("sending --- ", json) //debug
fetch('/style_transfer/style/',
{
headers: { "Content-type": "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" },
body: json,
method: "POST"
}
).then(response => {
if (!response.ok) {
console.log("couldn't fetch image")
}
return response.json()
})
.then(data => {
console.log("fetched data")
console.log(data)
outputs of console logs. This shows that the correct data is in json dictionary
But the data isn't received by DRF server.
The print(request.data) from the view returns <QueryDict: {}>.
The strange part is that the same code works with postman.
Things I've tried:
Remove the headers from fetch request - This throws unsupported media type error
Set content-type to "application/json" - This reads the string parameter but image key is empty. this is what request.data looks like {'image': {}, 'style': 'models\\wave\\wave200.pth'}
I want to understand what's causing this issue. I've read several similar threads but I couldn't find the recommended way to do something like this. So, what's the issue and what is the recommended way of doing this?
I've being developing a solution for my webpage with Django and javascript, it's a record button so that the user can send feedback and I can store it into the server.
The plan is putting a text input where the user can introduce its name and a file is created with that name. This is my code by now. Can anyone help me with this?
Python views.py
def voice_request(request):
f = open('./Grabaciones/file.wav', 'wb')
f.write(request.body)
f.close()
return HttpResponse('audio received')
Javascript part
function sendData(data) {
let csrftoken = getCookie('csrftoken');
let response=fetch("/salud/voice_request/", {
method: "post",
body: data,
headers: { "X-CSRFToken": csrftoken },
})
}
Welcome at SO.
You have to offer some text input form to the user in order to enable him to send some context. On the backend site, you would then push the data to the database using a Django model which is basically the toolbox for handling data in Django.
Kindly refer to the docu to get a deep dive into it:
https://docs.djangoproject.com/en/3.0/topics/forms/
I am building a web app with Django/Python and trying to send data to a controller via a POST request using the Axios library (within Vue.js code).
The POST QueryDict seems to be empty and I can't see why that is happening:
changeCountry: function(e, id){
console.log("Let's change the country")
console.log(e.target.value) // is printing correctly
console.log(id) // also printing correctly
axios({
method: 'post',
url: '/template/country',
data: {
id: id,
country: e.target.value
},
headers: {
'X-CSRFToken': "{{csrf_token}}"
}
})
.then(function (response) {
alert(response.data); // this is returning what I expect
})
.catch(function (error) {
console.log(error);
})
},
The Python method looks like this:
def update_template_country(request):
pprint(request.POST) # prints an empty QueryDict
id = request.POST.get('id')
country = request.POST.get('country')
print(id, country) #prints None None
return HttpResponse("The country is changed") # this is being returned back to the client
The console.log messages at the top print what I expect and since there is no error I am assuming the CSRF header token is fine. Have I missed something obvious or misunderstood how this is working?
EDIT: looking at the Chrome Network tab, it seems the data is being 'POSTed' correctly:
It shows this:
{"id":"593ff2270098e6e8d3292b60","country":"US"}
and that's what I expect, so I suspect the issue is with Django. But I can't see what that might be.
Write your python POST request like this:
def update_template_country(request):
data = json.loads(request.body)
id = data["id"]
country = data["country"]
'''Any other function you want to perform'''
return HttpResponse(json.dumps({'message':'The country is changed'},status=200)
Basically the problem is with the format of POST request, Django is not able to parse it properly that's why when you print the POST request it return an empty dictionary.
I'm developing a Flask server to communicate between some backend Python functionality and Javascript clients over the web. I'm attempting to utilize Flask's session variable to store user specific data over the course of their time interacting with the app. I've removed most of the application specific code below but the core problem I'm experiencing remains.
Here is my the code for my (simplified) Flask app:
import json
import os
from flask import Flask, jsonify, request, session
app = Flask(__name__)
app.secret_key = 'my_secret_key'
#app.route('/', methods=['GET'])
def run():
session['hello'] = 'world'
return jsonify(session['hello'])
#app.route('/update', methods=['POST'])
def update():
return jsonify(session['hello'])
if __name__ == '__main__':
app.run(host='0.0.0.0')
Utilizing Postman, I can make a GET request to my server and receive the expected output of "world". I can then make a POST request with an arbitrary body and receive the same expected output of "world" (again using Postman).
When using Chrome, I can visit my server IP and see the expected output "world" on the page. I can also manually make a GET request using Javascript (in Chrome's console) and receive the same response as expected. However, my problem arises when trying to send a POST request to the server using Javascript; the server shows a KeyError: 'hello' when trying to make this request.
Here is the Javascript I'm using to make the POST request:
var url = 'http://my_server_ip/update';
fetch(url, {
method: 'POST',
body: JSON.stringify('arbitrary_string'),
headers: new Headers({
'Content-Type': 'application/json'
})
})
.then(response => response.json())
.then((data) => {
console.log(data);
})
What's going wrong here? Why can I make the GET/POST requests with Postman just fine but run into errors making the same requests with Javascript?
The caveats section of the fetch documentation says:
By default, fetch won't send or receive any cookies from the server, resulting in unauthenticated requests if the site relies on maintaining a user session.
It is recommended to use AJAX to exchange information with Flask views.
Meanwhile, in your code for the Flask app, the session object is a dictionary. Now, if you access a dictionary with its key session['hello'] and if this key does not exist, a Keyerror is raised. To get around this error, you can use the get() method for dictionaries.
What is happening is: the fetch request does not find the hello key(or GET the session value from the Flask view) in the Flask session.
user = session.get('hello')
return jsonify(session_info=user)
But this will still give you a null value for the session { session_info: null }. Why is that so?
When you send GET/POST requests to the Flask server, the session is initialized and queried from within Flask. However, when you send a Javascript fetch POST request, you must first GET the session value from Flask and then send it as a POST request to your Flask view which returns the session information.
In your code, when the POST request is triggered from fetch, when I send the payload data to Flask, it is received correctly and you check this using request.get_json() in the Flask view:
#app.route('/update', methods=['POST'])
def update():
user = session.get('hello')
payload = request.get_json()
return jsonify(session_info=user, payload=payload)
This will return { payload: 'arbitrary_string', session_info: null }. This also shows that fetch does not receive the session information because we did not call GET first to get the session information from Flask.
Remember: The Flask session lives on the Flask server. To send/receive information through Javascript you must make individual calls unless there is a provision to store session cookies.
const fetch = require('node-fetch');
var url_get = 'http://my_server_ip';
var url_post = 'http://my_server_ip/update';
fetch(url_get, {
method:'GET'
}).then((response)=>response.json()).then((data) =>fetch(url_post, {
method: 'POST',
body: JSON.stringify(data),
dataType:'json',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then((postdata) => {
console.log(postdata);
}));
The Flask views will change slightly:
#app.route('/', methods=['GET'])
def set_session():
session['hello'] = 'world'
return jsonify(session['hello'])
#app.route('/update', methods=['POST'])
def update():
payload = request.get_json()
return jsonify(session_info=payload)
When you trigger the Javacript request now, the output will be: { session_info: 'world' }
After a few hours of testing, I managed to figure out the issue. Although I think #amanb's answer highlights the problem, I'm going to answer my own question because what I found is ultimately a simpler solution.
In order to make the POST request return the expected value, I simply needed to add a credentials: 'same-origin' line to the fetch body. This looks like the following:
var url = 'http://my_server_ip/update';
fetch(url, {
method: 'POST',
body: JSON.stringify('arbitrary_string'),
credentials: 'same-origin', // this line has been added
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then((data) => {
console.log(data);
})
According to Mozilla's Fetch usage guide,
By default, fetch won't send or receive any cookies from the server,
resulting in unauthenticated requests if the site relies on
maintaining a user session.
So it seems I looked over this. Changing the credentials to allow communication of the cookie/session between client and server resolved the issue.
I've got a web front-end for a flask app that is doing some heavy calculations on the back-end before passing the calculated data via JSON to the front-end to get charted.
The issue is, the calculation takes several minutes, and ideally I want the front-end to know the % done and status of the request rather than sitting there quietly.
JS Ajax request front-end:
function runBacktest() {
$.ajax({
type: "POST",
url: '/backtest',
data: {
run_partial: 1,
use_saved_model: false,
saved_model_file: 'model.h5'
},
dataType: "json",
success: function(data) {
//Successful data
},
error: function () {
alert('There was a problem contacting the server.');
}
});
}
Python backend:
#webapp.route('/backtest', methods=['POST'])
def backtest():
print('> Running Backtest...')
"""Calculation code goes on here"""
print('Percent Completed: \r{0:.1f}%'.format(round(pct_done,1)), end='')
"""Serialise each agent instance into a dictionary and put in list to be converted to JSON object"""
agents_serialised = [agent.__dict__ for agent in bt_engine.agents]
return json.dumps(agents_serialised)
Question is, how can I pass something like the percentage done, which I'm printing on stdout, on every change of percentage, to the front end? Followed by then passing the json data once it's finished?
A more Flasky approach would be to pass a generator to the response. From what I've read, this is the preferred approach to streaming data with Flask. Here's a very abstract example. Look here for my answer to different question where I have a more fleshed out and tested script using a generator in a response.
def do_calcs():
while(more_calculations):
"""do your calculations and figure out the percentage."""
agents_serialized = [agent.__dict__ for agent in bt_engine.agents]
yield json.dumps({percent: percent, agents: agents_serialized})
And in your route:
return Response(do_calcs(), mimetype='text/json')
For updating the percentage kind of stuff we need socket connection between Front end and Back end .Flask have a great package do this which is socket.io. And there is javascript support also for the socket.io.
Blog post which help to build this
I am sure you can build with this, because i done it before.
Sample Python code:
from flask import Flask, render_template
from flask.ext.socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
#app.route('/')
def index():
return render_template('index.html')
#socketio.on('my percentage event', namespace='/test')
def test_message(message):
#create pertage opertion here
emit('percentage status', {'data': message['data']}, broadcast=True)
Sample javascript code:
$(document).ready(function(){
var socket = io.connect('http://' + document.domain + ':' + location.port + '/test');
socket.on('percentage status', function(msg) {
//portion for update the percentage
});
});
These code are not exactly, But you can use as reference.