Skip to content

Commit 95143a8

Browse files
C22 task-list-api updates (#67)
* Remove incorrect Wave_1 requirement from wave_01.md. Change primary keys for Task and Goal to be uid=501(kelseysteven) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),701(com.apple.sharepoint.group.1),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),400(com.apple.access_remote_ae). Update project scaffold for flask changes. Update wave 1-5 docs for flask changes (more remain to update) * Add info and screenshots to deployment doc about choosing the runtime * Update requirements.txt * Add requests package for sending Slack notification * Update to_json to to_dict following what we use in class * Remove mention of combined routes file * Update ada-project-docs/optional-enhancements.md * Update screenshots for setting language in Render * Add red circle in first image showing where Language field is * Updates for PR review to fix typos & be consistent with how we reference waves * Apply suggestions from code review Co-authored-by: Ashley Yang <ashley@adadevelopersacademy.org> --------- Co-authored-by: Ashley Yang <ashley@adadevelopersacademy.org>
1 parent 48a3ee1 commit 95143a8

File tree

18 files changed

+127
-138
lines changed

18 files changed

+127
-138
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Skills Assessed
44

5-
- Following directions and reading comprehension
5+
- Gathering technical requirements from written documentation
66
- Reading, writing, and using tests
77
- Demonstrating understanding of the client-server model, request-response cycle and conventional RESTful routes
88
- Driving development with independent research, experimentation, and collaboration
131 KB
Loading
80.3 KB
Loading

ada-project-docs/optional-enhancements.md

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,6 @@ How would you write tests for it? How would you implement it?
2828

2929
Your decisions should not break the other tests.
3030

31-
### Re-organize Routes
32-
33-
Consider refactoring how endpoints are written in the `routes.py` file.
34-
35-
Here are some ideas to start:
36-
37-
- Instead of having `if/elif` blocks to handle many HTTP methods in one route method, separate them into different route methods
38-
3931
### Model Instance Methods
4032

4133
We can define instance methods in our model classes.
@@ -44,7 +36,7 @@ Consider places in your code that deal with one model at a time. Is there any re
4436

4537
Here are some ideas to start:
4638

47-
- Create an instance method in `Task` named `to_json()`
39+
- Create an instance method in `Task` named `to_dict()`
4840
- Converts a `Task` instance into JSON
4941
- Returns a Python dictionary in the shape of the JSON our API returns in the `GET` `/tasks` route
5042
- Create a class method in `Task` named `from_json()`
@@ -54,13 +46,13 @@ Here are some ideas to start:
5446

5547
### Use List Comprehensions
5648

57-
Use list comprehensions in your `routes.py` logic.
49+
Use list comprehensions in your route functions where applicable.
5850

5951
### Route Helper Methods
6052

61-
If you have not already refactored your `routes.py` to use helper methods, do so now!
53+
If you have not already refactored your route files to use helper methods, do so now!
6254

63-
Consider code with complex or repetitive logic, and refactor it into helper methods. Watch your `routes.py` file become cleaner and more readable!
55+
Consider code with complex or repetitive logic, and refactor it into helper methods. Watch your route files become cleaner and more readable!
6456

6557
### More Query Params
6658

ada-project-docs/setup.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ The goal for setup is to cover all of the set up needed at the beginning of this
99
1. Setting up development and test databases
1010
1. Setting up a `.env` file
1111
1. Running `$ flask db init`
12-
1. Running `$ flask run` and `$ FLASK_ENV=development flask run`
12+
1. Running `$ flask run` and `$ flask run --debug`
1313

1414
# Requirements
1515

@@ -63,14 +63,14 @@ Run `$ flask db init`.
6363

6464
**_After you make your first model in Wave 1_**, run the other commands `migrate` and `upgrade`.
6565

66-
## Run `$ flask run` or `$ FLASK_ENV=development flask run`
66+
## Run `$ flask run` or `$ flask run --debug`
6767

6868
Check that your Flask server can run with `$ flask run`.
6969

7070
We can run the Flask server specifying that we're working in the development environment. This enables hot-reloading, which is a feature that refreshes the Flask server every time there is a detected change.
7171

7272
```bash
73-
$ FLASK_ENV=development flask run
73+
$ flask run --debug
7474
```
7575

7676
**It is highly recommended to run the Flask servers with this command**.

ada-project-docs/wave_01.md

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,25 @@ Tasks are entities that describe a task a user wants to complete. They contain a
1010
- description to hold details about the task
1111
- an optional datetime that the task is completed on
1212

13-
Our goal for this wave is to be able to create, read, update, and delete different tasks. We will create RESTful routes for this different operations.
13+
Our goal for this wave is to be able to create, read, update, and delete different tasks. We will create RESTful routes for these different operations.
1414

1515
# Requirements
1616

1717
## Task Model
1818

1919
There should be a `Task` model that lives in `app/models/task.py`.
2020

21-
Tasks should contain these attributes. Feel free to change the name of the `task_id` column if you would like. **The tests require the remaining columns to be named exactly** as `title`, `description`, and `completed_at`.
21+
Tasks should contain these attributes. **The tests require the following columns to be named exactly** as `title`, `description`, and `completed_at`.
2222

23-
- `task_id`: a primary key for each task
23+
- `id`: a primary key for each task
2424
- `title`: text to name the task
2525
- `description`: text to describe the task
26-
- `completed_at`: a datetime that has the date that a task is completed on. **Can be _nullable_,** and contain a null value. A task with a `null` value for `completed_at` has not been completed. When we create a new task, `completed_at` should be `null` AKA `None` in Python.
26+
- `completed_at`: a datetime that represents the date that a task is completed on. **Can be _nullable_,** and contain a null value. A task with a `null` value for `completed_at` has not been completed. When we create a new task, `completed_at` should be `null` AKA `None` in Python.
2727

2828
### Tips
2929

30-
- SQLAlchemy's column type for text is `db.String`. The column type for datetime is `db.DateTime`.
31-
- SQLAlchemy supports _nullable_ columns with specific syntax.
30+
- To work with date information, we can import the `datetime` data type with the import line `from datetime import datetime`.
31+
- SQLAlchemy supports optional, or _nullable_, columns with specific syntax.
3232
- Don't forget to run:
3333
- `flask db init` once during setup
3434
- `flask db migrate` every time there's a change in models, in order to generate migrations
@@ -38,8 +38,6 @@ Tasks should contain these attributes. Feel free to change the name of the `task
3838

3939
## CRUD for Tasks
4040

41-
The following are required routes for wave 1. Feel free to implement the routes in any order within this wave.
42-
4341
### Tips
4442

4543
- Pay attention to the exact shape of the expected JSON. Double-check nested data structures and the names of the keys for any mispellings.
@@ -52,9 +50,15 @@ The following are required routes for wave 1. Feel free to implement the routes
5250

5351
### CLI
5452

55-
In addition to testing your code with pytest and postman, you can play test your code with the CLI (Command Line Interface) by running `python3 cli/main.py`. The flask server needs to be running to run the CLI.
53+
In addition to testing your code with pytest and postman, you can play test your code with the CLI (Command Line Interface) by running `python3 cli/main.py`.
54+
55+
The flask server needs to be running first before running the CLI.
56+
57+
### CRUD Routes
5658

57-
### Create a Task: Valid Task With `null` `completed_at`
59+
The following are required routes for wave 1. Feel free to implement the routes in any order within this wave.
60+
61+
#### Create a Task: Valid Task With `null` `completed_at`
5862

5963
As a client, I want to be able to make a `POST` request to `/tasks` with the following HTTP request body
6064

@@ -83,7 +87,7 @@ and get this response:
8387

8488
so that I know I successfully created a Task that is saved in the database.
8589

86-
### Get Tasks: Getting Saved Tasks
90+
#### Get Tasks: Getting Saved Tasks
8791

8892
As a client, I want to be able to make a `GET` request to `/tasks` when there is at least one saved task and get this response:
8993

@@ -106,7 +110,7 @@ As a client, I want to be able to make a `GET` request to `/tasks` when there is
106110
]
107111
```
108112

109-
### Get Tasks: No Saved Tasks
113+
#### Get Tasks: No Saved Tasks
110114

111115
As a client, I want to be able to make a `GET` request to `/tasks` when there are zero saved tasks and get this response:
112116

