django-admin-autoapi 0.1.2
Zero-config REST API generation for Django Admin
License: MIT
Requires Python: >=3.11
Keywords: django, admin, rest, api, automatic, zero-config

<div align="center">
<img src="https://gitlab.com/chrisspen/django-admin-autoapi/-/raw/master/assets/logo-clear2-medium.png" alt="django-admin-autoapi logo">
</div>


# django-admin-autoapi

Zero-configuration REST API generation for Django Admin. Automatically expose your admin-registered models via a REST API with token authentication and Django model permissions.

## Features

- **Zero Configuration**: Models registered with the admin are automatically available via REST API
- **Token Authentication**: Uses Django REST Framework's token authentication
- **Permission Integration**: Leverages Django's built-in model permissions (view, add, change, delete)
- **Field Selection**: Request only the fields you need with `?fields=name,email`
- **Filtering**: Filter querysets with query parameters like `?status=published`
- **Ordering**: Sort results with `?order_by=name` or `?order_by=-created_at`
- **Pagination**: Built-in pagination with configurable page size
- **Calculated Fields**: Expose model properties via `api_calculated_fields`

## Installation

```bash
pip install django-admin-autoapi
```

Add to your `INSTALLED_APPS`:

```python
INSTALLED_APPS = [
    # Django apps
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    # ...

    # Required
    "rest_framework",
    "rest_framework.authtoken",
    "django_admin_autoapi",

    # Your apps
    "myapp",
]
```

Configure Django REST Framework:

```python
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.TokenAuthentication",
        "rest_framework.authentication.SessionAuthentication",
    ],
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticated",
    ],
    "PAGE_SIZE": 25,
}
```

## Usage

### Basic Setup

Replace Django's default admin site with the AutoAPI admin site:

```python
# myapp/admin.py
from django.contrib import admin
from django_admin_autoapi.sites import site

from .models import Author, Book

# Register models with the AutoAPI admin site
site.register(Author)
site.register(Book)
```

Update your URL configuration:

```python
# urls.py
from django_admin_autoapi.sites import site

urlpatterns = [
    path("admin/", site.urls),
]
```

That's it! Your models are now available via REST API at:

- `GET /admin/api/` - List all available endpoints
- `GET /admin/api/myapp/author/` - List authors
- `GET /admin/api/myapp/author/123/` - Retrieve author 123
- `POST /admin/api/myapp/author/` - Create author
- `PATCH /admin/api/myapp/author/123/` - Update author 123
- `DELETE /admin/api/myapp/author/123/` - Delete author 123

### Authentication

Get a token for a user:

```bash
# Create a token (in Django shell or via management command)
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=user)
```

Use the token in API requests:

```bash
curl -H "Authorization: Token your-token-here" \
     http://localhost:8000/admin/api/myapp/author/
```

### Field Selection

Request only specific fields:

```bash
# Only get id, name, and email
curl -H "Authorization: Token ..." \
     "http://localhost:8000/admin/api/myapp/author/?fields=name,email"
```

### Filtering

Filter results with query parameters:

```bash
# Filter by status
curl -H "Authorization: Token ..." \
     "http://localhost:8000/admin/api/myapp/book/?status=published"

# Filter by related field
curl -H "Authorization: Token ..." \
     "http://localhost:8000/admin/api/myapp/book/?author=123"

# Django-style lookups
curl -H "Authorization: Token ..." \
     "http://localhost:8000/admin/api/myapp/book/?title__contains=Django"
```

### Ordering

Sort results:

```bash
# Sort by name ascending
curl -H "Authorization: Token ..." \
     "http://localhost:8000/admin/api/myapp/author/?order_by=name"

# Sort by created_at descending
curl -H "Authorization: Token ..." \
     "http://localhost:8000/admin/api/myapp/author/?order_by=-created_at"

# Multiple fields
curl -H "Authorization: Token ..." \
     "http://localhost:8000/admin/api/myapp/book/?order_by=author,-title"
```

### Calculated Fields

Expose model properties in the API:

```python
class Author(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    email = models.EmailField()

    # List properties to expose via API
    api_calculated_fields = ["full_name", "display_name"]

    @property
    def full_name(self):
        return f"{self.first_name} {self.last_name}"

    @property
    def display_name(self):
        return f"{self.full_name} <{self.email}>"
```

### Custom Admin Classes

Use the mixin with custom ModelAdmin classes:

```python
from django.contrib import admin
from django_admin_autoapi.sites import site
from django_admin_autoapi.mixins import AutoAPIMixin

class AuthorAdmin(AutoAPIMixin, admin.ModelAdmin):
    list_display = ["name", "email", "is_active"]
    list_filter = ["is_active"]
    search_fields = ["name", "email"]

site.register(Author, AuthorAdmin)
```

### Read-Only API

For read-only API access, use the read-only mixin:

```python
from django_admin_autoapi.mixins import ReadOnlyAutoAPIMixin

class ReportAdmin(ReadOnlyAutoAPIMixin, admin.ModelAdmin):
    list_display = ["title", "created_at"]

site.register(Report, ReportAdmin)
```

## Permissions

The API respects Django's built-in model permissions:

| HTTP Method | Required Permission |
|------------|---------------------|
| GET | `app.view_model` |
| POST | `app.add_model` |
| PUT/PATCH | `app.change_model` |
| DELETE | `app.delete_model` |

Users must have `is_staff=True` and the appropriate permissions to access the API.

## Pagination

Responses are paginated by default:

```json
{
    "count": 100,
    "next": "http://localhost:8000/admin/api/myapp/author/?page=2",
    "previous": null,
    "results": [
        {"id": 1, "name": "Author 1", ...},
        {"id": 2, "name": "Author 2", ...},
        ...
    ]
}
```

Configure pagination in settings:

```python
REST_FRAMEWORK = {
    "PAGE_SIZE": 25,  # Default items per page
    "MAX_PAGE_SIZE": 1000,  # Maximum items per page
}
```

Request a specific page size:

```bash
curl "http://localhost:8000/admin/api/myapp/author/?limit=50"
```

## API Index

Get a list of all available endpoints:

```bash
curl -H "Authorization: Token ..." \
     http://localhost:8000/admin/api/
```

Response:

```json
{
    "endpoints": [
        {
            "model": "myapp.author",
            "list_url": "/admin/api/myapp/author/",
            "detail_url": "/admin/api/myapp/author/<pk>/",
            "verbose_name": "author",
            "verbose_name_plural": "authors"
        },
        ...
    ],
    "count": 5
}
```

## Configuration

### Custom Admin Site Name

```python
from django_admin_autoapi.sites import AutoAPIAdminSite

site = AutoAPIAdminSite(name="myadmin")
```

### Disable API for Specific Models

Register with the standard Django admin instead of the AutoAPI site:

```python
from django.contrib import admin
from django_admin_autoapi.sites import site

# This model gets an API
site.register(PublicModel)

# This model doesn't get an API
admin.site.register(InternalModel)
```

## Requirements

- Python 3.11+
- Django 4.2+
- Django REST Framework 3.14+

## Development

Run tests across Python and Django versions:

```bash
./test.sh
```

Or run a specific environment:

```bash
./test.sh -e py312-django50
```

Available test environments:
- `py311-django42` - Python 3.11 + Django 4.2
- `py311-django50` - Python 3.11 + Django 5.0
- `py312-django42` - Python 3.12 + Django 4.2
- `py312-django50` - Python 3.12 + Django 5.0

## License

MIT License - see LICENSE file for details.

## Contributing

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