-
Notifications
You must be signed in to change notification settings - Fork 44
C22-Phoenix -Tatyana Venanzi #30
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
…ed Slack post message API
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 overall! There are some items I would like to see you revisit, particularly around querying, I'll leave more details on that in Learn.
title: Mapped[str] = mapped_column(nullable=False) | ||
tasks: Mapped[List["Task"]] = relationship("Task", back_populates="goal") | ||
|
||
def goal_dict(self): |
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.
Since this function is a method of the Goal
class, including goal
in the name doesn't give the reader new information. Names like create_dict
, as_dict
, or to_dict
would convey a little more clearly to the user the intent of the function.
from ..db import db | ||
|
||
class Goal(db.Model): | ||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) | ||
title: Mapped[str] = mapped_column(nullable=False) |
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.
In the current version of SQLAlchemy nullable=False
is the default, so we could leave off the mapped_column
statement without changing our tables:
title: Mapped[str]
from ..db import db | ||
|
||
class Goal(db.Model): | ||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) | ||
title: Mapped[str] = mapped_column(nullable=False) | ||
tasks: Mapped[List["Task"]] = relationship("Task", back_populates="goal") |
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 works, but we can also use the built-in Python list
type here. I typically recommend using the Python built in unless there is a need to use a more specific library version of a data structure.
Since we define that the attribute is a list
of Task
s on the left side of the assignment, we do not need to pass "Task"
as the first parameter in the relationship
. This feedback applies to the relationship attribute in the Task
class as well.
tasks: Mapped[list["Task"]] = relationship(back_populates="goal")
title: Mapped[str] = mapped_column(nullable=False) | ||
description: Mapped[str] = mapped_column(nullable=False) | ||
completed_at: Mapped[Optional[datetime]] = mapped_column(nullable=True, default=None) |
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.
Since we aren't changing the default options for the declarations on the left side of the assignment, we can leave off the mapped_column
calls for these 3 attributes.
# Nullable is False by default unless an attribute is marked as Optional
# These 2 attributes are not nullable
title: Mapped[str]
description: Mapped[str]
# Since it is declared as Optional, nullable = True by default
# If an attribute is nullable, it will be defaulted to `None` if it is not set when a record is
# created unless a different default value is explicitly provided in the definition here
completed_at: Mapped[Optional[datetime]]
title: Mapped[str] = mapped_column(nullable=False) | ||
description: Mapped[str] = mapped_column(nullable=False) | ||
completed_at: Mapped[Optional[datetime]] = mapped_column(nullable=True, default=None) | ||
goal_id: Mapped[Optional[int]] = mapped_column(ForeignKey('goal.id'), nullable=True) |
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.
Since goal_id
is Optional
, we can leave off the nullable
argument in mapped_column
:
goal_id: Mapped[Optional[int]] = mapped_column(ForeignKey('goal.id'))
"Content-Type": "application/json" | ||
} | ||
|
||
notification = { |
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 notification
variable contains more that just the notification message, I suggest changing the variable name to reflect that.
@@ -0,0 +1,28 @@ | |||
import os |
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.
Really nice organization moving this out to its own file.
goals_bp = Blueprint("goals_bp", __name__, url_prefix="/goals") | ||
|
||
def validate_goal(goal_id): |
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 very similar to our validate_task
function, how could we refactor these functions to reduce repetition?
# @pytest.mark.skip(reason="test to be completed by student") | ||
def test_delete_goal_not_found(client): | ||
raise Exception("Complete test") | ||
|
||
# Act | ||
# ---- Complete Act Here ---- | ||
response = client.delete("/goals/999") # Assumes no goal with id=999 exists | ||
response_body = response.get_json() | ||
|
||
# Assert | ||
# ---- Complete Assertions Here ---- | ||
# assertion 1 goes here | ||
# assertion 2 goes here | ||
# ---- Complete Assertions Here ---- | ||
assert response.status_code == 404 | ||
assert response_body == {"message": "Goal 999 not found"} |
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.
Updates look great across the tests!
sort_order = request.args.get("sort", "asc") | ||
if sort_order == "desc": | ||
query = query.order_by(Task.title.desc()) | ||
else: | ||
query = query.order_by(Task.title.asc()) | ||
|
||
# Execute the query | ||
tasks = db.session.scalars(query) |
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 the syntax we should be using for querying any time we are trying to query for a result that could be more than a single record and may be applying filters and sorting to the results. When we know we only want a single record and have the primary key, the shorthand syntax used in mark_task_complete
is valid:
db.session.get(Task, task_id)
fyi: I tried to refactor my code while also doing wave 6 and majority of tests were failing so i went back to git and re-used the code i pushed up from up until wave 5 when all tests were passing and haven't refactored the updated code yet.