Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
162 lines (124 sloc) 5.57 KB
# this app.py file is like server.js in the express unit
# from flask import Flask is like like: const express = require('express')
# jsonify lets us send JSON HTTP responses
from flask import Flask, jsonify, g
# g lets us use global variables for the life of (i.e. in the context of) this
# particular execution of this app (similar to app.locals)
# get a package that will let us handle CORS
# https://flask-cors.readthedocs.io/en/latest/
from flask_cors import CORS
# login manager is the main tool for cooardinating session/login stuff in our app
from flask_login import LoginManager
from resources.dogs import dogs # import blueprint from ./resources/dogs
from resources.users import users
# in python you import a file and you get everything in the "global scope"
# of that file
# so this statement imports all variables and methods from that file as
# properties on the models object (e.g. models.initialize() is available here)
# note we did not explicitly export anything in models.py
# google "namespacing in python"
import models
DEBUG = True # print nice helpful error messages since we're in development
PORT = 8000
# this is like const app = express()
# instantiating the Flask class
app = Flask(__name__)
# according to this - https://flask-login.readthedocs.io/en/latest/#configuring-your-application
# you need to import and config login manager
# 1. we need to setup a secret key
app.secret_key = 'AlsakdlkaskdlaskVery:sld. asklkSecrets;lda;lsaWoah'
# 2. instantiate to get a login_manager
login_manager = LoginManager()
# 3. actually connect app with lom
login_manager.init_app(app)
# in reg and login we did login_user(user that was found or created)
# that puts the ID of the user in session
# to use the user object whose is that is, you must define a cb
# for user_loader (part of login manger) tou use
# https://flask-login.readthedocs.io/en/latest/#how-it-works
@login_manager.user_loader
def load_user(user_id):
try:
return models.User.get(models.User.id == user_id)
except models.DoesNotExist:
return None
# CORS = Cross Origin Resource Sharing
# a web domain is an "origin"
# This app is localhost:8000, that's an origin
# our React app is localhost:3000, that's different origin
# Browsers implement CORS to prevent a JS app from sending requests to
# origins other than the one the browser originally went to to get the JS
# (i.e. say som JS tries to send data to some nefarious 3rd party)
# configuring CORS lets browser say "here's who I'm expecting to hear from"
# (certain origins)
# first arg -- we add cors to blueprints
# second arg -- list of allowed origins
# third arg -- lets us accept requests with cookies attached, this allows us
# to use sessions for authentication
CORS(dogs, origins=['http://localhost:3000'], supports_credentials=True)
CORS(users, origins=['http://localhost:3000'], supports_credentials=True)
# we are using blueprints tio make "controllers"
# "use this blueprint (component/piece/section of the app) to handle dogs stuff"
# analogous to app.use('/dogs', dogController)
# the point of the api v no is to let you build an upgraded API with
# a different url prefix, and let your old API remain intact so that you don't
# break a bunch of apps already built on top of your old API with the old URLS
app.register_blueprint(dogs, url_prefix='/api/v1/dogs')
app.register_blueprint(users, url_prefix='/api/v1/users')
# we don't want to hog up the SQL connection pool
# so we should connect to the DB before every request
# and close the db connection after every request
@app.before_request # use this decorator to cause a function to run before reqs
def before_request():
"""Connect to the db before each request"""
# store the database as a global var in g
g.db = models.DATABASE
g.db.connect()
@app.after_request # use this decorator to cause a function to run after reqs
def after_request(response):
"""Close the db connetion after each request"""
g.db.close()
return response # go ahead and send response back to client
# (in our case this will be some JSON)
# here's how you write a route in flask
# note the default URL ends in /
@app.route('/') # @ symbol here means this is a decorator
def index():
return 'Hello, world!'
# it's finicky about types -- e.g. you can't return a list
# check the error message at this route
@app.route('/test')
def test_list():
return ['hello', 'there']
# let's use the jsonify module to try to send the list as json
@app.route('/test_json')
def test_json():
# we are using jsonify to create a JSON response
# this is analogous to res.json() in express
return jsonify(['hello', 'there'])
@app.route('/cat_json')
def get_cat_json():
# you can pass key value pairs into jsonify()
return jsonify(name="Nico", age=15)
# you can use a dictionary as the value of one of the
# key-value pairs in jsonify()
@app.route('/nested_json')
def get_nested_json():
nico = {
'name': 'Nico',
'age': 15
}
return jsonify(name="Reuben", age=41, cat=nico)
# URL parameters in flask look like this
# username is the URL param below like :username in express
@app.route('/say_hello/<username>')
def say_hello(username): # this func takes URL param as arg
return "Hello {}".format(username)
# this is like app.listen() in express -- at the bottom
# __name__ being '__main__' here means that we just ran this file
# as opposed to exporting it and inmporting it somewhere else
if __name__ == '__main__':
# when we start the app set up our tables (if necessary) as defined in models.py
# remember in express we required db.js before app.listen
models.initialize()
app.run(debug=DEBUG, port=PORT)