wave 1 and wave 2 by Danqing and Celina Group #4#21
wave 1 and wave 2 by Danqing and Celina Group #4#21DQLIU1995 wants to merge 4 commits intoAda-C19:mainfrom
Conversation
anselrognlie
left a comment
There was a problem hiding this comment.
You're off to a great start. Keep it up for the following waves! 🌊
Be sure to add an additional attribute to your Planet class.
| app = Flask(__name__) | ||
|
|
||
| return app | ||
| from .routes import bp |
| from flask import Blueprint, jsonify, abort, make_response | ||
|
|
||
| class Planet: | ||
| def __init__(self, id, name, description): |
There was a problem hiding this comment.
👀 Note that the project asked to
Define a
Planetclass with the attributesid,name, anddescription, and one additional attribute
Please add an additional attribute of your choosing to the Planet. This could any additional piece of information you'd like to track about the planet. Maybe some zodiacal association, discovery date, mass... really anything at all.
| self.name = name | ||
| self.description = description | ||
|
|
||
| def make_planet_dict(self): |
There was a problem hiding this comment.
✅ Nice helper to build a dict representing this type. The name here follows from the live code example, but prefer not mentioning the type in the function name. The type is implied by class we're in and doesn't need to be mentioned in the function name. So here something like make_dict would be more expected.
Consider that we would probably have a planet instance in a variable named something like planet. As written, calling the code to make a dict would look like
planet_dict = planet.make_planet_dict()which is a little redundant. If we shorten the name, it would be
planet_dict = planet.make_dict()We can still see that we're making a dict from a planet instance.
| planets = [ | ||
| Planet(1, "Apple Planet", "A planet that only grows Apple"), | ||
| Planet(2, "Orange Planet", "A planet that only grows orange"), | ||
| Planet(3, "Pear Planet", "A planet that only grows pear") |
There was a problem hiding this comment.
Stylistically, consider leaving a trailing , after the final item, which makes it easier to add additional items later if needed.
| Planet(3, "Pear Planet", "A planet that only grows pear") | ||
| ] | ||
|
|
||
| bp = Blueprint("planets", __name__, url_prefix="/planets") |
There was a problem hiding this comment.
✅ Blueprint looks good. Nice use of the conventional bp for the name.
| for planet in planets: | ||
| if planet.id == id: | ||
| return planet | ||
| abort(make_response({"message": f"Cat with id {id} was not found"}, 404)) |
There was a problem hiding this comment.
Update to Planet.
abort(make_response({"message": f"Planet with id {id} was not found"}, 404))|
|
||
|
|
||
| @bp.route("", methods=["GET"]) | ||
|
|
There was a problem hiding this comment.
👀 Watch out for stray lines. Decorators should sit directly on top of the function they're decorating.
|
|
||
| @bp.route("", methods=["GET"]) | ||
|
|
||
| def get_all_planets(): |
There was a problem hiding this comment.
✅ Looks good. But since you added the helper to make a dict, consider using a list comprehension to build up the converted list of dictionaries.
|
|
||
|
|
||
| @bp.route("/<id>", methods=["GET"]) | ||
| def search_single_planet(id): |
There was a problem hiding this comment.
✅ Looks good. Consider naming this something like get_single_planet rather than using search. Search usually implies a more involved operation, like looking for matches by name or something, and often there might be multiple results. Here's we're retrieving by id, not so much searching.
anselrognlie
left a comment
There was a problem hiding this comment.
Nice job overall, though I suspect there may be some fallout from the GH confusion at the end. The __init__.py for the project didn't get updated to connect to the database. When I did so locally, there were a number of problems that prevented the tests you have from running properly. Consult my comments for details. Your code is pretty close to what we'd like to see, so just stay vigilant when working on Task List.
There was a problem hiding this comment.
It looks like the updates to connect to the database didn't make it in here. Maybe it was misplaced with the GH confusion? In addition to registering the routes, things that we'd want to see in this file include:
- Initialize the database and migration systems
- Load connection string
- Load models (though if we load a route file that itself loads the models, we don't need to do this here)
|
|
||
| class Planet(db.Model): | ||
| id = db.Column(db.Integer, primary_key=True, autoincrement=True) | ||
| name = db.Column(db.String, nullable=False) |
There was a problem hiding this comment.
👍 Nice decision to mark these columns as not nullable.
| @classmethod | ||
| def from_dict(cls, data_dict): | ||
| return cls( | ||
| id=data_dict["id"], |
There was a problem hiding this comment.
👀 For at least the scenario we're using from_dict now (POST create route), we would not set the id explicitly. We want the database to set this when we commit the model record.
| rating=data_dict["rating"] | ||
| ) | ||
|
|
||
| def to_dictionary(self): |
There was a problem hiding this comment.
👀 As modelled in Learn (and how your code is calling it) this should be named to_dict.
| from flask import abort, make_response | ||
|
|
||
| #HELPER FUNCTIONS | ||
| def validate_model(cls, id): |
There was a problem hiding this comment.
👀 This helper should return the model if it was able to be looked up.
|
|
||
| # GET ONE ENDPOINT | ||
| @bp.route("/<id>", methods=["GET"]) | ||
| def handle_planet(id): |
| planet = validate_model(Planet, id) | ||
| request_body = request.get_json() | ||
|
|
||
| planet.id = request_body["id"] |
There was a problem hiding this comment.
👀 We should not attempt to change the id. Once the id has been assigned by the database during the create, we should leave it unchanged as long as the data remains in the DB.
| planet.name = request_body["name"] | ||
| planet.description = request_body["description"] | ||
| planet.rating = request_body["rating"] |
There was a problem hiding this comment.
As with my suggestion for the POST endpoint, we may want to wrap this with a try/expect to handle any KeyError that occurs.
|
|
||
| db.session.commit() | ||
|
|
||
| return make_response(f"Planet {planet.name} successfully updated", 200) |
There was a problem hiding this comment.
👀 At the least, this should jsonify the result so that all our endpoints return JSON. However, as with the POST endpoint, we might want to return the updated record.
| db.session.delete(planet) | ||
| db.session.commit() | ||
|
|
||
| return make_response(f"Planet {planet.name} successfully deleted", 200) |
There was a problem hiding this comment.
👀 At the least, this should jsonify the result so that all our endpoints return JSON. However, we might consider having no response body at all, since the 200 status itself should be enough to tell the caller that the delete occurred successfully.
No description provided.