-
Notifications
You must be signed in to change notification settings - Fork 61
Sharks - Jeannie Z. & Juli T. #15
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?
Conversation
audreyandoy
left a comment
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.
Part 1 looks great! 👍
app/__init__.py
Outdated
| from .routes import planet_bp | ||
| app.register_blueprint(planet_bp) |
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.
👍 Looks good! We can also move this file into a routes folder which would change the path of this import.
app/routes.py
Outdated
| class Planet: | ||
| def __init__(self, id, name, description, distance_from_earth): | ||
| self.id = id | ||
| self.name = name | ||
| self.description = description | ||
| self.distance_from_earth = distance_from_earth | ||
|
|
||
| def to_json(self): | ||
| return { | ||
| "id": self.id, | ||
| "name": self.name, | ||
| "description": self.description, | ||
| "Distance from Earth": self.distance_from_earth | ||
| } |
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 work!
app/routes.py
Outdated
| planets = [ | ||
| Planet(1, "Mars", "Next livable planet", "131.48 million mi"), | ||
| Planet(2, "Mercury", "Smallest planet", "94.025 million mi"), | ||
| Planet(3, "Earth", "We live here, slowly dying", "0.0 million mi") |
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.
Lol the description... 🤣 😭
app/routes.py
Outdated
| def get_planets(): | ||
| planets_response = [] | ||
| for planet in planets: | ||
| planets_response.append( | ||
| { | ||
| "id": planet.id, | ||
| "name": planet.name, | ||
| "description": planet.description, | ||
| "Distance from Earth": planet.distance_from_earth | ||
| }) | ||
| return jsonify(planets_response) |
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.
This is a good place to use the to_json() helper method from the Planet class:
def get_planets():
planets_response = []
for planet in planets:
planets_response.append(planet.to_json())
return jsonify(planets_response)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.
We can also use list comprehension to build planets_response.
app/routes.py
Outdated
| def validate_planet(planet_id): | ||
| try: | ||
| planet_id = int(planet_id) | ||
| except: | ||
| return abort(make_response({"message": f"planet {planet_id} is invaild"}, 400)) | ||
|
|
||
| for planet in planets: | ||
| if planet.id == planet_id: | ||
| return planet | ||
| return abort(make_response({"message": f"planet {planet_id} does not exist"}, 404)) |
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.
The validation for detecting bad ids and ids with no record looks good!
app/routes.py
Outdated
| @planet_bp.route("/<planet_id>", methods=["GET"]) | ||
| def get_one_planet(planet_id): | ||
| planet = validate_planet(planet_id) | ||
| return jsonify(planet.to_json(), 200) |
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.
👍 nice use of the helper method!
audreyandoy
left a comment
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.
Jeannie and Julie! Great work in finishing solar system. I have added comments on small ways to improve the API.
🦈 ✨
| 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__) | ||
|
|
||
|
|
||
| app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False | ||
| if not test_config: | ||
| app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get( | ||
| "SQLALCHEMY_DATABASE_URI") | ||
| else: | ||
| app.config["TESTING"] = True | ||
| app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get( | ||
| "SQLALCHEMY_TEST_DATABASE_URI") | ||
|
|
||
| db.init_app(app) | ||
| migrate.init_app(app, db) | ||
| from app.models.planet import Planet | ||
|
|
||
| from .routes.planet_routes import planet_bp | ||
| app.register_blueprint(planet_bp) |
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 work in setting up the Flask app!
| name = db.Column(db.String) | ||
| description = db.Column(db.String) | ||
| color = db.Column(db.String) |
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.
Should we be able to make planets with no name? To prevent our API from creating a planet with a null name, we can set that column to nullable = False.
name = db.Column(db.String, nullable=False)| def to_json(self): | ||
| return { | ||
| "id": self.id, | ||
| "name": self.name, | ||
| "description": self.description, | ||
| "color": self.color | ||
| } | ||
|
|
||
| def update(self, request_body): | ||
| self.name = request_body["name"] | ||
| self.description = request_body["description"] | ||
| self.color = request_body["color"] | ||
|
|
||
| @classmethod | ||
| def create(cls, request_body): | ||
| new_planet = cls( | ||
| name=request_body['name'], | ||
| description=request_body['description'], | ||
| color=request_body['color'] | ||
| ) | ||
| return new_planet |
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.
Nice use of helper methods and a class method!
| def validate_planet(planet_id): | ||
| try: | ||
| planet_id = int(planet_id) | ||
| except: | ||
| return abort(make_response(jsonify(f"Planet {planet_id} is invalid"), 400)) | ||
|
|
||
| planet = Planet.query.get(planet_id) | ||
|
|
||
| if not planet: | ||
| return abort(make_response(jsonify(f"Planet {planet_id} does not exist"), 404)) | ||
| return planet |
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.
Helpers look great! 👍 We may want to consider making the validation code as generic as possible to utilize any class and id or renaming this file to helper_planet_routes or planet_routes_helper. Either would be helpful if we expand this project to validate other objects like moons, suns, etc.
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.
A more generic validation helper method would look like:
from flask import make_response, abort
def validate_object(cls, id):
try:
id = int(id)
except:
return abort(make_response({"message": f"{cls} {id} is invalid"}, 400))
obj = cls.query.get(id)
if not obj:
abort(make_response({"message": f"{cls} {id} not found"},404))
return obj| @planet_bp.route("", methods=["POST"]) | ||
| def create_planet(): | ||
| request_body = request.get_json() | ||
|
|
||
| new_planet = Planet.create(request_body) | ||
|
|
||
| db.session.add(new_planet) | ||
| db.session.commit() | ||
|
|
||
| return make_response(jsonify(f"Planet {new_planet.name} has been created"), 201) |
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.
jsonify() is sufficient enough to generate a Response object
@planet_bp.route("", methods=["POST"])
def create_planet():
request_body = request.get_json()
new_planet = Planet.create(request_body)
db.session.add(new_planet)
db.session.commit()
return jsonify(f"Planet {new_planet.name} has been created"), 201| @ planet_bp.route("/<planet_id>", methods=["GET"]) | ||
| def get_one_planet(planet_id): | ||
| planet = validate_planet(planet_id) | ||
| return make_response(jsonify(planet.to_json()), 200) |
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.
👍 Nice work!
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.
Also, if a view function returns a dictionary (planet.to_json() in this case), Flask will automatically convert the dictionary into a JSON response object (aka Flask will turn dictionaries into JSON data for us). This means you can leave out make_response() like so:
@planets_bp.route("/<planet_id>", methods=["GET"])
def get_one_planet(planet_id):
planet = validate_planet(planet_id)
return planet.to_json(), 200Here's the documentation with more info:
https://flask.palletsprojects.com/en/2.0.x/quickstart/#apis-with-json
| @ planet_bp.route("/<planet_id>", methods=["PUT"]) | ||
| def update_planet(planet_id): | ||
| planet = validate_planet(planet_id) | ||
| request_body = request.get_json() | ||
|
|
||
| try: | ||
| Planet.update(request_body) | ||
| db.session.commit() | ||
| except KeyError: | ||
| return abort(make_response(jsonify("Missing information")), 400) | ||
|
|
||
| return make_response(jsonify(f"Planet #{planet.id} successfully updated"), 200) |
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.
Nice work! We may want to consider validating the request_body data in a separate helper method.
| @ planet_bp.route("/<planet_id>", methods=["DELETE"]) | ||
| def delete_one_planet(planet_id): | ||
| planet = validate_planet(planet_id) | ||
|
|
||
| db.session.delete(planet) | ||
| db.session.commit() | ||
|
|
||
| return make_response(jsonify(f"Planet {planet.id} has been deleted"), 200) |
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.
👍 Comment about not needing make_response also applies.
| def two_saved_planets(app): | ||
| # Arrange | ||
| planet_one = Planet(name="Mars", | ||
| description="Close enough", | ||
| color="Red") | ||
| planet_two = Planet(name="Earth", | ||
| description="we out here", | ||
| color = "Green") | ||
|
|
||
| db.session.add_all([planet_one, planet_two]) | ||
| db.session.commit() No newline at end of file |
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.
👍
| @@ -0,0 +1,73 @@ | |||
| #`GET` `/planets` returns `200` and an empty array. | |||
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.
Test routes look great 👍 !
Completed Wave 1 & 2.