Can I invoke controller outside Flask server startup? - python

I'm attempting to create a simple model view controller pattern using Python and Flask. I add a new controller but it appears the routes are not being invoked.
server.py:
if __name__ == '__main__':
TicTacToeController()
app.run(host='0.0.0.0', port=80)
This class is defined in a new file:
class TicTacToeController :
#app.route('/ttt')
def ttt(self):
return render_template('home-tic-tac-toe.html')
Error when try to visit route '/ttt':
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
Defining #app.route('/ttt') in server.py the route '/' is accessible. How to add the controller mappings in a new class that is separate to the main server class ( server.py ) ?

All your functions with #app.route need to be defined before calling app.run. Once you call app.run that line will run forever as it's now serving requests. Put it at the bottom.
You also don't need to put your routes inside classes. Just def ttt(): at the global level.

Related

Bottle mysql connect

I am trying connect to mysql in bottle framework but with no success. Error tells me to give second argument to route but I do not want additional argument in url.
import bottle
import bottle_mysql
from bottle import route, run, template, app
app = bottle.Bottle()
plugin = bottle_mysql.Plugin(dbuser='root', dbpass='toor', dbname='database')
app.install(plugin)
#route('/show/<a>')
def show(a, db):
db.execute('SELECT * FROM table WHERE a > "%d"', (a,))
return template('Hello {{name}}, how are you?', name=a)
run(host='192.168.1.19', port=8080, debug=True)
Error:
TypeError('show() takes exactly 2 arguments (1 given)',)
You may want to create db as a global variable and remove it as a parameter for the function show() or possibly make it an optional variable
The author of bottle-mysql says :
to automatically detect routes that need a database connection,
the plugin searches for route callbacks that require a db keyword
argument (configurable) and skips routes that do not.
Each route needs to be configured as belonging to the app or the app's plugin can't send data via that route.
So you do need the "app." in #app.route('/show/<a>')
And your run statement on the last line needs to specify the app too otherwise it won't recognise the routes belonging to the app.
run(app, host='192.168.1.19', port=8080, debug=True)
As others have responded, you need to change:
#route('/show/<a>')
to:
#app.route('/show/<a>')
But this is not the only change you need to make to solve the issue, you also need to change:
run(host='192.168.1.19', port=8080, debug=True)
to:
app.run(host='192.168.1.19', port=8080, debug=True)
Unfortunately this last part is not clear in the documentation and took a bit of guess work to figure out, but it's actually pretty obvious actually because if you just call run without the app. prefix, you're basically running a new bottle instance, which will result in 404 errors tying to access your routes.

Cloud9: Running a python server

In my Cloud9 IDE, which is running on Ubuntu I have encountered a problem in trying to reach my Python server externally. It's because their projects use a non-standard naming structure:
https://preview.c9users.io/{user}/{project}/
Changing the address to something like this, which is the default server address, doesn't help:
https://preview.c9users.io:8080/{user}/{project}/
I'm looking for a solution so I can run the following script or for a way to be able to combine HTML+JS+Python on Cloud9. The purpose of the server should be to respond to AJAX calls.
The Cloud9 server is Ubuntu-based, so there may be other ways to address this problem than just my script below.
import web
def make_text(string):
return string
urls = ('/', 'tutorial')
render = web.template.render('templates/')
app = web.application(urls, globals())
my_form = web.form.Form(
web.form.Textbox('', class_='textfield', id='textfield'),
)
class tutorial:
def GET(self):
form = my_form()
return render.tutorial(form, "Your text goes here.")
def POST(self):
form = my_form()
form.validates()
s = form.value['textfield']
return make_text(s)
if __name__ == '__main__':
app.run()
The server above actually runs and is available through URL in special format. It has been changed since earlier version, so I couldn't find it at first:
http://{workspacename}-{username}.c9users.io
Now I prefer to run it as a service (daemon) in the console window to execute additional scripts in the backend and test frontend functionality.

When is flask's app.before_first_request called when behind apache?

