Python Flask URL Logic for 2 different scripts and different views - python

I am new to flask(using it with nginx) and I am trying to understand the URL logic. I have 2 python scripts.... /site/myapp.py and /site/bar.py.
I have three questions, please:
If, I want to run myapp.py only and not /site/bar.py how do I add
a url rule to run it with add_url_rule?
How would I do the same if I wanted to run
/site/bar.py instead?
If I wanted to run myapp.py, and have two
different views...depending on xml.open("POST",
"/site/myapp/view1", true) and xml.open("POST",
"/site/myapp/view2", true)....how would I assign a url for the each
view in myapp.py with add_url_rule?
python script /site/myapp.py:
root#chat:/site# cat myapp.py
import flask, flask.views
app = flask.Flask(__name__)
class View1(flask.views.MethodView):
def post(self):
pass
app.add_url_rule('/site/myapp', view_func=View1.as_view('view1'))
root#chat:/site#
Javascript function:
function foo() {
var xml = new XMLHttpRequest();
xml.open("POST", "/site/myapp", true);
xml.send(form);
console.log("sent")
xml.onreadystatechange = function () {
console.log(xml.readyState);
console.log(xml.status);
if (xml.readyState == "4" && xml.status == "200"){
console.log("yes");
console.log(xml.responseText);
}
}
}
nginx config:
server {
listen 10.33.113.55;
access_log /var/log/nginx/localhost.access_log main;
error_log /var/log/nginx/localhost.error_log info;
location / {
root /var/www/dude;
}
location /site/ {
try_files $uri #uwsgi;
}
location #uwsgi {
include uwsgi_params;
uwsgi_pass 127.0.0.1:3031;
}
}

On the flask tutorial, you can find things like:
#app.route('/')
def show_entries():
cur = g.db.execute('select title, text from entries order by id desc')
entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()]
return render_template('show_entries.html', entries=entries)
That means, anyone accessing your website at http://yourdomain.tld/ will execute the show_entries function and the returned value of render_template('show_entries.html', entries=entries) will be sent to the user.
On this page, you can also find that:
#app.route('/')
def index():
pass
is equivalent to
def index():
pass
app.add_url_rule('/', 'index', index)
You need to forget about your PHP background, and think in another way. People won't access you website using URLs like http://yourdomain.com/index.py. Basically, you tell your server that flask is in charge of handling the URLs, and you map URLs to functions. Simple as that.

Related

Flask HTML/AJAX page Linking Issue

I have created a FLASK app which preforms CRUD operations on an SQL database. I had everything work a few days ago but now when using the web interface the HTML pages aren't working when clicked. For example after entering valid details and clicking login the URL now looks like:
incorrect url path
when it should redirect to
correct url path
showing in terminal
terminal
This is my folder layout
folder layout
My AJAX call to redirect to main.html
`
// Login a user
function userLogin() {
data = getLogin()
console.log(data)
$.ajax({
url:"http://127.0.0.1:5000/login",
data: JSON.stringify(data),
method:"POST",
dataType:"JSON",
contentType: "application/json; charset=utf-8",
success: function(result) {
if (result == 1) {
window.location.replace("main.html"); // Redirect to to main.html if successful
}
},
error: function(xhr, status, error){
window.alert("Invaild username and/or password");
console.log("error "+ error + " code "+ status)
}
})
}
`
Flask Server route:
`
# Homepage route
#app.route('/')
def index():
if not 'username' in session:
return app.send_static_file('index.html')
# Login
#app.route("/login", methods = ["POST"])
def login():
account = {
"username":request.json["username"],
"password":request.json["password"]
}
return jsonify(bookmarkDAO.login(account))
`
I've tried deleting the cache, changing my folder directories around and I even tried an older version which correctly worked from my github repository but now it is even throwing the same error. I am using VS Code, could it possibly be an issue with the terminal?
You are not trailing the main.html with /
Change this
window.location.replace("main.html")
to
window.location.replace("/main.html")

Weird Axios Network Error with seemingly error-free code

