Skip to content

C22 - Sphinx - Tatiana Trofimova #38

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

Open
wants to merge 80 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
a5d2d10
Adds Task model
Nerpassevera Nov 5, 2024
8ad364a
Adds Task blueprint
Nerpassevera Nov 5, 2024
11048e4
Updates migration files
Nerpassevera Nov 5, 2024
20dabc8
Adds create_task to task_routes.py
Nerpassevera Nov 5, 2024
af10725
Adds get_one_task function
Nerpassevera Nov 5, 2024
1a41d60
Adds get_all_tasks function
Nerpassevera Nov 5, 2024
4d17fc6
refactor: Adds Task class method from_dict
Nerpassevera Nov 5, 2024
a6094b6
Adds edit_task function
Nerpassevera Nov 6, 2024
7d877be
Adds delete_task function
Nerpassevera Nov 6, 2024
991f860
Fixes tests for wave 1
Nerpassevera Nov 6, 2024
055a22f
Adds sorting order to get_all_tasks
Nerpassevera Nov 6, 2024
2858943
Adds complete and incomplete tasks finctionality
Nerpassevera Nov 6, 2024
3c6bb1f
Adds message sending functionality to mark_task_completed
Nerpassevera Nov 7, 2024
ededb67
Creates Goal model
Nerpassevera Nov 7, 2024
4bdfaec
refactor: Creates validate_model and set_new_attributes route utilities
Nerpassevera Nov 7, 2024
0589dab
feat: Creates goal routes
Nerpassevera Nov 7, 2024
360a353
Adds tests for goal_routes functions
Nerpassevera Nov 7, 2024
23f70c1
Adds /tasks GET and POST routes to Blueprint Goal
Nerpassevera Nov 8, 2024
b4031cc
refactor: removes abondend nullable
Nerpassevera Nov 8, 2024
d96de8b
refactor: minor changes
Nerpassevera Nov 9, 2024
81eb790
refactor: Creates utility func create_class_instance
Nerpassevera Nov 10, 2024
e328024
refactor: Creates utility func get_all_instances
Nerpassevera Nov 10, 2024
d2fbaf4
refactor: Creates utility func get_one_instance
Nerpassevera Nov 10, 2024
db350a8
refactor: Creates utility func update_instance
Nerpassevera Nov 10, 2024
b4c37a8
refactor: Creates utility func delete_instance
Nerpassevera Nov 10, 2024
a8c75bb
chore: remove print statements
Nerpassevera Nov 10, 2024
d910bdf
fix: a typo in Content_type
Nerpassevera Nov 10, 2024
490d343
refactor: Adds descriptive error message to create_class_instance
Nerpassevera Nov 10, 2024
94df535
Adds Travis CI config file
Nerpassevera Nov 20, 2024
cb0af09
Changes python v in travis config
Nerpassevera Nov 20, 2024
e391da3
Changes python v in travis config
Nerpassevera Nov 20, 2024
e93fc24
Changes python v in travis config3
Nerpassevera Nov 20, 2024
edc1841
Changes python v in travis config 4
Nerpassevera Nov 20, 2024
0039a99
Changes python v in travis config 5
Nerpassevera Nov 20, 2024
f9521b9
Changes python v in travis config 5
Nerpassevera Nov 20, 2024
3302239
Changes python v in travis config 6
Nerpassevera Nov 20, 2024
a6dcf4a
Changes python v in travis config 7
Nerpassevera Nov 20, 2024
b49f6a0
Changes python v in travis config 8
Nerpassevera Nov 20, 2024
2b73458
Changes python v in travis config 9
Nerpassevera Nov 20, 2024
4c54403
Changes python v in travis config 10
Nerpassevera Nov 20, 2024
d32dfb3
Changes python v in travis config 11
Nerpassevera Nov 20, 2024
1ca3859
Changes python v in travis config 12
Nerpassevera Nov 20, 2024
4d92b7d
Changes python v in travis config 13
Nerpassevera Nov 20, 2024
3fee895
Changes python v in travis config 13 fixed
Nerpassevera Nov 20, 2024
c440a7b
Changes python v in travis config 14
Nerpassevera Nov 20, 2024
069d7ec
Changes python v in travis config 15
Nerpassevera Nov 20, 2024
583722c
Changes python v in travis config 16
Nerpassevera Nov 20, 2024
3457fe4
Changes python v in travis config 17
Nerpassevera Nov 21, 2024
ed09c67
Changes python v in travis config 18
Nerpassevera Nov 21, 2024
6716d2a
Changes python v in travis config
Nerpassevera Nov 20, 2024
a4943da
Merge branch 'main' of https://github.com/Nerpassevera/task-list-api
Nerpassevera Nov 21, 2024
82fc58d
Adds instruction for deploy on Render
Nerpassevera Nov 21, 2024
4eb37c0
Adds instruction for deploy on Render 2
Nerpassevera Nov 21, 2024
5755c17
Adds instruction for deploy on Render 3
Nerpassevera Nov 21, 2024
0db806a
Adds instruction for deploy on Render 4
Nerpassevera Nov 21, 2024
321b6bd
Adds instruction for deploy on Render 5
Nerpassevera Nov 21, 2024
485dac5
Adds instruction for deploy on Render 6
Nerpassevera Nov 21, 2024
a92db83
Adds instruction for deploy on Render 7
Nerpassevera Nov 21, 2024
2e4dc64
Adds instruction for deploy on Render 8
Nerpassevera Nov 21, 2024
10c2c39
Breaking the code
Nerpassevera Dec 2, 2024
721fe94
Fixing the code
Nerpassevera Dec 2, 2024
52da2dc
Breaking the code
Nerpassevera Dec 2, 2024
2ffdc3f
Fixing the code
Nerpassevera Dec 2, 2024
a2bf5ed
Fixed to work with local frontend
Nerpassevera Dec 18, 2024
1b51387
Add render.yaml
Nerpassevera Dec 18, 2024
09f89e9
log for debugging the server version of backend
Nerpassevera Jan 4, 2025
363fb62
configurates CORS
Nerpassevera Jan 4, 2025
5ceb059
configurates CORS
Nerpassevera Jan 4, 2025
f22a456
fixing notofocations in deployed BE
Nerpassevera Jan 4, 2025
acca02a
fixing notofocations in deployed BE
Nerpassevera Jan 4, 2025
c2e586d
fixing notofocations in deployed BE
Nerpassevera Jan 4, 2025
5c178dd
fixing notofocations in deployed BE
Nerpassevera Jan 4, 2025
53f779c
fixing notofocations in deployed BE
Nerpassevera Jan 4, 2025
6052392
fixing notofocations in deployed BE
Nerpassevera Jan 4, 2025
b15e2d0
Merge branch 'main' of https://github.com/Nerpassevera/task-list-api
Nerpassevera Jan 5, 2025
011e936
adds gh-pages address to CORS configs
Nerpassevera Jan 5, 2025
c904e75
Updates README
Nerpassevera Jan 5, 2025
051049f
Create LICENSE
Nerpassevera Jan 5, 2025
6507919
Updates README
Nerpassevera Jan 5, 2025
4697786
Merge branch 'main' of https://github.com/Nerpassevera/task-list-api
Nerpassevera Jan 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,7 @@ dmypy.json
.pytype/

# Cython debug symbols
cython_debug/
cython_debug/

# Slack bot logo
slack_bot_logo.png
32 changes: 32 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
dist: focal
language: python
python:
- "3.9"
services:
- postgresql
addons:
postgresql: "13"
env:
global:
- SQLALCHEMY_TEST_DATABASE_URI=postgresql+psycopg2://postgres@localhost:5432/task_list_api_test
before_install:
- sudo apt-get update
- sudo apt-get install -y postgresql-13 postgresql-client-13
before_script:
- echo "Starting PostgreSQL..."
- sudo sed -i 's/#port = 5432/port = 5432/'
/etc/postgresql/13/main/postgresql.conf
- sudo systemctl restart postgresql || sudo service postgresql start
- psql --version
- psql -c 'create database task_list_api_test;' -U postgres || true
- psql -c '\l' -U postgres
- curl --version
install:
- pip install -r requirements.txt
script:
- pytest
after_success:
- echo "Deploying to Render..."
- echo "RENDER_API_KEY: ${RENDER_API_KEY}"
- curl -X POST "https://api.render.com/deploy/srv-csmrpdaj1k6c73dnhqi0?key=hVyereic-JM"
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Tatiana Trofimova

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
151 changes: 110 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,126 @@
# Task List API

## Skills Assessed
# Task List API Backend

