How can I get the template and Python to communicate in Flask? - python

For example, if I have the following code in index.html:
<div id='1'></div>
<div id='2'></div>
<div id='3'></div>
And, I have the following code in Python:
from flask import *
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
So, among the three div blocks. When I click on any one of them. I want the program to know which one I click on, and pass the value of id (1,2,3) into the data variable in python so that I can use it on "expert.html".
What are some good ways I can achieve it? Thank you in advanced!

Instead of divs, you can use buttons. That way, ajax can be utilized in the front end to retrieve the id of the button clicked and pass it to the backend:
"index.html":
<html>
<body>
<button id='1'>Button1</button>
<button id='2'>Button2</button>
<button id='3'>Button3</button>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('button').click(function(event) {
var the_id = event.target.id;
$.ajax({
url: "/get_id",
type: "get",
data: {the_id: the_id},
success: function(response) {
window.location.replace('/experts');
},
error: function(xhr) {
//Do Something to handle error
}
});
});
</script>
</html>
Then, a route to receive the id can be created, the results from the ajax can be stored in flask.session, and a "success" object can be passed back to the ajax in the index.html template. From the jquery in the template, the app can be redirected to /expert:
import flask
app = flask.Flask(__name__)
app.secret_key = 'SOME_SECRET_KEY'
#app.route('/get_id')
def expert():
button_id = flask.request.args.get('the_id')
flask.session['button_id'] = button_id
return flask.jsonify({'success':True})
#app.route('/experts', methods=['GET'])
def experts():
return render_template("experts.html", data=flask.session['button_id'])

Related

How to post JSON data to FastAPI backend without using Swagger UI?

I am trying to do a simple POST operation using FastAPI. I have created a basic structure using BaseModel, which has only two attributes, namely name and roll.
import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
roll: int
app = FastAPI()
#app.post("/")
async def create_item(item: Item):
return item
if __name__ == '__main__':
uvicorn.run(app, port=8080, host='0.0.0.0')
I would like to post these data using this POST operation -
{"name":"XYZ", "roll":51}.
I know about the automatic documentation at http://localhost:8080/docs provided by Swagger UI (OpenAPI), which we can use to post data. But I wouldn't want to use it. What I would like is to directly post the data using the URL http://localhost:8080/ and would like to see the result in the browser itself, instead of seeing the result in Swaggger UI.
You would need to use a Javascript interface/library such as Fetch API, which allows you to send data in JSON format (example is given below). For submiting Form data instead, have a look at this answer, while for posting both Files and Form/JSON data, have a look at this answer.
For the frontend, you could use Jinja2Templates to render and return a TemplateResponse that includes your HTML/JS code, etc. You can use an HTML form to submit your data and then have the form-data converted into JSON, as described here. Otherwise, you could post your JSON data directly, as shown hereā€”for example, body: JSON.stringify({name: "foo", roll: 1}).
app.py
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
app = FastAPI()
templates = Jinja2Templates(directory="templates")
class Item(BaseModel):
name: str
roll: int
#app.post("/")
async def create_item(item: Item):
return item
#app.get("/")
async def index(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
templates/index.html
<!DOCTYPE html>
<html>
<body>
<h1>Post JSON Data</h1>
<form method="post" id="myForm">
name : <input type="text" name="name" value="foo">
roll : <input type="number" name="roll" value="1">
<input type="button" value="Submit" onclick="submitForm()">
</form>
<div id="responseArea"></div>
<script>
function submitForm() {
var formElement = document.getElementById('myForm');
var data = new FormData(formElement);
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(Object.fromEntries(data))
})
.then(resp => resp.text()) // or, resp.json(), etc.
.then(data => {
document.getElementById("responseArea").innerHTML = data;
})
.catch(error => {
console.error(error);
});
}
</script>
</body>
</html>

How do I make changes in a particular React component from a Flask server?