I have some code decorated with #app.before_first_request
In my testing environment when debug is set to true and I run the flask web server by calling python my_flask_server.py the functions decorated with before_first_request do not get called until I actually make a request with the browser.
However when I use Apache and mod_wsgi to serve the flask app, it appears that when I call from my_server import app as application the decorated functions get executed.
This is a problem because my wsgi script looks like this:
import my_server
from my_server import app as application
my_server.configure_stuff() # read from a conf file
application.run(host='0.0.0.0', port=5000, debug=False)
Now I need the configure_stuff() function to execute and to set attributes on the app object. However because #app.before_request decorated functions are run immediately after from my_server import app as application, I get "no attribute errors."
Anyone know how to prevent flask form executing running these decorated functions until a real request has come in?

Combining resources in Python with Flask

I' trying to combine two independent Flask apps like the example below:
from geventwebsocket import WebSocketServer, Resource
...
server = WebSocketServer(('', 8080), Resource({
'/': frontend,
'/one': flask_app_one,
'/two': flask_app_two}))
server.serve_forever()
Inside each Flask app I declare the full path, isn't that suppose to be relative path, inside flask_app_one:
from flask import Flask
app = Flask(__name__)
#app.route('/one/ping')
def ping():
return 'hello\n'
Why I should specify in #app.route('/one/ping') instead of just #app.route('/ping') since all traffic to /one will be forwarded to the corresponding app?
Let me know if you need any additional info I kept my example clean
Thank you
Finally I have managed to do it with the so called Application Dispatching and the resources found in this page:
http://flask.pocoo.org/docs/0.10/patterns/appdispatch/#app-dispatch
Thanks

Changing URLs after deploying Flask app

So, I have a flask application that works well when it's not deployed. Imagine it has pages for /index/ and /home/ and /home/field/. Now that I have deployed the app using Apache and mod_wsgi, it needs to have a prefix for every URL.
Now, it should look like /newapp/index/ and /newapp/home/ and /newapp/home/field/.
So, I changed all of the URLs to include the new /newapp/ prefix, but the only URL that works with it is the original /index/ URL. All of the others return a
Not Found The requested URL was not found on the server.
in the browser when I click for that URL. I definitely handle that route in my main.py, so I don't know why it would not be found.
Anyone know what is going on?
EDIT: adding some code
Basically I changed all my code in main.py from:
Original:
#app.route('/')
#app.route('/index/', methods=['GET', 'POST'])
def index():
#Stuff
#app.route('/home/')
def farms():
#More stuff
#app.route('/home/<selector>')
def fields(selector):
#Further stuff
To....
New Code
#app.route('/newapp/')
#app.route('/newapp/index/', methods=['GET', 'POST'])
def index():
#Stuff
#app.route('/newapp/home/')
def farms():
#More stuff
#app.route('/newapp/home/<selector>')
def fields(selector):
#Further stuff
I did this because the domain I am using already has another Flask app, so I had to differentiate between the two. Also, I expect there to be more flask apps in the future, so this newapp will end up being an identifier for any given flask app.
I changed main.py as well has all of my hrefs in my templates. So, the hrefs went from
href=/index/
to
href=/newapp/index/
And, I get the error that I posted above whenever I try to click on a link
Further info:
So, checking out the apache error logs one error says, File does not exist: /var/www/flask_util.js, because in my main.py I call from flask_util_js import FlaskUtilJs. I'm not sure if this has anything to do with the URL routing, but it might
You don't need to add the prefix in your code.
Say you have code like
#app.route('/hi', methods = ['GET','POST'])
def myIndex():
return "Hello World!", 200
And you set your alias like to deploy it to www.myserver.com/app/
WSGIScriptAlias /app /var/www/myDir/myApp/app.wsgi
the server should automatically map www.myserver.com/app/hi to /hi in your application.
However if you set the mapping to
#app.route('/newapp/hi', methods = ['GET','POST'])
def myIndex():
return "Hello World!", 200
You WSGI app would only receive the call for /hi (server strips away the prefix) so it would find no matching Path and return not found.

Categories