- Gathering technical requirements from written documentation
- Reading, writing, and using tests
- Demonstrating understanding of the client-server model, request-response cycle and conventional RESTful routes
- Driving development with independent research, experimentation, and collaboration
- Reading and using existing external web APIs
- Using Postman as part of the development workflow
- Using git as part of the development workflow
A backend RESTful API built with Flask to manage tasks and goals in a full-stack project. The API is integrated with a PostgreSQL database and provides endpoints for creating, reading, updating, and deleting tasks and goals.

## About the Project

This backend application is part of a full-stack project created to practice and strengthen skills in backend development, API design, and database integration. It serves as the server-side component of the TaskList application.

### Deployed Application

- **Backend Deployment**: [Deployed Backend on Render](https://task-list-api-ai13.onrender.com)
- **Frontend Deployment**: [Deployed Frontend on GitHub Pages](https://nerpassevera.github.io/task-list-front-end)

## Features

### Tasks
- **Create Tasks**: Add new tasks.
- **Delete Tasks**: Remove tasks from the list.
- **Read Tasks**: Retrieve all tasks or a single task.
- **Update Tasks**: Update task information.
- **Mark Tasks as Completed/Incompleted**: Change the task status.
- **Slack Notifications**: Notify a Slack channel when a task is marked as completed.

Working with the Flask package:
### Goals
- **Create Goals**: Add new goals.
- **Delete Goals**: Remove goals from the list.
- **Read Goals**: Retrieve all goals or a single goal.
- **Update Goals**: Update goal information.
- **Assign Tasks to Goals**: Link multiple tasks to specific goals.

- Creating models
- Creating conventional RESTful CRUD routes for a model
- Reading query parameters to create custom behavior
- Create unconventional routes for custom behavior
- Apply knowledge about making requests in Python, to call an API inside of an API
- Apply knowledge about environment variables
- Creating a one-to-many relationship between two models
## Technologies Used

## Goals
- **Flask**: Lightweight web framework for Python.
- **SQLAlchemy**: ORM for database management.
- **Alembic**: Database migration tool.
- **PostgreSQL**: Relational database for storing tasks and goals.
- **Flask-CORS**: Manage Cross-Origin Resource Sharing for API.
- **Python-dotenv**: Manage environment variables using a `.env` file.

There's so much we want to do in the world! When we organize our goals into smaller, bite-sized tasks, we'll be able to track them more easily, and complete them!
## API Endpoints

If we make a web API to organize our tasks, we'll be able to create, read, update, and delete tasks as long as we have access to the Internet and our API is running!
### Tasks Routes

We also want to do some interesting features with our tasks. We want to be able to:
| Method | Endpoint | Description |
|----------|-----------------------------|------------------------------------------|
| GET | `/tasks` | Retrieve all tasks. |
| POST | `/tasks` | Create a new task. |
| GET | `/tasks/<task_id>` | Retrieve a specific task by ID. |
| PUT | `/tasks/<task_id>` | Update a specific task by ID. |
| DELETE | `/tasks/<task_id>` | Delete a specific task by ID. |
| PATCH | `/tasks/<task_id>/mark_complete` | Mark a task as completed. |
| PATCH | `/tasks/<task_id>/mark_incomplete` | Mark a task as incomplete. |

- Sort tasks
- Mark them as complete
- Get feedback about our task list through Slack
- Organize tasks with goals
### Goals Routes

... and more!
| Method | Endpoint | Description |
|----------|-----------------------------|------------------------------------------|
| GET | `/goals` | Retrieve all goals. |
| POST | `/goals` | Create a new goal. |
| GET | `/goals/<goal_id>` | Retrieve a specific goal by ID. |
| PUT | `/goals/<goal_id>` | Update a specific goal by ID. |
| DELETE | `/goals/<goal_id>` | Delete a specific goal by ID. |
| POST | `/goals/<goal_id>/tasks` |Assign multiple tasks to a specific goal. |
| GET | `/goals/<goal_id>/tasks` |Retrieve all tasks associated with a goal.|

## How to Complete and Submit
## Setup Instructions

Go through the waves one-by-one and build the features of this API.
### Prerequisites
- Python 3.12 or higher
- PostgreSQL

At submission time, no matter where you are, submit the project via Learn.
### Installation

## Project Directions
1. Clone the repository:
```bash
git clone https://github.com/Nerpassevera/task-list-api.git
cd task-list-api
```

This project is designed to fulfill the features described in detail in each wave. The tests are meant to only guide your development.
2. Create and activate a virtual environment:
```bash
python3 -m venv venv
source venv/bin/activate # On Linux/macOS
venv\Scripts\activate # On Windows
```

1. [Setup](ada-project-docs/setup.md)
1. [Testing](ada-project-docs/testing.md)
1. [Wave 1: CRUD for one model](ada-project-docs/wave_01.md)
1. [Wave 2: Using query params](ada-project-docs/wave_02.md)
1. [Wave 3: Creating custom endpoints](ada-project-docs/wave_03.md)
1. [Wave 4: Using an external web API](ada-project-docs/wave_04.md)
1. [Wave 5: Creating a second model](ada-project-docs/wave_05.md)
1. [Wave 6: Establishing a one-to-many relationship between two models](ada-project-docs/wave_06.md)
1. [Wave 7: Deployment](ada-project-docs/wave_07.md)
1. [Optional Enhancements](ada-project-docs/optional-enhancements.md)
3. Install dependencies:
```bash
pip install -r requirements.txt
```

4. Set up environment variables:
```bash
cp .env.example .env
```

Update `.env` with your database URL and Slack API key:
```
SQLALCHEMY_DATABASE_URI=<your_database_url>
SLACK_API_KEY=<your_slack_api_key>
```

5. Run database migrations:
```bash
flask db upgrade
```

6. Start the development server:
```bash
flask run
```

## Future Plans

- Create a meta route with information of endpoints available
- Allow users to dynamically change the Slack channel for notifications.
- Create user accounts

## Author

- [Tatiana Trofimova](https://github.com/Nerpassevera)

## License

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
57 changes: 57 additions & 0 deletions ada-project-docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Task List API

## Skills Assessed

- Gathering technical requirements from written documentation
- Reading, writing, and using tests
- Demonstrating understanding of the client-server model, request-response cycle and conventional RESTful routes
- Driving development with independent research, experimentation, and collaboration
- Reading and using existing external web APIs
- Using Postman as part of the development workflow
- Using git as part of the development workflow

Working with the Flask package:

- Creating models
- Creating conventional RESTful CRUD routes for a model
- Reading query parameters to create custom behavior
- Create unconventional routes for custom behavior
- Apply knowledge about making requests in Python, to call an API inside of an API
- Apply knowledge about environment variables
- Creating a one-to-many relationship between two models

## Goals

There's so much we want to do in the world! When we organize our goals into smaller, bite-sized tasks, we'll be able to track them more easily, and complete them!

If we make a web API to organize our tasks, we'll be able to create, read, update, and delete tasks as long as we have access to the Internet and our API is running!

We also want to do some interesting features with our tasks. We want to be able to:

- Sort tasks
- Mark them as complete
- Get feedback about our task list through Slack
- Organize tasks with goals

... and more!

## How to Complete and Submit

Go through the waves one-by-one and build the features of this API.

At submission time, no matter where you are, submit the project via Learn.

## Project Directions

This project is designed to fulfill the features described in detail in each wave. The tests are meant to only guide your development.

1. [Setup](ada-project-docs/setup.md)
1. [Testing](ada-project-docs/testing.md)
1. [Wave 1: CRUD for one model](ada-project-docs/wave_01.md)
1. [Wave 2: Using query params](ada-project-docs/wave_02.md)
1. [Wave 3: Creating custom endpoints](ada-project-docs/wave_03.md)
1. [Wave 4: Using an external web API](ada-project-docs/wave_04.md)
1. [Wave 5: Creating a second model](ada-project-docs/wave_05.md)
1. [Wave 6: Establishing a one-to-many relationship between two models](ada-project-docs/wave_06.md)
1. [Wave 7: Deployment](ada-project-docs/wave_07.md)
1. [Optional Enhancements](ada-project-docs/optional-enhancements.md)
17 changes: 14 additions & 3 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
from flask_cors import CORS
from flask import Flask
import os
from .routes.task_routes import bp as task_bp
from .routes.goal_routes import bp as goal_bp
Comment on lines +4 to +5

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

from .db import db, migrate
from .models import task, goal
import os


def create_app(config=None):
app = Flask(__name__)

CORS(app, resources={r"/*": {"origins": [
"http://localhost:5173",
"https://task-list-api-a1l3.onrender.com",
"https://nerpassevera.github.io"
]}})
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('SQLALCHEMY_DATABASE_URI')
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get(
'SQLALCHEMY_DATABASE_URI')

if config:
# Merge `config` into the app's configuration
Expand All @@ -18,5 +27,7 @@ def create_app(config=None):
migrate.init_app(app, db)

# Register Blueprints here
app.register_blueprint(task_bp)
app.register_blueprint(goal_bp)

return app
16 changes: 15 additions & 1 deletion app/models/goal.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import String
from ..db import db

class Goal(db.Model):
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
title: Mapped[str] = mapped_column(String(50))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider whether the this column for Goal should be nullable. It feels odd to allow someone to create a goal that gets saved to the DB without a title.

tasks: Mapped[list["Task"]] = relationship(back_populates="goal")

def to_dict(self):
return {
"id": self.id,
"title": self.title
}

@classmethod
def from_dict(cls, data):
return Goal(title=data["title"])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we can explicitly use Goal here, we can also use the cls keyword, like:

Suggested change
return Goal(title=data["title"])
return cls(title=data["title"])


35 changes: 34 additions & 1 deletion app/models/task.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import String, DateTime, ForeignKey
from datetime import datetime
from typing import Optional
from ..db import db

class Task(db.Model):
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
title: Mapped[str] = mapped_column(String(50))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As with Goal, consider which of the columns for Task should be nullable and which should not be.

description: Mapped[str] = mapped_column(String(255))
completed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
goal_id: Mapped[Optional[int]] = mapped_column(ForeignKey("goal.id"))
goal: Mapped[Optional["Goal"]] = relationship(back_populates="tasks")

def to_dict(self):
task_dict = {
"id": self.id,
"title": self.title,
"description": self.description,
"is_complete": bool(self.completed_at)
}

if self.goal_id is not None:
task_dict["goal_id"] = self.goal_id

return task_dict

@classmethod
def from_dict(cls, data):
data["completed_at"] = data.get("completed_at", None)

task = Task(
title=data["title"],
description=data["description"],
completed_at=data["completed_at"],
)

return task
Comment on lines +32 to +38

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you don't reference the variable task after you initialize it and before you return it, you can just directly return the instance of task without making a variable:

Suggested change
task = Task(
title=data["title"],
description=data["description"],
completed_at=data["completed_at"],
)
return task
return cls(
title=data["title"],
description=data["description"],
completed_at=data["completed_at"],
)

Loading