Metadata-Version: 2.4
Name: rango-api
Version: 0.1.0
Summary: A modern Python web framework built on FastAPI with Django-like features and structure
Home-page: https://github.com/reshadMajumder/rango
Author: Jahidul Hassan Reshad
Author-email: Jahidul Hassan Reshad <hassanjahidul365@gmail.com>
License: MIT License
        
        Copyright (c) 2025 Jahidul Hassan Reshad
        
        
        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.
        
        
Project-URL: Homepage, https://github.com/reshadMajumder/rango
Project-URL: Documentation, https://github.com/reshadMajumder/rango#readme
Project-URL: Repository, https://github.com/reshadMajumder/rango
Project-URL: Issues, https://github.com/reshadMajumder/rango
Keywords: web,framework,fastapi,api,django-like
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aerich==0.9.2
Requires-Dist: aiosqlite==0.21.0
Requires-Dist: annotated-types==0.7.0
Requires-Dist: anyio==4.11.0
Requires-Dist: asyncclick==8.3.0.7
Requires-Dist: click==8.3.0
Requires-Dist: colorama==0.4.6
Requires-Dist: dictdiffer==0.9.0
Requires-Dist: fastapi==0.119.0
Requires-Dist: h11==0.16.0
Requires-Dist: idna==3.10
Requires-Dist: iso8601==2.1.0
Requires-Dist: markdown-it-py==4.0.0
Requires-Dist: mdurl==0.1.2
Requires-Dist: pydantic==2.12.0
Requires-Dist: pydantic_core==2.41.1
Requires-Dist: Pygments==2.19.2
Requires-Dist: pypika-tortoise==0.6.2
Requires-Dist: pytz==2025.2
Requires-Dist: rich==14.2.0
Requires-Dist: shellingham==1.5.4
Requires-Dist: sniffio==1.3.1
Requires-Dist: starlette==0.48.0
Requires-Dist: tortoise-orm==0.25.1
Requires-Dist: typer==0.19.2
Requires-Dist: typing-inspection==0.4.2
Requires-Dist: typing_extensions==4.15.0
Requires-Dist: uvicorn==0.37.0
Provides-Extra: dev
Requires-Dist: pytest>=6.0; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# Rango API Framework

A modern Python web framework built on FastAPI with Django-like features for rapid API development.

## Features

- **FastAPI Integration**: Built on top of FastAPI for high performance and automatic API documentation
- **Django-like Structure**: Familiar project and app structure similar to Django
- **ORM Integration**: Built-in Tortoise ORM support with migrations
- **Generic Views**: Pre-built views for common CRUD operations
- **Serializers**: Django REST Framework-like serializers
- **CLI Tools**: Command-line interface for project management
- **CORS Middleware**: Built-in CORS support

## Installation

```bash
pip install rango-api
```

## Quick Start

### 1. Create a new project

```bash
rango startproject myproject
cd myproject
```

### 2. Create an app

```bash
rango startapp blog
```






### Initialize database
Init Aerich config

```bash

aerich init -t project.settings.TORTOISE_ORM
```
Create database & initial migration

```bash

aerich init-db
```
Make migrations after changing models

```bash

aerich migrate --name "initial"
aerich upgrade
```

Every time you create or modify models:
 aerich migrate --name "your_message" → aerich upgrade






### 3. Run migrations

```bash
rango makemigrations
rango migrate
```

### 4. Start the development server

```bash
rango runserver
```

## Tutorial

### Create models with ForeignKey

```python
from tortoise import fields, models

class Category(models.Model):
    id = fields.IntField(pk=True)
    name = fields.CharField(max_length=100)

class Product(models.Model):
    id = fields.IntField(pk=True)
    title = fields.CharField(max_length=255)
    category = fields.ForeignKeyField('models.Category', related_name='products')
```

### Serializers (nested FK supported)

```python
from rango_api.serializers import ModelSerializer
from .models import Category, Product

class CategorySerializer(ModelSerializer):
    class Meta:
        model = Category
        fields = ["id", "name"]

class ProductSerializer(ModelSerializer):
    class Meta:
        model = Product
        fields = ["id", "title", "category"]  # can send category or category_id
        nested_serializers = {
            'Category': CategorySerializer
        }
```

### Views (generic, with FK optimization)

```python
from rango_api.generics import ListCreateView, RetrieveUpdateDeleteView
from .models import Product
from .serializers import ProductSerializer

class ProductListCreateView(ListCreateView):
    model = Product
    serializer_class = ProductSerializer
    select_related = ['category']  # optimize FK

class ProductDetailView(RetrieveUpdateDeleteView):
    model = Product
    serializer_class = ProductSerializer
    select_related = ['category']
```

### URLs

```python
from rango_api.router import Router
from .views import ProductListCreateView, ProductDetailView

router = Router()
router.add("/products", ProductListCreateView, methods=["GET", "POST"])
router.add("/products/{id}", ProductDetailView, methods=["GET", "PUT", "PATCH", "DELETE"])
```

### Test the API

- Create category:
```bash
curl -X POST http://127.0.0.1:8000/categories \
  -H "Content-Type: application/json" \
  -d '{"name":"Electronics"}'
```

- Create product (supports category or category_id):
```bash
curl -X POST http://127.0.0.1:8000/products \
  -H "Content-Type: application/json" \
  -d '{"title":"Phone","category":1}'
```

## Extensibility (DRF-like Hooks)

You can override hooks in generic views to customize behavior:

```python
class ProductListCreateView(ListCreateView):
    model = Product
    serializer_class = ProductSerializer

    def get_queryset(self, request):
        return self.model.all().select_related('category')

    async def before_create(self, request, data: dict) -> dict:
        # mutate/validate incoming data
        data.setdefault("title", data.get("title", "Untitled"))
        return data

    async def after_create(self, request, obj):
        # side-effects, logging, etc.
        return obj

class ProductDetailView(RetrieveUpdateDeleteView):
    model = Product
    serializer_class = ProductSerializer

    async def before_update(self, request, obj, data: dict) -> dict:
        # e.g. normalize FK input
        if 'category' in data and 'category_id' not in data:
            data['category_id'] = data.pop('category')
        return data
```

Available hooks include: `get_queryset`, `filter_queryset`, `before_create`, `perform_create`, `after_create`, `before_update`, `perform_update`, `after_update`, `before_delete`, `perform_delete`, `after_delete`.

## Project Structure

```
myproject/
├── apps/
│   └── blog/
│       ├── models.py
│       ├── serializers.py
│       ├── views.py
│       └── urls.py
├── project/
│   ├── settings.py
│   ├── urls.py
│   ├── views.py
│   └── asgi.py
├── main.py
└── manage.py
```

## Basic Usage

### Models

```python
from tortoise import fields, models

class Post(models.Model):
    title = fields.CharField(max_length=255)
    content = fields.TextField()
    created_at = fields.DatetimeField(auto_now_add=True)
```

### Serializers

```python
from rango_api.serializers import ModelSerializer
from .models import Post

class PostSerializer(ModelSerializer):
    class Meta:
        model = Post
        fields = ["id", "title", "content", "created_at"]
```

### Views

```python
from rango_api.generics import ListCreateView, RetrieveUpdateDeleteView
from .models import Post
from .serializers import PostSerializer

class PostListCreateView(ListCreateView):
    model = Post
    serializer_class = PostSerializer

class PostDetailView(RetrieveUpdateDeleteView):
    model = Post
    serializer_class = PostSerializer
```

### URLs

```python
from rango_api.router import Router
from .views import PostListCreateView, PostDetailView

router = Router()
router.add("/posts", PostListCreateView, methods=["GET", "POST"])
router.add("/posts/{id}", PostDetailView, methods=["GET", "PUT", "DELETE"])
```

## CLI Commands

- `rango startproject <name>` - Create a new project
- `rango startapp <name>` - Create a new app
- `rango makemigrations [message]` - Create database migrations
- `rango migrate` - Apply database migrations
- `rango runserver [host] [port]` - Start development server

## Requirements

- Python 3.8+
- FastAPI
- Tortoise ORM
- Uvicorn

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Support

If you have any questions or need help, please open an issue on GitHub.
