---
name: vector-django
description: "Provisions an Upstash Vector index for a Django app with `npx extraorbital add vector` (no signup, no card) and wires it into Django with `upstash-vector`. Use when a Django project needs Vector index, embeddings, semantic search, RAG, a vector database or UPSTASH_VECTOR_REST_URL, or when UPSTASH_VECTOR_REST_URL is missing or unset in .env."
---

# Vector index in Django

<!-- Generated from ExtraOrbital's service registry by `pnpm skills:build` in platform/app. Edit the generator, not this file. -->

ExtraOrbital provisions an Upstash Vector index in one command and writes the credentials into the project's env file. For anything this recipe does not cover, use the `extraorbital` skill or https://extraorbital.dev/llms.txt.

## 1. Provision

```bash
npx extraorbital add vector
```

Run it from the project root. It is idempotent (a second run returns the same resource) and writes to `.env.local` if the project has one, otherwise `.env`, keeping that file out of git. Add `--json` to parse the result; credential values are redacted there, and you should never print them either.

| Variable | |
| --- | --- |
| `UPSTASH_VECTOR_REST_URL` |  |
| `UPSTASH_VECTOR_REST_TOKEN` |  |

Free on the Prototype plan: 10K queries + 10K updates/day.

## 2. Install the client

```bash
pip install python-dotenv upstash-vector
```

## 3. Connect

Django reads no env file by itself: `settings.py` loads it with `python-dotenv`, below `BASE_DIR`.

**`yourproject/settings.py`**

```python
import os

from dotenv import load_dotenv

# ExtraOrbital writes .env.local when the project has one, else .env.
# load_dotenv never overrides a variable already set, so the first file wins.
load_dotenv(BASE_DIR / ".env.local")
load_dotenv(BASE_DIR / ".env")

UPSTASH_VECTOR_REST_URL = os.environ["UPSTASH_VECTOR_REST_URL"]
UPSTASH_VECTOR_REST_TOKEN = os.environ["UPSTASH_VECTOR_REST_TOKEN"]
```

**`yourapp/vector.py`**

```python
from upstash_vector import Index

from django.conf import settings

vector_index = Index(
    url=settings.UPSTASH_VECTOR_REST_URL, token=settings.UPSTASH_VECTOR_REST_TOKEN
)
```

## 4. Use it

**`yourapp/views.py`**

```python
from django.http import JsonResponse

from yourapp.vector import vector_index

# yourapp/urls.py: path("api/vector/", views.check_vector)


def check_vector(request):
    info = vector_index.info()
    return JsonResponse({"vectors": info.vector_count, "dimension": info.dimension})
```

Store and search:

```python
# Each vector must have the index's dimension (1536 unless provisioned otherwise).
vector_index.upsert(vectors=[("doc-42", embedding, {"title": "Q3 report"})])
hits = vector_index.query(vector=query_embedding, top_k=5, include_metadata=True)
```

## 5. Verify

```bash
npx extraorbital list        # the resource is listed as active
python manage.py runserver
curl http://localhost:8000/api/vector/
```

A JSON answer means the credentials, the client and the route all work. Delete the route afterwards if the app does not need it.

## Pitfalls

- Dimensions and the similarity function are fixed at creation. Match the embedding model: `npx extraorbital add vector --dimensions 3072` (default 1536, `COSINE`); to change them, provision a new `--slug` and re-index.
- `provision .` creates the index at 1536 dimensions when it detects the variables; run `add vector --dimensions …` first if your model differs.
- Embeddings come from your model; for an API key to call one, see the `ai-gateway-*` skills.
- `yourapp` and `yourproject` stand for the project's own app and settings package.
- Read credentials once in `settings.py` and import `django.conf.settings` elsewhere; `os.environ[...]` fails at startup when one is missing, which is the point.
- Exit code 3 means the account is past its free allowance: show the human the link the command printed and wait. Do not retry or work around it.

Docs: https://extraorbital.dev/docs/resources/vector.md
