-
Notifications
You must be signed in to change notification settings - Fork 36
Pine: Karina & Roslyn #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
67cc5df
97a7024
63c6c05
ee4a36a
05f4785
c2fbe5f
d822457
73bf728
1799c41
25d4594
d833244
80a2f72
e70a696
03499ba
fe8ee9b
2c8e489
de29dec
7f6eb66
9c87859
587834d
7a9eff0
cb47a25
fb7edff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| web: gunicorn 'app:create_app()' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,32 @@ | ||
| from flask import Flask | ||
| from flask_sqlalchemy import SQLAlchemy | ||
| from flask_migrate import Migrate | ||
| from dotenv import load_dotenv | ||
| import os | ||
|
|
||
| db = SQLAlchemy() | ||
| migrate = Migrate() | ||
| load_dotenv() | ||
|
|
||
| def create_app(test_config=None): | ||
| app = Flask(__name__) | ||
|
|
||
| if not test_config: | ||
| app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False | ||
| app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get( | ||
| "SQLALCHEMY_DATABASE_URI") | ||
| else: | ||
| app.config["TESTING"] = True | ||
| app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False | ||
| app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get( | ||
| "SQLALCHEMY_TEST_DATABASE_URI") | ||
|
|
||
| from app.models.planet import Planet | ||
|
|
||
| db.init_app(app) | ||
| migrate.init_app(app, db) | ||
|
|
||
| from .routes import planets_bp | ||
| app.register_blueprint(planets_bp) | ||
|
|
||
| return app | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| from app import db | ||
|
|
||
| class Planet(db.Model): | ||
| __tablename__ = "Planets" | ||
| id = db.Column(db.Integer,primary_key=True,autoincrement = True) | ||
| name = db.Column(db.String) | ||
| diameter = db.Column(db.String) | ||
| moons = db.Column(db.Boolean) | ||
| picture = db.Column(db.String) | ||
|
|
||
| def to_dict(self): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good helper method! |
||
| return ({"id": self.id, | ||
| "name": self.name, | ||
| "diameter": self.diameter, | ||
| "moons": self.moons, | ||
| "picture": self.picture}) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| { | ||
| "name": "Mercury", | ||
| "diameter":"Diameter: 3,031 miles (4,878 km)", | ||
| "moons": false, | ||
| "picture":"https://cdn.mos.cms.futurecdn.net/oU94fqcyf9HzQc59wJyaHN-970-80.jpg" | ||
| } | ||
|
|
||
| { | ||
| "name": "Venus", | ||
| "diameter": "Diameter: 7,521 miles (12,104 km)", | ||
| "moons": false, | ||
| "picture": "https://cdn.mos.cms.futurecdn.net/KhHofvaDG73pypCEzyLuab-970-80.png" | ||
| } | ||
|
|
||
| { | ||
| "name": "Earth", | ||
| "diameter": "Diameter: 7,926 miles (12,760 km)", | ||
| "moons": true, | ||
| "picture": "https://cdn.mos.cms.futurecdn.net/4aeTmiqCqpRKuFc8tkDcmm-970-80.jpg" | ||
| } | ||
|
|
||
| { | ||
| "name": "Mars", | ||
| "diameter": "Diameter: 4,217 miles (6,787 km)", | ||
| "moons": true, | ||
| "picture": "https://cdn.mos.cms.futurecdn.net/tQUhJUq9GXqMfZXjGYdw8c-970-80.jpg" | ||
| } | ||
|
|
||
| { | ||
| "name": "Jupiter", | ||
| "diameter":"Diameter: 86,881 miles (139,822 km)", | ||
| "moons": true, | ||
| "picture":"https://cdn.mos.cms.futurecdn.net/WyxFYsiUAQAgU4peSSoBNZ-970-80.png" | ||
| } | ||
|
|
||
| { | ||
| "name": "Saturn", | ||
| "diameter":"Diameter: 74,900 miles (120,500 km)", | ||
| "moons": true, | ||
| "picture":"https://cdn.mos.cms.futurecdn.net/bDVqRSjnbY9jMyVPmStUBY-970-80.png" | ||
| } | ||
|
|
||
| { | ||
| "name": "Uranus", | ||
| "diameter":"Diameter: 31,763 miles (51,120 km)", | ||
| "moons": true, | ||
| "picture":"https://cdn.mos.cms.futurecdn.net/kZXxHS85dDgVEAviQrM2KW-970-80.jpg" | ||
| } | ||
|
|
||
| { | ||
| "name": "Neptune", | ||
| "diameter":"Diameter: 30,775 miles (49,530 km)", | ||
| "moons": true, | ||
| "picture":"https://cdn.mos.cms.futurecdn.net/KW2AU72GRriUXQvsn5jAbg-970-80.jpg" | ||
| } |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -1,2 +1,137 @@ | ||||
| from flask import Blueprint | ||||
| from flask import Blueprint, jsonify, render_template, make_response, request, abort | ||||
| from app import db | ||||
| from app.models.planet import Planet | ||||
|
|
||||
|
|
||||
| planets_bp = Blueprint("planets_bp", __name__,url_prefix="/planets") | ||||
|
|
||||
|
|
||||
| @planets_bp.route("", methods = ["GET"]) | ||||
| def handle_planets(): | ||||
|
Comment on lines
+9
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Like the Query params |
||||
| planets_response = [] | ||||
|
|
||||
| if request.args.get("name"): | ||||
| planets = Planet.query.filter_by(name=request.args.get("name")) | ||||
|
|
||||
| elif request.args.get("has_moons"): | ||||
| planets = Planet.query.filter(Planet.moons == request.args.get("has_moons")) | ||||
|
|
||||
| elif request.args.get("order_by") == "name": | ||||
| planets = Planet.query.order_by(Planet.name) | ||||
|
|
||||
| else: | ||||
| planets = Planet.query.all() | ||||
| for planet in planets: | ||||
| planets_response.append(planet.to_dict()) | ||||
|
|
||||
| return jsonify(planets_response), 200 | ||||
|
|
||||
|
|
||||
| @planets_bp.route("/<planet_id>", methods=["GET", "PATCH", "PUT", "DELETE"]) | ||||
| def handle_planet(planet_id): | ||||
| if not planet_id.isnumeric(): | ||||
| return { "Error": f"{planet_id} must be numeric."}, 404 | ||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An argument can be made for this to be a 400 error as opposed to 404. |
||||
| planet_id = int(planet_id) | ||||
| planet = Planet.query.get(planet_id) | ||||
| if not planet: | ||||
| return { "Error": f"Planet {planet_id} was not found"}, 404 | ||||
|
|
||||
| elif request.method == "GET": | ||||
| return (planet.to_dict()),200 | ||||
|
|
||||
| elif request.method == "PATCH": | ||||
| form_data = request.get_json() | ||||
| sanitize_data(form_data) | ||||
| if 'name' in form_data: | ||||
| planet.name = request.json['name'] | ||||
| if 'diameter' in form_data: | ||||
| planet.diameter = request.json['diameter'] | ||||
| if 'moons' in form_data: | ||||
| planet.moons = request.json['moons'] | ||||
| if 'picture' in form_data: | ||||
| planet.picture = request.json['picture'] | ||||
|
|
||||
| db.session.commit() | ||||
|
|
||||
| return make_response(f"Planet #{planet.id} successfully updated") | ||||
|
|
||||
| elif request.method == "PUT": | ||||
| form_data = request.get_json() | ||||
| sanitize_data(form_data) | ||||
| planet.name = form_data["name"] | ||||
| planet.diameter = form_data["diameter"] | ||||
| planet.moons = form_data["moons"] | ||||
| planet.picture = form_data["picture"] | ||||
|
|
||||
| db.session.commit() | ||||
|
|
||||
| return make_response(f"Planet #{planet.id} successfully updated") | ||||
|
|
||||
| elif request.method == "DELETE": | ||||
| db.session.delete(planet) | ||||
| db.session.commit() | ||||
|
|
||||
| return { | ||||
| "message": f"Planet with title {planet.name} has been deleted" | ||||
| }, 200 | ||||
|
|
||||
|
|
||||
| @planets_bp.route("", methods=["POST"]) | ||||
| def create_planet(): | ||||
| request_data = request.get_json() | ||||
| sanitize_data(request_data) | ||||
|
|
||||
| if "name" not in request_data or "moons" not in request_data \ | ||||
| or "diameter" not in request_data or "picture" not in request_data: | ||||
|
|
||||
| return jsonify({"message": "Missing data"}), 400 | ||||
|
|
||||
| new_planet = Planet(name=request_data["name"], diameter=request_data["diameter"], | ||||
| moons=request_data["moons"], picture=request_data["picture"]) | ||||
|
|
||||
| db.session.add(new_planet) | ||||
| db.session.commit() | ||||
|
|
||||
| return f"Planet {new_planet.name} created", 201 | ||||
|
|
||||
| @planets_bp.route("/picturesummary", methods=["GET"]) | ||||
| def handle_planet_summary_params(): | ||||
|
Comment on lines
+97
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice custom route and use of |
||||
| if request.args.get("name"): | ||||
| planets = Planet.query.filter_by(name=request.args.get("name")) | ||||
| for planet in planets: | ||||
| if planet.moons == True: | ||||
| moon = "Yes" | ||||
| else: | ||||
| moon = "No" | ||||
| return render_template('planet_summary.html', | ||||
| url=planet.picture, | ||||
| title=planet.name, | ||||
| diameter=planet.diameter, | ||||
| moon=moon) | ||||
|
|
||||
| @planets_bp.route("/picturesummary/<planet_id>", methods=["GET"]) | ||||
| def handle_planet_summary(planet_id): | ||||
| planet = Planet.query.get(planet_id) | ||||
| if planet.moons == True: | ||||
| moon = "Yes" | ||||
| else: | ||||
| moon = "No" | ||||
|
|
||||
| return render_template('planet_summary.html', | ||||
| url=planet.picture, | ||||
| title=planet.name, | ||||
| diameter=planet.diameter, | ||||
| moon=moon) | ||||
|
Comment on lines
+120
to
+124
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh well! |
||||
|
|
||||
|
|
||||
| def sanitize_data(input_data): | ||||
| data_types = {"name":str, "diameter":str, "moons":bool, "picture":str} | ||||
| for name, val_type in data_types.items(): | ||||
| try: | ||||
| assert val_type==type(input_data[name]) | ||||
| print(name,type(input_data[name])) | ||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
|
|
||||
| except Exception as e: | ||||
| print(e) | ||||
| abort(400, "Bad Data") | ||||
| return input_data | ||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <html> | ||
| <head> | ||
| </head> | ||
|
|
||
| <body> | ||
| <img src="{{ url }}"> | ||
| </body> | ||
|
|
||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| <html> | ||
| <head> | ||
| </head> | ||
|
|
||
| <body> | ||
| <h1>{{title}}</h1> | ||
| <br> | ||
| <i>{{diameter}}</i> | ||
| <br> | ||
| <i>Moon: {{moon}}</i> | ||
| <br> | ||
| <img src="{{ url }}"> | ||
| </body> | ||
|
|
||
| </html> | ||
|
Comment on lines
+1
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎉 |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Generic single-database configuration. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # A generic, single database configuration. | ||
|
|
||
| [alembic] | ||
| # template used to generate migration files | ||
| # file_template = %%(rev)s_%%(slug)s | ||
|
|
||
| # set to 'true' to run the environment during | ||
| # the 'revision' command, regardless of autogenerate | ||
| # revision_environment = false | ||
|
|
||
|
|
||
| # Logging configuration | ||
| [loggers] | ||
| keys = root,sqlalchemy,alembic | ||
|
|
||
| [handlers] | ||
| keys = console | ||
|
|
||
| [formatters] | ||
| keys = generic | ||
|
|
||
| [logger_root] | ||
| level = WARN | ||
| handlers = console | ||
| qualname = | ||
|
|
||
| [logger_sqlalchemy] | ||
| level = WARN | ||
| handlers = | ||
| qualname = sqlalchemy.engine | ||
|
|
||
| [logger_alembic] | ||
| level = INFO | ||
| handlers = | ||
| qualname = alembic | ||
|
|
||
| [handler_console] | ||
| class = StreamHandler | ||
| args = (sys.stderr,) | ||
| level = NOTSET | ||
| formatter = generic | ||
|
|
||
| [formatter_generic] | ||
| format = %(levelname)-5.5s [%(name)s] %(message)s | ||
| datefmt = %H:%M:%S |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good use of env variables!