Skip to content

AvgDeftonesEnjoyer/TravelProject

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Travel Planner API

API for managing travel projects and places to visit. The system integrates with Art Institute of Chicago API for validation and retrieving information about places.

Features

  • CRUD operations for travel projects
  • Managing places in projects (up to 10 places per project)
  • Integration with Art Institute of Chicago API
  • Place validation through external API
  • Automatic tracking of project completion status
  • JWT authentication for all endpoints
  • Caching of external API requests
  • OpenAPI/Swagger documentation
  • Pagination and filtering

Requirements

  • Python 3.11+
  • PostgreSQL
  • Docker and Docker Compose (optional)

Installation

Local Installation

  1. Clone the repository:
git clone <repository-url>
cd TravelProject
  1. Create a virtual environment:
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
  1. Install dependencies:
pip install -r requirements.txt
  1. Create a .env file in the project root:
SECRET_KEY=your-secret-key-here
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1
DB_NAME=travel_db
DB_USER=postgres
DB_PASSWORD=postgres
DB_HOST=localhost
DB_PORT=5432
  1. Run migrations:
cd config
python manage.py migrate
  1. Start the development server:
python manage.py runserver

Running with Docker

  1. Make sure the .env file is created (see above)

  2. Start the containers:

cd docker
docker-compose up --build

API will be available at http://localhost:8000

Authentication

All API endpoints require JWT authentication.

Register New User

POST /api/register/
Content-Type: application/json

{
  "username": "newuser",
  "email": "user@example.com",
  "password": "securepassword123",
  "password_confirm": "securepassword123"
}

Response:

{
  "message": "User created successfully",
  "username": "newuser",
  "email": "user@example.com"
}

Get Access Token

POST /api/token/
Content-Type: application/json

{
  "username": "your_username",
  "password": "your_password"
}

Response:

{
  "access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
  "refresh": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}

Refresh Access Token

POST /api/token/refresh/
Content-Type: application/json

{
  "refresh": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}

Using Token in Requests

Include the token in the Authorization header:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...

Alternative: Create User via Django Admin

You can also create users via Django admin:

cd config
python manage.py createsuperuser

Then access admin panel at /admin/

API Endpoints

Note: All endpoints below require JWT authentication.

Projects

  • GET /api/projects/ - List projects (with pagination and filtering)
  • POST /api/projects/ - Create project (can include array of places)
  • GET /api/projects/{id}/ - Get project
  • PUT /api/projects/{id}/ - Update project
  • PATCH /api/projects/{id}/ - Partial update of project
  • DELETE /api/projects/{id}/ - Delete project (not allowed if any places are visited)