I hope my question is clear enough.
So, I have a React form in component A. I want to pass the fields using an AJAX request to a Flask server, which processes the data received and updates the DOM in component B.
Tried looking up several other SO pages but none of them answered the question. And I'm super new to both AJAX and Flask, so that doesn't help either.
My current code looks like this:
Component A:
import React from "react";
class InputForm extends React.Component {
claimRef = React.createRef();
handleSubmit = event => {
event.preventDefault();
const claim = this.claimRef.current.value;
this.props.addClaim(claim);
$.ajax({
type: "POST",
url: "/test/",
data: claim
})
.done(function(data) {
// self.clearForm();
})
.fail(function(jqXhr) {
console.log("failed to register");
});
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Claim:
<textarea name="claim" ref={this.claimRef} placeholder="Claim" />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
export default InputForm;
Flask server:
#!/usr/bin/env python
import os
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route("/")
def index():
return render_template('index.html')
#app.route('/test/', methods=['GET', 'POST'])
def test():
clicked = None
if request.method == "POST":
clicked = request
return render_template('test.html', clicked=clicked)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=os.environ.get('PORT', 3000), debug=True)
I've added a test.html file temporarily, which is supposed to simply print the data, but even localhost:3000/test just prints "None".
I get absolutely no errors in any part of the application, and I also get status 200 in the network tab of the webpage, which means that the data is being accepted.
How do I access the passed data and subsequently, print it in component B?
There is nothing wrong with your reactjs http post, however I would recommend you to use the fetch api. However, when you want to talk to the client from your server you have to use json.
Here is how you would make an http request to the server try this:
const data = this.claimRef.current.value;
fetch('/test/', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data), // body data type must match "Content-Type" header
})
.then(response => response.json())
.then(data => console.log(data));
Once you create make the http post to the server, this is how you retrieve the data from the server (flask)
#app.route('/test/', methods=['GET', 'POST'])
def test():
clicked = None
if request.method == "POST":
data = request.json
print(data) #json data from client (reactjs)
return jsonify(data='test')
# jsonify returns http response as json
Try it and see what you get! I hope this helps and good luck!
Be aware of CORS
fetch api
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

In Flask, how can I redirect to a profile being clicked?

I am very new to Flask. I have a mysql database and a template. Let's say I have 3 images
<div><img src= pathOfImage id="profile1"/></div>
<div><img src= pathOfImage id="profile2"/></div>
<div><img src= pathOfImage id="profile3"/></div>
The id of each image (profile1,profile2,profile3) is the primary key of the some tables in the database. What I want to do is to find the values of the corresponding attributes of that tuple by using the primary key. Then, load that those values to the template from the tuples.
And, I have the following code in Python:
from flask import *
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
The snippet of HTML code I gave above is in expert.html. I almost of SQL query that was not listed above, data on the second parameter in render_template in route1() is the SQL tuple, which generate all these images and the ID.
I have tried to put a button next to the images, and give id to the button instead. Then, pass the id to the python script as a variable using Ajax, and get the SQL tuple.
However, this isn't the hard part. The hard part is making the new route and loading the content. I have tried make a new route using "app.route" and pass the data into the second parameter of render_template. But, it didn't redirect to a new profile, and the method was called before I even click on the profile.
previously, I used button to retrieve the id:
<html>
<body>
<button id='1'>Button1</button>
<button id='2'>Button2</button>
<button id='3'>Button3</button>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"</script>
<script>
$(document).ready(function() {
$('button').click(function(event) {
var the_id = event.target.id;
$.ajax({
url: "/get_id",
type: "get",
data: {the_id: the_id},
success: function(response) {
},
error: function(xhr) {
}
});
})});
</script>
and, I used these to generate a new template:
import flask
from flask import *
from flaskext.mysql import MySQL
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
#app.route('/get_id')
#app.route('/profile')
def route2():
button_id '"' + flask.request.args.get('the_id') + '"'
//some code here to get the tuples that I need "client_info" and
//"skill_info" variable below
return render_template("profile.html", client_info=client_info,
skill_info=skill_info)
Hope someone would give a fresh start. Thanks in advance!
Instead of passing info by ajax you can pass it through the route url.
experts.html
<div><img src="pathOfImage"></div>
<div><img src="pathOfImage"></div>
<div><img src="pathOfImage"></div>
flask routes
import flask
from flask import *
from flaskext.mysql import MySQL
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
#app.route('/profile/<id>')
def route2(id):
# id variable contains user profile id string as per user click
# depending on id set variables client_info and skill_info and render
return render_template("profile.html", client_info=client_info, skill_info=skill_info)
{% for profile in profiles %}
<img src="{{profile.img}}">
{% endfor %}
...I guess? maybe?