@@ -116,7 +120,7 @@ As a client, I want to be able to make a `GET` request to `/tasks` when there ar
116120
[]
117121
```
118122

119-
### Get One Task: One Saved Task
123+
#### Get One Task: One Saved Task
120124

121125
As a client, I want to be able to make a `GET` request to `/tasks/1` when there is at least one saved task and get this response:
122126

@@ -133,7 +137,7 @@ As a client, I want to be able to make a `GET` request to `/tasks/1` when there
133137
}
134138
```
135139

136-
### Update Task
140+
#### Update Task
137141

138142
As a client, I want to be able to make a `PUT` request to `/tasks/1` when there is at least one saved task with this request body:
139143

@@ -159,9 +163,9 @@ and get this response:
159163
}
160164
```
161165

162-
Note that the update endpoint does update the `completed_at` attribute. This will be updated with custom endpoints implemented in Wave 03.
166+
Note that the update endpoint does update the `completed_at` attribute. This will be updated with custom endpoints implemented in Wave 3.
163167

164-
### Delete Task: Deleting a Task
168+
#### Delete Task: Deleting a Task
165169

166170
As a client, I want to be able to make a `DELETE` request to `/tasks/1` when there is at least one saved task and get this response:
167171

@@ -173,15 +177,15 @@ As a client, I want to be able to make a `DELETE` request to `/tasks/1` when the
173177
}
174178
```
175179

176-
### No matching Task: Get, Update, and Delete
180+
#### No Matching Task: Get, Update, and Delete
177181

178182
As a client, if I make any of the following requests:
179183

180184
* `GET` `/tasks/<task_id>`
181185
* `UPDATE` `/tasks/<task_id>`
182186
* `DELETE` `/tasks/<task_id>`
183187

184-
and there is no existing task with `task_id`
188+
and there is no existing task with an `id` of `task_id`
185189

186190
The response code should be `404`.
187191

@@ -190,9 +194,9 @@ You may choose the response body.
190194
Make sure to complete the tests for non-existing tasks to check that the correct response body is returned.
191195

192196

193-
### Create a Task: Invalid Task With Missing Data
197+
#### Create a Task: Invalid Task With Missing Data
194198

195-
#### Missing `title`
199+
##### Missing `title`
196200

197201
As a client, I want to be able to make a `POST` request to `/tasks` with the following HTTP request body
198202

@@ -215,7 +219,7 @@ and get this response:
215219

216220
so that I know I did not create a Task that is saved in the database.
217221

218-
#### Missing `description`
222+
##### Missing `description`
219223

220224
If the HTTP request is missing `description`, we should also get this response:
221225