Places

  • GET /api/projects/{project_id}/places/ - List project places
  • POST /api/projects/{project_id}/places/ - Add place to project
  • GET /api/projects/{project_id}/places/{id}/ - Get place
  • PUT /api/projects/{project_id}/places/{id}/ - Update place
  • PATCH /api/projects/{project_id}/places/{id}/ - Partial update of place
  • DELETE /api/projects/{project_id}/places/{id}/ - Delete place
  • GET /api/places/search-artworks/?query=monet&limit=10 - Search artworks in Art Institute API to find external_id (doesn't require project)

Documentation

  • GET /api/docs/ - Swagger UI documentation (includes authentication)
  • GET /api/redoc/ - ReDoc documentation
  • GET /api/schema/ - OpenAPI schema

How to Get external_id

The external_id is the artwork ID from Art Institute of Chicago API. You can get it in several ways:

1. Search via API endpoint (Recommended)

GET /api/places/search-artworks/?query=monet&limit=10
Authorization: Bearer <your_token>

This will return a list of artworks with their IDs. Use the id field as external_id.

2. Direct API call to Art Institute

GET https://api.artic.edu/api/v1/artworks/search?q=monet&limit=10

Response includes artworks with id field - use this as external_id.

3. Example external_id values

You can test with these valid IDs:

  • 27992 - Example artwork
  • 25865 - Example artwork
  • 16571 - Example artwork

Request Examples

Important: All requests require JWT token in the Authorization header:

Authorization: Bearer <your_access_token>

Creating a project without places

POST /api/projects/
Content-Type: application/json
Authorization: Bearer <your_token>

{
  "name": "Trip to Chicago",
  "description": "Exploring art museums",
  "start_date": "2024-06-01"
}

Creating a project with places

POST /api/projects/
Content-Type: application/json
Authorization: Bearer <your_token>

{
  "name": "Trip to Chicago",
  "description": "Exploring art museums",
  "start_date": "2024-06-01",
  "places_data": [
    {
      "external_id": "27992",
      "notes": "Must see this artwork"
    },
    {
      "external_id": "25865",
      "notes": "Interesting piece"
    }
  ]
}

Adding a place to a project

POST /api/projects/1/places/
Content-Type: application/json
Authorization: Bearer <your_token>

{
  "external_id": "27992",
  "notes": "Additional notes about this place"
}

Note: The external_id must exist in Art Institute of Chicago API. Use /api/places/search-artworks/ to find valid IDs.

Updating place notes

PATCH /api/projects/1/places/1/
Content-Type: application/json
Authorization: Bearer <your_token>

{
  "notes": "Updated notes"
}

Note: The 1 in /places/1/ is the place ID (not external_id). Get it from the list of places endpoint.

Marking a place as visited

PATCH /api/projects/1/places/1/
Content-Type: application/json
Authorization: Bearer <your_token>

{
  "is_visited": true
}

When all places in a project are marked as visited, the project is automatically marked as completed.

Business Rules

  1. Place limit: A project can contain up to 10 places (can be created without places)
  2. Uniqueness: A place with the same external_id can be added to a project only once
  3. Place validation: Before adding, a place is validated through Art Institute API
  4. Project deletion: A project cannot be deleted if at least one place is marked as visited
  5. Project completion: A project is automatically marked as completed when all places are visited

Filtering and Search

Project filtering

  • ?is_completed=true - Only completed projects
  • ?is_completed=false - Only incomplete projects
  • ?start_date=2024-01-01 - Projects with specific start date
  • ?search=chicago - Search by name or description
  • ?ordering=-created_at - Sorting (default: newest first)

Testing

Run tests:

cd config
python manage.py test

Note: Tests use JWT authentication. A test user is automatically created in setUp() method with JWT token for each test case.

Project Structure

TravelProject/
├── app/
│   ├── projects/              # Projects app
│   │   ├── models.py          # Project model
│   │   ├── serializers.py     # Project serializers
│   │   ├── views.py           # ProjectViewSet, UserRegistrationView
│   │   ├── urls.py            # Project routes
│   │   ├── validators.py      # Business logic validators
│   │   ├── auth_serializers.py  # User registration serializer
│   │   └── tests.py           # Project tests
│   └── places/                # Places app
│       ├── models.py          # ProjectPlace model
│       ├── serializers.py     # Place serializers
│       ├── views.py           # ProjectPlaceViewSet, SearchArtworksView
│       ├── urls.py            # Place routes (nested)
│       ├── services.py        # Art Institute API service
│       ├── validators.py      # Place validators
│       └── tests.py           # Place tests
├── config/                    # Django settings
│   ├── config/
│   │   ├── settings.py        # Django settings
│   │   ├── urls.py            # Main URL configuration
│   │   ├── wsgi.py
│   │   └── asgi.py
│   └── manage.py
├── docker/                    # Docker configuration
│   ├── Dockerfile
│   └── docker-compose.yml
├── static/                    # Static files
├── media/                     # Media files
├── README.md                  # Project documentation
├── requirements.txt           # Python dependencies
└── Travel_Planner_API.postman_collection.json  # Postman collection

Technologies

  • Django 5.2.11
  • Django REST Framework 3.16.1
  • Django REST Framework Simple JWT 5.3.1 (authentication)
  • PostgreSQL (via psycopg2-binary)
  • drf-spectacular 0.29.0 (OpenAPI documentation)
  • django-filter 25.2 (filtering)
  • djangorestframework-nested 0.1.6 (nested routes)
  • requests 2.32.5 (HTTP client for external API)
  • python-dotenv 1.2.1 (environment variables)

Postman Collection

Import the Travel_Planner_API.postman_collection.json file into Postman to test all endpoints.

The collection includes:

  • Authentication endpoints (register, token, refresh)
  • All project endpoints with JWT authentication
  • All place endpoints with JWT authentication
  • Search artworks endpoint
  • Automatic token management (tokens are saved to variables)

Setup:

  1. Import the collection
  2. Set base_url variable to http://localhost:8000 (or your server URL)
  3. Run "Register User" or "Get Access Token" first
  4. Tokens will be automatically saved and used for subsequent requests

Environment Variables

Required environment variables in .env file:

# Django Settings
SECRET_KEY=your-secret-key-here
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1,0.0.0.0

# Database Settings
DB_NAME=travel_db
DB_USER=postgres
DB_PASSWORD=postgres
DB_HOST=localhost  # Use 'db' for Docker
DB_PORT=5432

License

This project was created for a test assignment.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages