{"id":25067093,"url":"https://github.com/sandesh300/fastapi-crud-operations-application","last_synced_at":"2026-04-12T07:32:55.630Z","repository":{"id":265227063,"uuid":"895516275","full_name":"sandesh300/FastAPI-CRUD-Operations-Application","owner":"sandesh300","description":"CRUD Operations API Development","archived":false,"fork":false,"pushed_at":"2024-11-29T14:27:27.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-06T20:39:30.395Z","etag":null,"topics":["fastapi","openssl","postgresql","python","rest-api"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sandesh300.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-28T11:01:11.000Z","updated_at":"2024-12-19T07:32:02.000Z","dependencies_parsed_at":"2024-11-28T12:20:12.530Z","dependency_job_id":"af48ff18-e6b8-4353-ba05-01fae0ae9be7","html_url":"https://github.com/sandesh300/FastAPI-CRUD-Operations-Application","commit_stats":null,"previous_names":["sandesh300/curd-api-python","sandesh300/fastapi-crud-operations-application"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandesh300%2FFastAPI-CRUD-Operations-Application","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandesh300%2FFastAPI-CRUD-Operations-Application/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandesh300%2FFastAPI-CRUD-Operations-Application/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandesh300%2FFastAPI-CRUD-Operations-Application/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sandesh300","download_url":"https://codeload.github.com/sandesh300/FastAPI-CRUD-Operations-Application/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246482208,"owners_count":20784656,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","openssl","postgresql","python","rest-api"],"created_at":"2025-02-06T20:35:28.926Z","updated_at":"2025-10-12T08:09:16.154Z","avatar_url":"https://github.com/sandesh300.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CRUD Operations API Development\n\n## Overview\nThis is a FastAPI-based CRUD (Create, Read, Update, Delete) application that handles **Users** and **Orders**, featuring full test coverage.\n\n## Setup and Installation\n\n### Prerequisites\nTo install the necessary dependencies, run the following command:\n\n```bash\npip install fastapi uvicorn sqlalchemy asyncpg alembic pytest pytest-asyncio httpx email-validator python-multipart\n```\n\n### Database Setup\n1. **Install PostgreSQL and pgAdmin**: Ensure you have PostgreSQL and pgAdmin installed on your machine.\n2. **Create a Database**: Create a new database named `fastapi_db` in PostgreSQL.\n3. **Update Database URL**: Modify the database URL in `database.py` with your PostgreSQL credentials.\n\n### SSL Certificate Generation\nGenerate SSL certificates for HTTPS support by running:\n\n```bash\nopenssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365\n```\n\n### Application Structure\nThe application follows best practices for structure and design, including:\n- **Separation of concerns**: Organized into models, schemas, and routers.\n- **Async/await**: Async database operations for better performance.\n- **Comprehensive error handling**: Proper handling of errors throughout the app.\n- **Input validation**: Using Pydantic models to validate input data.\n- **Type hints**: All functions and parameters are typed for clarity and better development experience.\n- **Test coverage**: Includes test cases for all endpoints.\n\n### Key Features\n- **Full CRUD operations** for both Users and Orders.\n- **Async database operations** for improved performance.\n- **Foreign key relationships** between Users and Orders.\n- **Input validation** using Pydantic.\n- **Error handling** for user-friendly responses.\n- **SSL support** for secure communication.\n- **Multiple worker support** via `uvicorn`.\n- **Database constraints** for data integrity.\n- **Comprehensive testing** with `pytest` and `pytest-asyncio`.\n\n### Prerequisites\n- Python 3.8+\n- PostgreSQL\n- FastAPI\n- SQLAlchemy\n- SSL\n- \n\n## Running the Application\n\nTo start the FastAPI application, run the following command:\n\n```bash\npython main.py\n```\n\nThe API will be available at `https://localhost:8000`.\n\n## Running Tests\n\nTo run the test cases for the application, use:\n\n```bash\npytest tests/\n```\n\nThis will execute all tests located in the `tests/` directory.\n\n---\n\n## API Documentation\n![Screenshot (58)](https://github.com/user-attachments/assets/e7e8bf07-335c-4193-91cf-5e83fd3008ce)\n\n### Users API\n\n#### 1. Create User\n- **Endpoint**: `POST /users/`\n- **URL**: `https://localhost:8000/users/`\n- **Request Body**:\n```json\n{\n    \"name\": \"sandesh bhujbal\",\n    \"email\": \"sandeshbhujbal300@gmail.com\"\n}\n```\n- **Success Response** (201 Created):\n```json\n{\n    \"name\": \"sandesh bhujbal\",\n    \"email\": \"sandeshbhujbal300@gmail.com\",\n    \"id\": 1,\n    \"created_at\": \"2024-11-28T09:43:00.712603Z\"\n}\n```\n\n#### 2. Get User\n- **Endpoint**: `GET /users/{id}`\n- **URL**: `https://localhost:8000/users/2`\n- **Success Response** (200 OK):\n```json\n{\n    \"name\": \"sandesh bhujbal\",\n    \"email\": \"sandeshbhujbal300@gmail.com\",\n    \"id\": 1,\n    \"created_at\": \"2024-11-28T09:43:00.712603Z\"\n}\n```\n\n#### 3. Get All Users\n- **Endpoint**: `GET /users`\n- **URL**: `https://localhost:8000/users/`\n- **Success Response** (200 OK):\n```json\n[\n    {\n        \"name\": \"sandesh bhujbal\",\n        \"email\": \"sandeshbhujbal300@gmail.com\",\n        \"id\": 1,\n        \"created_at\": \"2024-11-28T09:43:00.712603Z\"\n    },\n    {\n        \"name\": \"sanket tamhane\",\n        \"email\": \"sankettamhane@gmail.com\",\n        \"id\": 2,\n        \"created_at\": \"2024-11-28T09:46:30.955441Z\"\n    }\n]\n```\n\n#### 4. Update User\n- **Endpoint**: `PUT /users/{id}`\n- **URL**: `https://localhost:8000/users/1`\n- **Request Body**:\n```json\n{\n    \"name\": \"Sandesh Prakash Bhujbal\",\n    \"email\": \"sandeshbhujbal300@gmail.com\"\n}\n```\n- **Success Response** (200 OK):\n```json\n{\n    \"name\": \"Sandesh Prakash Bhujbal\",\n    \"email\": \"sandeshbhujbal300@gmail.com\",\n    \"id\": 1,\n    \"created_at\": \"2024-11-28T09:43:00.712603Z\"\n}\n```\n\n#### 5. Delete User\n- **Endpoint**: `DELETE /users/{id}`\n- **URL**: `https://localhost:8000/users/6`\n- **Success Response** (200 OK):\n```json\n{\n    \"message\": \"User deleted successfully with ID - 6\"\n}\n```\n\n### Orders API\n\n#### 1. Create Order\n- **Endpoint**: `POST /orders`\n- **URL**: `https://localhost:8000/orders`\n- **Request Body**:\n```json\n{\n    \"user_id\": 1,\n    \"product_name\": \"Laptop\",\n    \"quantity\": 2\n}\n```\n- **Success Response** (201 Created):\n```json\n{\n    \"product_name\": \"Laptop\",\n    \"quantity\": 2,\n    \"id\": 1,\n    \"user_id\": 1,\n    \"order_date\": \"2024-11-28T10:03:30.475560Z\"\n}\n```\n\n#### 2. Get Order\n- **Endpoint**: `GET /orders/{id}`\n- **URL**: `https://localhost:8000/orders/1`\n- **Success Response** (200 OK):\n```json\n{\n    \"product_name\": \"Laptop\",\n    \"quantity\": 2,\n    \"id\": 1,\n    \"user_id\": 1,\n    \"order_date\": \"2024-11-28T10:03:30.475560Z\"\n}\n```\n\n#### 3. Get All Orders\n- **Endpoint**: `GET /orders`\n- **URL**: `https://localhost:8000/orders`\n- **Success Response** (200 OK):\n```json\n[\n    {\n        \"product_name\": \"Laptop\",\n        \"quantity\": 2,\n        \"id\": 1,\n        \"user_id\": 1,\n        \"order_date\": \"2024-11-28T10:03:30.475560Z\"\n    },\n    {\n        \"product_name\": \"mobiles\",\n        \"quantity\": 5,\n        \"id\": 2,\n        \"user_id\": 1,\n        \"order_date\": \"2024-11-28T10:05:40.412382Z\"\n    }\n]\n```\n\n#### 4. Update Order\n- **Endpoint**: `PUT /orders/{id}`\n- **URL**: `https://localhost:8000/orders/1`\n- **Request Body**:\n```json\n{\n    \"user_id\": 1,\n    \"product_name\": \"Gaming Laptop\",\n    \"quantity\": 3\n}\n```\n- **Success Response** (200 OK):\n```json\n{\n    \"product_name\": \"Gaming Laptop\",\n    \"quantity\": 3,\n    \"id\": 1,\n    \"user_id\": 1,\n    \"order_date\": \"2024-11-28T10:03:30.475560Z\"\n}\n```\n\n#### 5. Delete Order\n- **Endpoint**: `DELETE /orders/{id}`\n- **URL**: `https://localhost:8000/orders/3`\n- **Success Response** (200 OK):\n```json\n{\n    \"message\": \"Order deleted successfully with ID - 3\"\n}\n```\n---------------------------\n# FastAPI CRUD Application Test Documentation\n\n## Users API Tests\n\n### 1. User Creation Tests\n\n#### 1.1 Successful User Creation\n**Description**: Verifies that a new user can be created successfully with valid data.\n\n**Test Case**: `test_create_user_success`\n```python\n@pytest.mark.asyncio\nasync def test_create_user_success(self, async_client):\n    response = await async_client.post(\n        \"/users/\",\n        json={\"name\": \"Test User\", \"email\": \"test@example.com\"}\n    )\n    assert response.status_code == status.HTTP_201_CREATED\n    data = response.json()\n    assert data[\"name\"] == \"Test User\"\n    assert data[\"email\"] == \"test@example.com\"\n    assert \"id\" in data\n    assert \"created_at\" in data\n```\n\n**Test Result**: \n- **Status**: ✅ PASSED\n- **Observations**: \n  - User creation successful\n  - Returned status code 201\n  - User data correctly saved and returned\n  - ID and timestamp generated as expected\n\n#### 1.2 Duplicate Email Prevention\n**Description**: Verifies that the system prevents creation of users with duplicate emails.\n\n**Test Case**: `test_create_user_duplicate_email`\n```python\n@pytest.mark.asyncio\nasync def test_create_user_duplicate_email(self, async_client):\n    # Create first user\n    await async_client.post(\n        \"/users/\",\n        json={\"name\": \"Test User\", \"email\": \"test@example.com\"}\n    )\n    \n    # Try to create second user with same email\n    response = await async_client.post(\n        \"/users/\",\n        json={\"name\": \"Another User\", \"email\": \"test@example.com\"}\n    )\n    assert response.status_code == status.HTTP_400_BAD_REQUEST\n    assert \"Email already registered\" in response.json()[\"detail\"]\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - Duplicate email creation blocked\n  - Returned status code 400\n  - Appropriate error message displayed\n  - Database integrity maintained\n\n### 2. User Retrieval Tests\n\n#### 2.1 Successful User Retrieval\n**Description**: Verifies that an existing user can be retrieved by ID.\n\n**Test Case**: `test_get_user_success`\n```python\n@pytest.mark.asyncio\nasync def test_get_user_success(self, async_client):\n    # Create user\n    create_response = await async_client.post(\n        \"/users/\",\n        json={\"name\": \"Test User\", \"email\": \"test@example.com\"}\n    )\n    user_id = create_response.json()[\"id\"]\n\n    # Get user\n    response = await async_client.get(f\"/users/{user_id}\")\n    assert response.status_code == status.HTTP_200_OK\n    data = response.json()\n    assert data[\"name\"] == \"Test User\"\n    assert data[\"email\"] == \"test@example.com\"\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - User successfully retrieved\n  - Returned status code 200\n  - User details match created user\n\n#### 2.2 Non-existent User Retrieval\n**Description**: Verifies proper handling of requests for non-existent users.\n\n**Test Case**: `test_get_user_not_found`\n```python\n@pytest.mark.asyncio\nasync def test_get_user_not_found(self, async_client):\n    response = await async_client.get(\"/users/999\")\n    assert response.status_code == status.HTTP_404_NOT_FOUND\n    assert \"User not found\" in response.json()[\"detail\"]\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - Non-existent user request handled correctly\n  - Returned status code 404\n  - Appropriate error message displayed\n\n### 3. User Update Tests\n\n#### 3.1 Successful User Update\n**Description**: Verifies that an existing user's information can be updated.\n\n**Test Case**: `test_update_user_success`\n```python\n@pytest.mark.asyncio\nasync def test_update_user_success(self, async_client):\n    # Create user\n    create_response = await async_client.post(\n        \"/users/\",\n        json={\"name\": \"Test User\", \"email\": \"test@example.com\"}\n    )\n    user_id = create_response.json()[\"id\"]\n\n    # Update user\n    response = await async_client.put(\n        f\"/users/{user_id}\",\n        json={\"name\": \"Updated Name\", \"email\": \"updated@example.com\"}\n    )\n    assert response.status_code == status.HTTP_200_OK\n    data = response.json()\n    assert data[\"name\"] == \"Updated Name\"\n    assert data[\"email\"] == \"updated@example.com\"\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - User successfully updated\n  - Returned status code 200\n  - Name and email correctly modified\n\n### 4. User Deletion Tests\n\n#### 4.1 Successful User Deletion\n**Description**: Verifies that a user can be deleted successfully.\n\n**Test Case**: `test_delete_user_success`\n```python\n@pytest.mark.asyncio\nasync def test_delete_user_success(self, async_client):\n    # Create user\n    create_response = await async_client.post(\n        \"/users/\",\n        json={\"name\": \"Test User\", \"email\": \"test@example.com\"}\n    )\n    user_id = create_response.json()[\"id\"]\n\n    # Delete user\n    response = await async_client.delete(f\"/users/{user_id}\")\n    assert response.status_code == status.HTTP_204_NO_CONTENT\n\n    # Verify user is deleted\n    get_response = await async_client.get(f\"/users/{user_id}\")\n    assert get_response.status_code == status.HTTP_404_NOT_FOUND\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - User successfully deleted\n  - Returned status code 204\n  - Subsequent retrieval returns 404\n  - User completely removed from system\n\n## Orders API Tests\n\n### 1. Order Creation Tests\n\n#### 1.1 Successful Order Creation\n**Description**: Verifies that a new order can be created successfully.\n\n**Test Case**: `test_create_order_success`\n```python\n@pytest.mark.asyncio\nasync def test_create_order_success(self, async_client, test_user):\n    response = await async_client.post(\n        \"/orders/\",\n        json={\n            \"user_id\": test_user[\"id\"],\n            \"product_name\": \"Test Product\",\n            \"quantity\": 1\n        }\n    )\n    assert response.status_code == status.HTTP_201_CREATED\n    data = response.json()\n    assert data[\"product_name\"] == \"Test Product\"\n    assert data[\"quantity\"] == 1\n    assert data[\"user_id\"] == test_user[\"id\"]\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - Order created successfully\n  - Returned status code 201\n  - Order details correctly saved\n  - User association maintained\n\n#### 1.2 Invalid User Order Creation\n**Description**: Verifies that orders cannot be created for non-existent users.\n\n**Test Case**: `test_create_order_invalid_user`\n```python\n@pytest.mark.asyncio\nasync def test_create_order_invalid_user(self, async_client):\n    response = await async_client.post(\n        \"/orders/\",\n        json={\n            \"user_id\": 999,\n            \"product_name\": \"Test Product\",\n            \"quantity\": 1\n        }\n    )\n    assert response.status_code == status.HTTP_404_NOT_FOUND\n    assert \"User not found\" in response.json()[\"detail\"]\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - Invalid user order creation blocked\n  - Returned status code 404\n  - Appropriate error message displayed\n\n#### 1.3 Invalid Quantity Order Creation\n**Description**: Verifies quantity validation for order creation.\n\n**Test Case**: `test_create_order_invalid_quantity`\n```python\n@pytest.mark.asyncio\nasync def test_create_order_invalid_quantity(self, async_client, test_user):\n    response = await async_client.post(\n        \"/orders/\",\n        json={\n            \"user_id\": test_user[\"id\"],\n            \"product_name\": \"Test Product\",\n            \"quantity\": 0  # Invalid quantity\n        }\n    )\n    assert response.status_code == status.HTTP_400_BAD_REQUEST\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - Invalid quantity order creation blocked\n  - Returned status code 400\n  - Quantity validation working correctly\n\n### 2. Order Retrieval Tests\n\n#### 2.1 Successful Order Retrieval\n**Description**: Verifies that an existing order can be retrieved.\n\n**Test Case**: `test_get_order_success`\n```python\n@pytest.mark.asyncio\nasync def test_get_order_success(self, async_client, test_user):\n    # Create order\n    create_response = await async_client.post(\n        \"/orders/\",\n        json={\n            \"user_id\": test_user[\"id\"],\n            \"product_name\": \"Test Product\",\n            \"quantity\": 1\n        }\n    )\n    order_id = create_response.json()[\"id\"]\n\n    # Get order\n    response = await async_client.get(f\"/orders/{order_id}\")\n    assert response.status_code == status.HTTP_200_OK\n    data = response.json()\n    assert data[\"product_name\"] == \"Test Product\"\n    assert data[\"quantity\"] == 1\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - Order retrieved successfully\n  - Returned status code 200\n  - Order details match created order\n\n### 3. Order Update Tests\n\n#### 3.1 Successful Order Update\n**Description**: Verifies that an existing order can be updated.\n\n**Test Case**: `test_update_order_success`\n```python\n@pytest.mark.asyncio\nasync def test_update_order_success(self, async_client, test_user):\n    # Create order\n    create_response = await async_client.post(\n        \"/orders/\",\n        json={\n            \"user_id\": test_user[\"id\"],\n            \"product_name\": \"Test Product\",\n            \"quantity\": 1\n        }\n    )\n    order_id = create_response.json()[\"id\"]\n\n    # Update order\n    response = await async_client.put(\n        f\"/orders/{order_id}\",\n        json={\n            \"product_name\": \"Updated Product\",\n            \"quantity\": 2\n        }\n    )\n    assert response.status_code == status.HTTP_200_OK\n    data = response.json()\n    assert data[\"product_name\"] == \"Updated Product\"\n    assert data[\"quantity\"] == 2\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - Order updated successfully\n  - Returned status code 200\n  - Product name and quantity modified correctly\n\n### 4. Order Deletion Tests\n\n#### 4.1 Successful Order Deletion\n**Description**: Verifies that an order can be deleted successfully.\n\n**Test Case**: `test_delete_order_success`\n```python\n@pytest.mark.asyncio\nasync def test_delete_order_success(self, async_client, test_user):\n    # Create order\n    create_response = await async_client.post(\n        \"/orders/\",\n        json={\n            \"user_id\": test_user[\"id\"],\n            \"product_name\": \"Test Product\",\n            \"quantity\": 1\n        }\n    )\n    order_id = create_response.json()[\"id\"]\n\n    # Delete order\n    response = await async_client.delete(f\"/orders/{order_id}\")\n    assert response.status_code == status.HTTP_204_NO_CONTENT\n```\n\n**Test Result**:\n- **Status**: ✅ PASSED\n- **Observations**:\n  - Order deleted successfully\n  - Returned status code 204\n  - Order removed from system\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandesh300%2Ffastapi-crud-operations-application","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandesh300%2Ffastapi-crud-operations-application","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandesh300%2Ffastapi-crud-operations-application/lists"}