@@ -226,15 +230,3 @@ If the HTTP request is missing `description`, we should also get this response:
226230
"details": "Invalid data"
227231
}
228232
```
229-
230-
#### Missing `completed_at`
231-
232-
If the HTTP request is missing `completed_at`, we should also get this response:
233-
234-
`400 Bad Request`
235-
236-
```json
237-
{
238-
"details": "Invalid data"
239-
}
240-
```

ada-project-docs/wave_05.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ This wave requires more test writing.
1818
- These tests are currently skipped with `@pytest.mark.skip(reason="test to be completed by student")` and the function body has `pass` in it. Once you implement these tests you should remove the `skip` decorator and the `pass`.
1919
- For the tests you write, use the requirements in this document to guide your test writing.
2020
- Pay attention to the exact shape of the expected JSON. Double-check nested data structures and the names of the keys for any mispellings.
21-
- You can model your tests off of the Wave 01 tests for Tasks.
21+
- You can model your tests off of the Wave 1 tests for Tasks.
2222
- Some tests use a [fixture](https://docs.pytest.org/en/6.2.x/fixture.html) named `one_goal` that is defined in `tests/conftest.py`. This fixture saves a specific goal to the test database.
2323

2424

@@ -28,9 +28,9 @@ This wave requires more test writing.
2828

2929
There should be a `Goal` model that lives in `app/models/goal.py`.
3030

31-
Goals should contain these attributes. Feel free to change the name of the `goal_id` column if you would like. **The tests require the title column to be named exactly** as `title`.
31+
Goals should contain these attributes. **The tests require the title column to be named exactly** as `title`.
3232

33-
- `goal_id`: a primary key for each goal
33+
- `id`: a primary key for each goal
3434
- `title`: text to name the goal
3535

3636
### Tips

ada-project-docs/wave_06.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,26 @@ Secondly, we should create our new route, `/goals/<goal_id>/tasks`, so that our
1616

1717
### Tips
1818

19-
- Use independent research to discover how to set up a one-to-many relationship in Flask.
19+
- Use lesson materials and independent research to review how to set up a one-to-many relationship in Flask.
2020
- Remember to run `flask db migrate` and `flask db upgrade` whenever there is a change to the model.
2121
- Pay attention to the exact shape of the expected JSON. Double-check nested data structures and the names of the keys for any mispellings.
2222
- Use the tests in `tests/test_wave_06.py` to guide your implementation.
2323
- Some tests use a fixture named `one_task_belongs_to_one_goal` that is defined in `tests/conftest.py`. This fixture saves a task and a goal to the test database, and uses SQLAlchemy to associate the goal and task together.
2424

2525
### Updates to the Goal Model
2626

27-
Use independent research to discover how to set up a one-to-many relationship in Flask.
28-
2927
The Goal model should have a _relationship_ with the model Task.
3028

31-
After learning the strategy for creating a one-to-many relationship, in the Goal model, we recommend:
32-
33-
- Setting the `lazy` value to `True`
29+
After reviewing the strategy for creating a one-to-many relationship, it is up to you if you would like to add convenience attributes for accessing the `Goal` model from it's related `Task`s and vice versa, accessing the list of associated `Task`s from a `Goal` model.
3430

3531
### Updates to the Task Model
3632

37-
Use independent research to discover how to set up a one-to-many relationship in Flask.
38-
3933
The Task model should belong to one `Goal`.
4034

41-
After learning the strategy for creating a one-to-many relationship, in the Task model, we recommend:
35+
After reviewing the strategy for creating a one-to-many relationship, in the Task model, we recommend:
4236

4337
- Setting the foreign key to `goal`'s primary key column
44-
- Setting the `nullable` to `True`
38+
- Using `Optional` syntax to make the attribute nullable
4539

4640
Remember to run `flask db migrate` and `flask db upgrade` whenever there is a change to the model.
4741

ada-project-docs/wave_07.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ Our goal is to make our project accessible online!
88

99
Deploy this project to Render.
1010

11-
Then, add some Task records and Goal records to the production database.
11+
When deploying a web service to Render, it will try to be helpful and set the `Language` field for you, but it doesn't always select the correct option.
12+
13+
![A screen shot of Render's UI for deploying a web service with the Language field circled in red showing Docker selected](assets/render-show-language-field.png)
14+
15+
Our language for this project should be `Python 3`, which you can select from a drop down if needed by clicking on the current value of the `Language` field.
16+
17+
![A screen shot of Render's UI for deploying a web service showing the drop down for selecting a runtime value](assets/render-show-language-drop-down.png)
18+
19+
Once deployed, add some Task records and Goal records to the production database.
1220

1321
Be sure to grab the URL of your deployed app. It will be submitted at the time of project submission.
1422

app/__init__.py

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,18 @@
11
from flask import Flask
2-
from flask_sqlalchemy import SQLAlchemy
3-
from flask_migrate import Migrate
2+
from .db import db, migrate
3+
from .models import task, goal
44
import os
5-
from dotenv import load_dotenv
65

7-
8-
db = SQLAlchemy()
9-
migrate = Migrate()
10-
load_dotenv()
11-
12-
13-
def create_app(test_config=None):
6+
def create_app(config=None):
147
app = Flask(__name__)
15-
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
168

17-
if test_config is None:
18-
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
19-
"SQLALCHEMY_DATABASE_URI")
20-
else:
21-
app.config["TESTING"] = True
22-
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
23-
"SQLALCHEMY_TEST_DATABASE_URI")
9+
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
10+
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('SQLALCHEMY_DATABASE_URI')
2411

25-
# Import models here for Alembic setup
26-
from app.models.task import Task
27-
from app.models.goal import Goal
12+
if config:
13+
# Merge `config` into the app's configuration
14+
# to override the app's default settings for testing
15+
app.config.update(config)
2816

2917
db.init_app(app)
3018
migrate.init_app(app, db)

0 commit comments

Comments
 (0)