Zoisite- Halimat-A #25
Conversation
| return { | ||
| "id": planet.id, | ||
| "name": planet.name, | ||
| "description": planet.description, | ||
| "diameter": planet.diameter | ||
| } No newline at end of file |
There was a problem hiding this comment.
notice that the creation of this dictionary is also on lines 24-27. We can create an instance method in the planet class called to_dict that handles turning a planet into a dictionary that represents the planet.
Then in each of your routes, you could make the code more concise by writing:
planet = validate_planet(planet_id)
return planet.to_dict()
Here's how we handled this refactor in Flasky with the Cat class: https://github.com/Ada-C19/flasky/blob/zoisite/app/routes.py#L10-L16
|
|
||
| ] | ||
|
|
||
| planets_bp= Blueprint('planets', __name__,url_prefix='/planets') |
There was a problem hiding this comment.
nitpick: white spacing around the equal sign should be the same on both sides:
planets_bp = Blueprint('planets', __name__,url_prefix='/planets')
| @planets_bp.route("", methods=['GET']) | ||
|
|
||
| def handle_planets(): |
There was a problem hiding this comment.
Tthe decorator should come right before the function definition with no white space: https://www.flake8rules.com/rules/E304.html#:~:text=There%20should%20be%20no%20blank,the%20function%20it%20is%20decorating.
|
Nice job on Waves 1 & 2! It looks like you've got a handle on creating a blueprint, registering it with your Flask app and writing routes. With the suggested refactor, you'll be able to pull some logic out of your routes so that they can be even more concise. |
yangashley
left a comment
There was a problem hiding this comment.
Nice job finishing up Solar System Part 2 independently 🥳 I left some comments about consistently using white spaces in your code.
I also left some comments about how to make your tests more robust, how you can refactor the code to make it a little more concise, and places that you'll need to add error handling so that your API will properly handle bad data from the client.
Let me know if you have any questions!
| app.config['SQLALCHEMY_DATABASE_URI']= os.environ.get("SQLALCHEMY_DATABASE_URI") | ||
| else: | ||
| app.config["TESTING"] = True | ||
| app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
There was a problem hiding this comment.
Notice that line 14 and 18 are the same. Since this line of code needs to execute for both conditions, you can bring it outside the if/else block.
| planet_dict = {} | ||
| planet_dict["id"] = self.id | ||
| planet_dict["name"] = self.name | ||
| planet_dict["description"] = self.description | ||
| planet_dict["form"] = self.form | ||
|
|
||
| return planet_dict |
There was a problem hiding this comment.
Since you don't have any conditional logic when you create a dictionary and add key value pairs to it, you can directly return a dictionary literal like:
return {
"id": self.id,
"name": self.name,
"description": self.description,
"form": self.form
}| def from_dict(cls, planet_data): | ||
| new_planet = Planet(name=planet_data["name"], | ||
| description=planet_data["description"], | ||
| form=planet_data["form"]) | ||
| return new_planet No newline at end of file |
There was a problem hiding this comment.
Instead of hardcoding Planet on line 19, we should use the cls variable that a class method can access.
Since you don't have any conditional logic when you create an instance of the object, you can directly return the object like this without needing to create the variable new_planet:
return cls(
name = data_dict["name"],
description = data_dict["description"],
radius = data_dict["form"]
)| # class Planet: | ||
| # def __init__(self, id, name, description, diameter): | ||
| # self.id = id | ||
| # self.name = name | ||
| # self.description = description | ||
| # self.diameter = diameter | ||
|
|
||
| # planets = [Planet(1, 'Venus', 'The hottest planet',12104 ), | ||
| # Planet(2,'Mercury', 'Has no natural satellite', 4879), | ||
| # Planet(3,'Earth', 'The only planet where life is found', 12742 ) | ||
|
|
||
| # ] |
There was a problem hiding this comment.
Now that you've refactored Planet into it's own file, you can delete these comments to keep your project concise
|
|
||
| planets_bp= Blueprint('planets', __name__,url_prefix='/planets') | ||
| # Helper function | ||
| def validate_model(cls,model_id): |
There was a problem hiding this comment.
nitpick: there should be a space after the comma (cls, model_id)
| assert response_body == { | ||
| "id": 1, | ||
| "name": "Mercury", | ||
| "description": "rocky planet", | ||
| "form": "solid" | ||
| } |
There was a problem hiding this comment.
If you return planets from saved_planets (see my comment in conftest.py) then you could check that the actual planet queried from the database in your fixture are the same as what's returned from this GET request in your test.
That could look like:
mercury = saved_planets[0]
assert response_body["id"] == mercury.id
assert response_body[name"] == mercury.name
assert response_body["description"] == mercury.description
assert response_body["form"] == mercury.form| assert response_body[0] == {"id":1, "name":"Mercury", | ||
| "description":"rocky planet", "form":"solid" } |
There was a problem hiding this comment.
Since this is a GET request for all planets, we should also have an assertion to check that response_body[1] is equal to something.
If saved_planets returned a list of planets, then you could make this test even more robust by checking what is inside saved_planets against the response body (see my comment in test_get_one_planet_with_test_data)
| assert actual_planet.name == "Saturn" | ||
| assert actual_planet.description == "made of hydrogen" | ||
| assert actual_planet.form =="gas" No newline at end of file |
There was a problem hiding this comment.
A way to make this test more robust would to check the actual_planet against the values in PLANET_DICT, instead of string literals. That would look like:
assert actual_planet.name == EXPECTED_PLANET["name"]
assert actual_planet.description == EXPECTED_PLANET["description"]
assert actual_planet.form == EXPECTED_PLANET["form"]| planet = validate_model(Planet, planet_id) | ||
| db.session.delete(planet) | ||
| db.session.commit() | ||
| return make_response(jsonify(f"Planet {planet_id} deleted successfully")) No newline at end of file |
| from app import db | ||
|
|
||
| class Planet(db.Model): | ||
| id = db.Column(db.Integer,primary_key = True, autoincrement = True) |
There was a problem hiding this comment.
nitpick: the spacing here is inconsistent. we need a space after the comma after db.Integer and there should be no spaces before and after equal sign for the last 2 arguments. That would look like:
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
No description provided.