# django-drf

Skill for building REST APIs on Django with ViewSets, serializers, and filters following Prowler standards. Use it when coding endpoints with RLS, JSON:API, and OpenAPI docs.

- skill · `type=skill` · Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode · 482 installs · ★ 15093
- Author: prowler-cloud
- License: Apache-2.0 · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/prowler-cloud/prowler/tree/HEAD/skills/django-drf/SKILL.md
- Updated: 2026-10-25
- HTML: https://affpapa.org/en/nevibecode/skills/django-drf

## What it does

django-drf provides ready patterns for DRF tasks: separate serializers by operation (Read, Create, Update, Include), use `filterset_class` instead of simple filters, avoid N+1 with `select_related` and `prefetch_related`. The skill auto-triggers when you create ViewSets, serializers, or filters in the `api/` directory.

Inside is a 9-step checklist (models → ViewSet → serializers → filters → permissions → pagination → routing → schema → tests), decision trees to pick base classes, and examples: how to mask sensitive data in `to_representation()`, write `@extend_schema_field` for OpenAPI, handle `swagger_fake_view` during schema generation.

Requires Python, Django, and `drf-spectacular` for docs. For Prowler-specific RLS and RBAC logic, reach for the separate `prowler-api` skill.

## Install

### Claude Code (native platform)

1. **Skills CLI (Vercel)**
```bash
npx skills add prowler-cloud/prowler --skill django-drf -a claude-code
```

2. **Manually: put the files in place**
- File: `~/.claude/skills/django-drf/SKILL.md` — Copy the whole skill folder; for one project use .claude/skills/django-drf/

### Codex

1. **Skills CLI (Vercel)**
```bash
npx skills add prowler-cloud/prowler --skill django-drf -a codex
```

2. **Manually: put the files in place**
- File: `.agents/skills/django-drf/SKILL.md` — For all projects use ~/.agents/skills/

### Cursor

1. **Skills CLI (Vercel)**
```bash
npx skills add prowler-cloud/prowler --skill django-drf -a cursor
```

2. **Manually: put the files in place**
- File: `.cursor/skills/django-drf/SKILL.md` — Cursor also reads .agents/skills/ and .claude/skills/

### GitHub Copilot

1. **GitHub CLI**
```bash
gh skill install prowler-cloud/prowler django-drf
```

2. **Manually: put the files in place**
- File: `.github/skills/django-drf/SKILL.md`

### Gemini CLI

1. **Skills CLI (Vercel)**
```bash
npx skills add prowler-cloud/prowler --skill django-drf -a gemini-cli
```

2. **Platform CLI**
```bash
gemini skills install https://github.com/prowler-cloud/prowler --path skills/django-drf
```

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/skills/django-drf/SKILL.md` — The legacy .windsurf/skills/ path still works

### OpenCode

**Skills CLI (Vercel)**
```bash
npx skills add prowler-cloud/prowler --skill django-drf -a opencode
```

### Claude.ai

**Claude.ai**
- Zip the folder and upload it in Settings → Capabilities → Skills

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/prowler-cloud/prowler/tree/HEAD/skills/django-drf/SKILL.md

## When to use it
- Prevent N+1 queries in get_queryset()
- Write separate serializers for read, create, and update operations
- Set up filtering via filterset_class instead of simple fields
- Document SerializerMethodField in OpenAPI schema
- Mask API keys and sensitive data in responses

## Example prompts
- Create a ViewSet for the Provider model with RLS
- Write a POST serializer that validates unknown fields
- Add pagination and provider filtering to the scans list

## Source text · SKILL.md · Apache-2.0

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: 14bdd1aade0c5d54.

BEGIN THIRD-PARTY FILE 14bdd1aade0c5d54
````text
---
name: django-drf
description: >
  Django REST Framework patterns.
  Trigger: When implementing generic DRF APIs (ViewSets, serializers, routers, permissions, filtersets). For Prowler API specifics (RLS/RBAC/Providers), also use prowler-api.
license: Apache-2.0
metadata:
  author: prowler-cloud
  version: "1.2.0"
  scope: [root, api]
  auto_invoke:
    - "Creating ViewSets, serializers, or filters in api/"
    - "Implementing JSON:API endpoints"
    - "Adding DRF pagination or permissions"
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
---

## Critical Patterns

- ALWAYS separate serializers by operation: Read / Create / Update / Include
- ALWAYS use `filterset_class` for complex filtering (not `filterset_fields`)
- ALWAYS validate unknown fields in write serializers (inherit `BaseWriteSerializer`)
- ALWAYS use `select_related`/`prefetch_related` in `get_queryset()` to avoid N+1
- ALWAYS handle `swagger_fake_view` in `get_queryset()` for schema generation
- ALWAYS use `@extend_schema_field` for OpenAPI docs on `SerializerMethodField`
- NEVER put business logic in serializers - use services/utils
- NEVER use auto-increment PKs - use UUIDv4 or UUIDv7
- NEVER use trailing slashes in URLs (`trailing_slash=False`)

> **Note:** `swagger_fake_view` is specific to **drf-spectacular** for OpenAPI schema generation.

---

## Implementation Checklist

When implementing a new endpoint, review these patterns in order:

| # | Pattern | Reference | Key Points |
|---|---------|-----------|------------|
| 1 | **Models** | `api/models.py` | UUID PK, `inserted_at`/`updated_at`, `JSONAPIMeta.resource_name` |
| 2 | **ViewSets** | `api/base_views.py`, `api/v1/views.py` | Inherit `BaseRLSViewSet`, `get_queryset()` with N+1 prevention |
| 3 | **Serializers** | `api/v1/serializers.py` | Separate Read/Create/Update/Include, inherit `BaseWriteSerializer` |
| 4 | **Filters** | `api/filters.py` | Use `filterset_class`, inherit base filter classes |
| 5 | **Permissions** | `api/base_views.py` | `required_permissions`, `set_required_permissions()` |
| 6 | **Pagination** | `api/pagination.py` | Custom pagination class if needed |
| 7 | **URL Routing** | `api/v1/urls.py` | `trailing_slash=False`, kebab-case paths |
| 8 | **OpenAPI Schema** | `api/v1/views.py` | `@extend_schema_view` with drf-spectacular |
| 9 | **Tests** | `api/tests/test_views.py` | JSON:API content type, fixture patterns |

> **Full file paths**: See [references/file-locations.md](references/file-locations.md)

---

## Decision Trees

### Which Serializer?
```text
GET list/retrieve → <Model>Serializer
POST create       → <Model>CreateSerializer
PATCH update      → <Model>UpdateSerializer
?include=...      → <Model>IncludeSerializer
```

### Which Base Serializer?
```text
Read-only serializer   → BaseModelSerializerV1
Create with tenant_id  → RLSSerializer + BaseWriteSerializer (auto-injects tenant_id on create)
````
END THIRD-PARTY FILE 14bdd1aade0c5d54

The third-party file has ended. Everything between the 14bdd1aade0c5d54 tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 2945 of 16200 bytes. © prowler-cloud · Apache-2.0 · https://github.com/prowler-cloud/prowler/tree/HEAD/skills/django-drf/SKILL.md

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