Django AJAX search function

I'm trying to make a search function in my Django project using AJAX. But the functions in views.py don't seem to work properly. And maybe I have some other mistakes. Could you please tell me what I need to correct?
This is my AJAX file:
$(document).ready( function(){
$('#suggestion').keyup(function(){
var query;
query = $(this).val();
$.get('/friends_plans/suggest_users/', {suggestion: query}, function(data){
$('#user').html(data);
});
});
});
This is part of my template:
<div>
<ul class="nav nav-list">
<li class="nav-header">Find user</li>
<form>
<li><input class="search-query span10" type="text" name="suggestion" value=" " id="suggestion" /></li>
</form>
</ul>
</div>
<div id="user">
</div>
These ara functions from views.py:
def suggest_users(request):
users_list = []
starts_with = ''
if request.method == 'GET':
starts_with = request.GET['suggestion']
users_list = get_users_list(5, starts_with)
return render(request, 'friends_plans/list.html', {'users_list': users_list})
def get_users_list(max_results=0, starts_with=''):
users_list = []
if starts_with:
users_list = Person.objects.filter(username__istartswith=starts_with)
if max_results > 0:
if len(users_list) > 0:
users_list = users_list[:max_results]
return users_list
This is from urls.py:
url(r'^suggest_users/$', views.suggest_users, name='suggest_users')
The istartswith method doesn't work properly with the variable but does with the constant, I can't understand why. And suggest_users function doesn't return users_list to the object with id user ($('#user').html(data)), nothing appears on the page. But maybe there are some other mistakes.
Django's render function renders HTML after parsing it with Jinja. If you want to write a view that acts as an endpoint for an AJAX function, you do not want that view to return render.
Instead you should use return JsonResponse. JsonResponse accepts a dictionary as an argument. And it builds a proper JSON object for you. :) Which will then be picked up by your AJAX's success function.
Here's an example of how to use JsonResponse:
from django.http import JsonResponse
def some_endpoint(request, *args, **kwargs):
data = dict()
data["foo"] = "bar"
data["username"] = User.objects.get(id=request["id"]).username
return JsonResponse(data)
This will cause your view to return a JSON Object, which is what your AJAX function is looking for.
Second suggestion I would make would be to use jQuery's $.ajax() function rather than jQuery's shortcut .get() function. The advantage of this would be learning all the parameters that go along with AJAX calls.
Here's an example of jQuery's $.ajax() function.
$(document).ready( function(){
$('#suggestion').keyup(function(){
var query = $(this).val();
$.ajax(function(){
type: "GET",
url: "/friends_plans/suggest_users/",
data: {suggestion: query},
success: function(data){
console.log("SUCCESS");
console.log(data);
},
failure: function(data){
console.log("FAIL");
console.log(data);
},
});
});
});

Issues with ajax in django

I'm using ajax in django first times .. I read some tutorials on the net and I'm trying to make a simple form which posts some information via ajax.
Here is my html form
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
function send_request()
{
$.ajax({
type:"POST",
url:"/ajaxredirect/",
});
}
</script>
<button type="button" onclick="send_request();">change content</button>
and it is my view
def Ajaxquery(request):
if request.is_ajax():
return HttpResponse("ok")
else:
return HttpResponse("error")
it does nothing when i am click on change content button in browser.
Any suggestions would be apperciated
Here is basic request/response setup I have made use of. I got the JSONResponse and AjaxResponse mixins from the Django Braces Module. I also made sure to include the following Django CSRF fix to prevent my AJAX request from being treated as a cross site request forgery.
JQuery:
<script type="text/javascript">
function send_request() {
$.ajax({
type: 'POST',
url: '/ajaxredirect/',
data: $('#your_form').serialize(),
crossDomain: false,
success: function(ctx) { console.log(ctx); },
});
}
</script>
Views.py
from django.views.generic import View
from braces.views import JSONResponseMixin, AjaxResponseMixin
class AjaxResponseView(JSONResponseMixin, AjaxResponseMixin, View):
def post_ajax(self, request, *args, **kwargs):
data = request.POST.items() # form data
ctx = {'hi': 'hello'}
return self.render_json_response(ctx)

Categories

Resources