This application allows you to manage groups, students, and courses using a PostgreSQL database. It provides RESTful APIs to perform CRUD operations and manage relationships between entities.
- Groups: Create, retrieve, update, and delete groups.
- Students: Create, retrieve, update, and delete students. Assign students to groups and courses.
- Courses: Create, retrieve, update, and delete courses.
- Relationships: Manage many-to-many relationships between students and courses.
- Test Data: Generate test data with scripts.
- Testing: Includes unit tests using
pytest.
- Python 3.8+
- PostgreSQL
- Git (optional, for version control)
-
Clone the Repository
git clone https://github.com/ujer-lou/student_management.git cd student_management -
Set Up the PostgreSQL Database
-
Method 1: Create User, Database and Tables (Not Recommended 🛑)
psql -U postgres psql -f create_user_and_db.sql psql -d student_management -f create_tables.sql exit -
Method 2: Using pgAdmin/Pycharm database (Recommended 🟢)
- 1 Connect to your postgres database
- 2 Create new database
- 3 Set name for database
- 4 Make sure you can see that database is created
- 5 If you can see database you are done
-
-
Set Up the Python Environment
python3 -m venv .venv # if you already have venv activate it source .venv/bin/activate # On Windows: .venv\Scripts\activate pip install -r requirements.txt # Download requirements
-
Configure Environment Variables
-
Create a
.envfile in the root directory (optional) or in student_management and set the following variables:FLASK_APP=run.py FLASK_ENV=development SQLALCHEMY_DATABASE_URI=postgresql://appuser:app_password@localhost/database_name SECRET_KEY=your_secret_key # (Optional)Important:
- Replace
appuser,app_passwordanddatabase_namewith your actual PostgreSQL username, password and database name.
- Replace
-
-
Generate Test Data
There are two methods to run the
generate_test_data.pyscript:-
Method 1: Run as a Script
Ensure you're in the project root directory and your virtual environment is activated.
python3 scripts/generate_test_data.py
Note: If you encounter the
ModuleNotFoundError, proceed to Method 2. -
Method 2: Run Manually
- Run
generate_test_datamanually
- Run
-
-
Run the Application
python3 run.py
The application includes a comprehensive test suite using pytest to ensure all API endpoints function as expected.
-
Navigate to the Tests Directory
cd tests -
Run the Test Suite
pytest test_api.py -v
============================= test session starts ==============================
platform linux -- Python 3.11.11, pytest-8.3.4, pluggy-1.5.0
cachedir: .pytest_cache
rootdir: /home/bob/PycharmProjects/Foxtask10/student_management/tests
plugins: Faker-35.0.0
collected 16 items
test_api.py::test_create_group PASSED [ 6%]
test_api.py::test_get_groups PASSED [ 12%]
test_api.py::test_get_group_students PASSED [ 18%]
test_api.py::test_get_groups_with_max_students PASSED [ 25%]
test_api.py::test_create_student PASSED [ 31%]
test_api.py::test_get_students PASSED [ 37%]
test_api.py::test_get_student_details PASSED [ 43%]
test_api.py::test_update_student PASSED [ 50%]
test_api.py::test_add_student_to_course PASSED [ 56%]
test_api.py::test_remove_student_from_course PASSED [ 62%]
test_api.py::test_create_course PASSED [ 68%]
test_api.py::test_get_courses PASSED [ 75%]
test_api.py::test_get_course_details PASSED [ 81%]
test_api.py::test_update_course PASSED [ 87%]
test_api.py::test_delete_course PASSED [ 93%]
test_api.py::test_get_students_by_course_name PASSED [100%]
============================== 16 passed in 0.78s ===============================- GET
/groups- Retrieve all groups. - POST
/groups- Create a new group. - GET
/groups/<group_id>/students- Retrieve all students in a group. - GET
/groups/with_max_students?max_count=<number>- Retrieve groups with student count ≤ max_count.
- GET
/students- Retrieve all students. - POST
/students- Create a new student. - GET
/students/<student_id>- Retrieve a specific student. - PUT
/students/<student_id>- Update a specific student. - DELETE
/students/<student_id>- Delete a specific student. - POST
/students/<student_id>/courses/<course_id>- Add a course to a student. - DELETE
/students/<student_id>/courses/<course_id>- Remove a course from a student.
- GET
/courses- Retrieve all courses. - POST
/courses- Create a new course. - GET
/courses/<course_id>- Retrieve a specific course. - PUT
/courses/<course_id>- Update a specific course. - DELETE
/courses/<course_id>- Delete a specific course.
Below are examples of how to interact with the API using cURL. Replace <UUID> with the actual UUID of the resource
you are targeting.
curl -X POST http://localhost:5000/groups \
-H "Content-Type: application/json" \
-d '{"name": "Group-123e4567-e89b-12d3-a456-426614174000"}'Response:
{
"id": 1,
"name": "Group-123e4567-e89b-12d3-a456-426614174000"
}curl http://localhost:5000/groupsResponse:
[
{
"id": 1,
"name": "Group-123e4567-e89b-12d3-a456-426614174000"
},
{
"id": 2,
"name": "Group-223e4567-e89b-12d3-a456-426614174001"
}
]curl http://localhost:5000/groups/1/studentsResponse:
{
"group_id": 1,
"group_name": "Group-123e4567-e89b-12d3-a456-426614174000",
"students": [
{
"id": 1,
"first_name": "John",
"last_name": "Doe",
"group_id": 1,
"courses": [
"Course-123e4567-e89b-12d3-a456-426614174002"
]
}
]
}curl http://localhost:5000/groups/with_max_students?max_count=10Response:
[
{
"id": 1,
"name": "Group-123e4567-e89b-12d3-a456-426614174000",
"student_count": 5
},
{
"id": 2,
"name": "Group-223e4567-e89b-12d3-a456-426614174001",
"student_count": 8
}
]curl -X POST http://localhost:5000/students \
-H "Content-Type: application/json" \
-d '{
"first_name": "Jane",
"last_name": "Smith",
"group_id": 1
}'Response:
{
"id": 1,
"first_name": "Jane",
"last_name": "Smith",
"group_id": 1
}curl http://localhost:5000/studentsResponse:
[
{
"id": 1,
"first_name": "Jane",
"last_name": "Smith",
"group_id": 1,
"courses": [
"Course-123e4567-e89b-12d3-a456-426614174002"
]
},
{
"id": 2,
"first_name": "Emily",
"last_name": "Johnson",
"group_id": 2,
"courses": []
}
]curl http://localhost:5000/students/1Response:
{
"id": 1,
"first_name": "Jane",
"last_name": "Smith",
"group_id": 1,
"courses": [
"Course-123e4567-e89b-12d3-a456-426614174002"
]
}curl -X PUT http://localhost:5000/students/1 \
-H "Content-Type: application/json" \
-d '{
"first_name": "Janet",
"last_name": "Doe",
"group_id": 2
}'Response:
{
"message": "Student updated successfully"
}curl -X DELETE http://localhost:5000/students/1Response:
{
"message": "Student deleted successfully"
}curl -X POST http://localhost:5000/students/1/courses/1Response:
{
"message": "Course added to student"
}curl -X DELETE http://localhost:5000/students/1/courses/1Response:
{
"message": "Course removed from student"
}curl -X POST http://localhost:5000/courses \
-H "Content-Type: application/json" \
-d '{
"name": "Course-123e4567-e89b-12d3-a456-426614174002",
"description": "Introduction to Testing"
}'Response:
{
"id": 1,
"name": "Course-123e4567-e89b-12d3-a456-426614174002",
"description": "Introduction to Testing"
}curl http://localhost:5000/coursesResponse:
[
{
"id": 1,
"name": "Course-123e4567-e89b-12d3-a456-426614174002",
"description": "Introduction to Testing"
},
{
"id": 2,
"name": "Course-223e4567-e89b-12d3-a456-426614174003",
"description": "Advanced Python"
}
]curl http://localhost:5000/courses/1Response:
{
"id": 1,
"name": "Course-123e4567-e89b-12d3-a456-426614174002",
"description": "Introduction to Testing"
}curl -X PUT http://localhost:5000/courses/1 \
-H "Content-Type: application/json" \
-d '{
"name": "Course-123e4567-e89b-12d3-a456-426614174002",
"description": "Advanced Testing Techniques"
}'Response:
{
"message": "Course updated successfully"
}curl -X DELETE http://localhost:5000/courses/1Response:
{
"message": "Course deleted successfully"
}