I am trying to use react to get data from an API (Python, I'm hosting it on the same machine).
API Code:
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route('/')
def all_data():
all_data = "Hello"
return jsonify({
'data':all_data,
'message':"success"
}), 200
if __name__ == "__main__":
app.run(debug=True)
React code(Didn't include the render()):
export default class HomeScreen extends Component {
constructor(props){
super(props);
this.state = {
listData:[],
url:"http://localhost:5000"
}
}
getPlanets=()=>{
console.log("Axios called")
const url = this.state.url;
console.log(url)
axios.get(url).then((response)=>{
console.log(response.data)
return this.setState({listData:response.data})
}).catch((error)=>{
console.log(error.message)
Alert.alert(error.message);
})
}
componentDidMount(){
this.getPlanets();
}
}
I'm always getting Network Error for the console.log(error.message).
I'm also getting a larger Error: "Network Error" in Error: Network Error << at e.exports (axios.js:3:7286) << at d.onerror (axios.js:3:6270) for console.log(error).
Simultaneously, I got two weird error messages in my API:
code 400, message Bad request version ('localhost\x00\x17\x00\x00ÿ\x01\x00\x01\x00\x00')
"▬♥☺☻☺☺ü♥♥ÆuaTÁS¾eài ¸ ²`½‼/cùCf{&*½(¨qh↓(â®z↨Ó ×D ÚÚ‼☺‼☻‼♥À+À/À,À0̨̩À‼À¶úú♫♀ l
ocalhost↨ÿ☺☺" HTTPStatus.BAD_REQUEST -
Help?
I've tried looking through a lot of websites for the problem, but they all just suggested adding the http:// prefix to my url, which I had already done. I'm also using Python for the API and not NodeJS, so I don't need to use CORS. I just couldn't find a relevant fix anywhere.

Unable to send flutter GET request to python local server

I've made a simple flutter web app with TextField() and a Text() widget. When I press the button I expect it to send a query to the simple flask app made using python where it will returns the inverted text and I display that on the Text widget.
NOTE: Inverting text is not the actual task. Its just to check if I'm
able to get the data.
Python Code:
This code works when I run on the chrome.
#performing flask imports
from flask import Flask,jsonify
from flask.globals import request
app = Flask(__name__) #intance of our flask application
#Route '/' to facilitate get request from our flutter app
#app.route("/api",methods=["GET"])
def function():
d = {}
text = str(request.args["Query"])
text = text[::-1]
d["query"] = text
return jsonify(d)
if __name__ == "__main__":
app.run()
Flutter Code:
main.dart
import 'package:flutter/material.dart';
import 'api.dart';
import 'dart:convert';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String url;
var data;
String queryText = "Query";
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("PYTHON AND FLUTTER"),
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
onChanged: (value) {
url = "http://10.0.2.2:5000/api?Query=" + value.toString();
},
decoration: InputDecoration(
hintText: "Search Anything Here",
suffixIcon: GestureDetector(
onTap: () async {
data = await getData(url);
var decodedData = jsonDecode(data);
setState(() {
queryText = decodedData["Query"];
});
},
child: Icon(Icons.search))),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
queryText,
style: TextStyle(fontSize: 30.0, fontWeight: FontWeight.bold),
),
),
],
),
),
);
}
}
api.dart
import 'package:http/http.dart' as http;
Future getData(url) async {
http.Response response = await http.get(url);
return response.body;
}
I followed the tutorial from : This Youtube Video
I'm running the python code via Command Prompt and flutter app through VScode.
I'm getting the following errors:
Error: Expected a value of type 'Uri', but got one of type 'String'
at Object.throw_ [as throw] (http://localhost:50523/dart_sdk.js:5348:11)
at Object.castError (http://localhost:50523/dart_sdk.js:5319:15)
at Object.cast [as as] (http://localhost:50523/dart_sdk.js:5635:17)
at Function.as_C [as as] (http://localhost:50523/dart_sdk.js:5263:19)
at getData (http://localhost:50523/packages/word_prediction/api.dart.lib.js:29:47)
at getData.next (<anonymous>)
at runBody (http://localhost:50523/dart_sdk.js:39211:34)
at Object._async [as async] (http://localhost:50523/dart_sdk.js:39242:7)
at Object.getData (http://localhost:50523/packages/word_prediction/api.dart.lib.js:28:18)
at main._MyAppState.new.<anonymous> (http://localhost:50523/packages/word_prediction/main.dart.lib.js:422:48)
at Generator.next (<anonymous>)
at runBody (http://localhost:50523/dart_sdk.js:39211:34)
at Object._async [as async] (http://localhost:50523/dart_sdk.js:39242:7)
at http://localhost:50523/packages/word_prediction/main.dart.lib.js:421:210
at tap.TapGestureRecognizer.new.invokeCallback (http://localhost:50523/packages/flutter/src/gestures/recognizer.dart.lib.js:203:18)
at tap.TapGestureRecognizer.new.handleTapUp (http://localhost:50523/packages/flutter/src/gestures/tap.dart.lib.js:417:40)
at tap.TapGestureRecognizer.new.[_checkUp] (http://localhost:50523/packages/flutter/src/gestures/tap.dart.lib.js:223:12)
at tap.TapGestureRecognizer.new.acceptGesture (http://localhost:50523/packages/flutter/src/gestures/tap.dart.lib.js:199:23)
at arena.GestureArenaManager.new.sweep (http://localhost:50523/packages/flutter/src/gestures/arena.dart.lib.js:222:31)
at binding$5.WidgetsFlutterBinding.new.handleEvent (http://localhost:50523/packages/flutter/src/gestures/binding.dart.lib.js:402:27)
at binding$5.WidgetsFlutterBinding.new.dispatchEvent (http://localhost:50523/packages/flutter/src/gestures/binding.dart.lib.js:381:24)
at binding$5.WidgetsFlutterBinding.new.dispatchEvent (http://localhost:50523/packages/flutter/src/rendering/layer.dart.lib.js:6107:13)
at binding$5.WidgetsFlutterBinding.new.[_handlePointerEventImmediately] (http://localhost:50523/packages/flutter/src/gestures/binding.dart.lib.js:352:14)
at binding$5.WidgetsFlutterBinding.new.handlePointerEvent (http://localhost:50523/packages/flutter/src/gestures/binding.dart.lib.js:325:43)
at binding$5.WidgetsFlutterBinding.new.[_flushPointerEventQueue] (http://localhost:50523/packages/flutter/src/gestures/binding.dart.lib.js:314:14)
at binding$5.WidgetsFlutterBinding.new.[_handlePointerDataPacket] (http://localhost:50523/packages/flutter/src/gestures/binding.dart.lib.js:304:65)
at Object.invoke1 (http://localhost:50523/dart_sdk.js:185426:7)
at _engine.EnginePlatformDispatcher.__.invokeOnPointerDataPacket (http://localhost:50523/dart_sdk.js:165747:15)
at _engine.PointerBinding.__.[_onPointerData] (http://localhost:50523/dart_sdk.js:166405:49)
at http://localhost:50523/dart_sdk.js:166863:28
at http://localhost:50523/dart_sdk.js:166816:16
at http://localhost:50523/dart_sdk.js:166509:11
I don't know what I'm doing wrong here.
Try this:
Future getData(String url) async {
var response = await http.get(Uri.parse(url));
return response.body;
}
Along this change https://stackoverflow.com/a/66517561/13592012 mentioned by Ουιλιαμ Αρκευα.
There was another problem:
When I use Break point it shows file call by blinding.dart
This was because of CORS.
Cross Origin Request(CORS) error which was because I did not set this up in my server.
This is especially if your flutter web application is not running in the same domain as the server where you api is running. Even if its on the same machine, you will have to allow the request from certain domain and ports.
This can be done by adding the following lines to flask code:
response.headers.add("Access-Control-Allow-Origin", "*")
and
response.headers.add("Access-Control-Allow-Credentials", "true")
So the updated code will be:
#performing flask imports
from flask import Flask,jsonify
from flask.globals import request
app = Flask(__name__) #intance of our flask application
#Route '/' to facilitate get request from our flutter app
#app.route("/api",methods=["GET"])
def word_predictor():
d = {}
text = str(request.args["Query"])
text = text[::-1]
d["Query"] = text
response = jsonify(d)
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add("Access-Control-Allow-Credentials", "true")
return response
if __name__ == "__main__":
app.run()
And, with these two changes, code works fine.

Exception when receiving data from Back end to Front end [duplicate]

This question already has answers here:
Configure Flask dev server to be visible across the network
(17 answers)
Closed 1 year ago.
I've created a simple flutter app which will get data from an api in json format sent from the backend (Python flask) and print out the data on click of a button.
When I click on the button, I get the error
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)]
Unhandled Exception: SocketException: OS Error: Connection refused, errno = 111, address = 127.0.0.1, port = 36820
I'm very new to flutter, please tell me where I did wrong and help me figure it out.
Flutter Dart code:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(new MaterialApp(
home: new HomePage(),
));
}
class HomePage extends StatefulWidget {
#override
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage> {
List data;
Future<String> getData() async {
var response = await http.get(
Uri.encodeFull("http://127.0.0.1:5000/ "),
headers: {
"Accept": "application/json"
}
);
data = json.decode(response.body);
print(data);
return "Success!";
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new RaisedButton(
child: new Text("Get data"),
onPressed: getData,
),
),
);
}
}
Python code:
from flask import Flask, jsonify
app = Flask(__name__)
#app.route('/')
def hello_world():
return jsonify({"about": "Hello World!"})
if __name__ == '__main__':
app.run()
Looks like you are running your back-end from localhost. In this case, 127.0.0.1 will only work if you run the application on your PC (and not another phone/device. Not sure about simulators though).
Trying to access 127.0.0.1 from a phone is like trying to access a server hosted on your phone (which evidently will not be found).
So, to run the app on your phone, you need to find your PC's (private) IP address, using e.g. ifconfig from your terminal. Once you get this IP address, use the URL {your-priv-IP}:5000 instead of 127.0.0.1:5000 in your code. Make sure though that your PC and phone are connected to the same Wifi network for this to work.

Connecting my Python backend with my Flutter Frontend using Flask

So currently I am trying to learn how to connect a flutter front end with a Python backend using flask and I am making a basic project where you basically input a number in the flutter app the number you input being the index of a list I have stored in my python app the python app will then return the number at the index you specified and it will be displayed on the screen. The issue I am having is that when I run the applications the flutter application just displays an error message. I have tried a whole bunch of things and can't figure out what is wrong
Here is the link to the screenshot of my Flutter App (Includes error message received from the server):
https://imgur.com/a/K6KYRAu
Here is my Python Code
from flask import Flask
from flask_restful import Api, Resource
app = Flask(__name__)
api = Api(app)
myList = [3,4,8,1,9,4,2,0,2,9,3,8,4,7,2,7,0,1]
#app.route('/', methods = ['GET'])
class Update(Resource):
def get(self,pos):
if(pos > len(myList)):
return {"num" : "invalid number: out of list range"}
else:
return {"num": str(myList[pos])}
api.add_resource(Update, "/Update/<int:pos>")
if __name__ == "__main__":
app.run(debug=True)
here is my Flutter Code:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Entry> fetchEntry() async {
final response =
await http.get('https://127.0.0.1:5000/Update/3');
if (response.statusCode == 200) {
return Entry.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load Entry');
}
}
class Entry {
final String number;
Entry({this.number});
factory Entry.fromJson(Map<String, dynamic> json) {
return Entry(
number: json['num'],
);
}
}
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future<Entry> futureEntry;
#override
void initState() {
super.initState();
futureEntry = fetchEntry();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Entry>(
future: futureEntry,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.number);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
),
),
);
}
}
Also I have double checked my dependencies in my pubspec.yaml file and AndroidManifest.xml file so that shouldn't be the issue. Any help would be greatly appreciated, thanks.
EDIT: for clarification I am using and android emulator for this and have tried using a different ip address for my flutter get request (I found the ip address when trying to figure out how to fix this problem and it said that ip address needs to be used for android emulators) but it still returned the same error when I did that.
Not exactly sure why this is throwing this error as you do specify the port as 5000, but a simple solution would be to change the flask port to 50162.
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=50162)
EDIT:
On further review, you might want to change your http request in the flutter code to http, not https.
I figured out the solution:
for my get request I need to be using an IP address that can be used by android the IP address that android uses is 10.0.2.2 I found this solution on this stack overflow post:
How to connect to my http://localhost web server from Android Emulator

Categories