Conversation
| from app import db | ||
|
|
||
|
|
||
| class Goal(db.Model): |
There was a problem hiding this comment.
Great job completing Task List Elaine! Your code looks clean and easily readable. I want to point out the good variable naming and your code is DRY. Great use of helper methods in your models! Excellent work using blue prints & creating RESTful CRUD routes for each model.
| completed_at = db.Column(db.DateTime, nullable=True) | ||
| goal_id = db.Column(db.Integer, db.ForeignKey('goal.goal_id')) | ||
| goal = db.relationship('Goal', back_populates='tasks') | ||
|
|
There was a problem hiding this comment.
Nice approach creating this relationship to your Goal model. Why not use lazy here?
| @classmethod | ||
| def from_dict(cls, task_data): | ||
| new_task = Task(title=task_data["title"], | ||
| description=task_data["description"], | ||
| completed_at=None) | ||
| return new_task | ||
|
|
||
| def to_dict(self): | ||
| task_as_dict = { | ||
| "id": self.task_id, | ||
| "title": self.title, | ||
| "description": self.description, | ||
| "is_complete": bool(self.completed_at) | ||
| } | ||
|
|
||
| if self.goal_id: | ||
| task_as_dict["goal_id"] = self.goal_id | ||
|
|
||
| return task_as_dict No newline at end of file |
There was a problem hiding this comment.
Great job creating this reusable helper function
| from .routes import task_bp | ||
| app.register_blueprint(task_bp) | ||
| from .routes import goal_bp | ||
| app.register_blueprint(goal_bp) |
There was a problem hiding this comment.
Great work registering these blueprints ✅
| @@ -1 +1,280 @@ | |||
| from flask import Blueprint No newline at end of file | |||
| from flask import Blueprint, jsonify, request, abort, make_response | |||
There was a problem hiding this comment.
👍🏾 These imports help a great deal when it comes to our request & response cycle
| task_bp = Blueprint("tasks", __name__, url_prefix="/tasks") | ||
| goal_bp = Blueprint("goals", __name__, url_prefix="/goals") |
| def validate_model(cls, model_id): | ||
| try: | ||
| model_id = int(model_id) | ||
| except: | ||
| abort(make_response({"message":f"{model_id} invalid type ({type(model_id)})"}, 400)) | ||
| # abort(make_response({"message":f"Invalid data"}, 400)) | ||
|
|
||
| model = cls.query.get(model_id) | ||
|
|
||
| if not model: | ||
| abort(make_response({"message":f"{cls.__name__.lower()} {model_id} not found"}, 404)) | ||
|
|
||
| return model | ||
|
|
| new_task = Task.from_dict(request_body) | ||
|
|
||
| # database collects new changes - adding new_task as a record | ||
| db.session.add(new_task) |
There was a problem hiding this comment.
Great job using db.session.<method-name>. Session gives us access to the follow:
dbis our app’s instance of SQLAlchemy.sessionrepresents our active database connection.- By referencing
db.sessionwe can use SQLAlchemy’s methods to perform tasks like:- committing a change to a model
- storing a new record of a model
- deleting a record.
- By referencing
db.session.add()you are able to use the SQLAlchemy method to store a new record of the task model
| "id": new_task.task_id, | ||
| "title": new_task.title, | ||
| "description": new_task.description, | ||
| "is_complete": bool(new_task.completed_at) |
| sort_query = request.args.get("sort") | ||
|
|
||
| if sort_query == "asc": | ||
| tasks = Task.query.order_by(Task.title).all() | ||
| elif sort_query == "desc": | ||
| tasks = Task.query.order_by(desc(Task.title)).all() | ||
| else: |
There was a problem hiding this comment.
⭐️ Great work handling this query param logic ⭐️
| assert response_body == {"message": "task 1 not found"} | ||
|
|
There was a problem hiding this comment.
Nice work with this test completion! This assertion is a great way to validate functionality is working as expected
| "id": new_goal.goal_id, | ||
| "title": new_goal.title | ||
| } | ||
| }, 201 |
There was a problem hiding this comment.
Usually a resource creation relates to a 201 response code 👍🏾
No description provided.