API & HTTP Integration¶
While reflex-django allows you to perform database queries directly inside reactive frontend states using the Django ORM, there are times when you need to expose traditional HTTP REST APIs, receive third-party webhooks, or integration-test endpoints.
This guide explains how to build and expose Django APIs alongside your Reflex Single Page Application (SPA).
Choosing Your Data Fetching Strategy¶
Before building an API endpoint, choose the architectural approach that best fits your immediate requirement:
| Integration Strategy | Execution Environment | Best For | Advantages |
|---|---|---|---|
| Direct ORM Queries | Run inside Reflex WebSocket Event Handlers (@rx.event) |
Standard UI grids, forms, user actions, dashboard charts. | Zero HTTP Latency: No REST overhead, direct DB connection, automatic user auth context. |
| Traditional Django Views | Exposed as HTTP endpoints under backend_prefix |
Webhook endpoints (e.g., Stripe, SendGrid), file downloads, legacy template pages. | Standard HTTP Lifecycle: Supports raw payloads, multipart forms, and direct file streaming. |
| REST APIs (DRF) | Exposed as structured REST endpoints under backend_prefix |
Mobile apps, public developer portals, integrations with third-party web clients. | Structured Payload Controls: Standardized CRUD actions, authentication schemes, and automatic docs. |
1. Traditional Django Views under backend_prefix¶
To expose standard HTTP views, configure the plugin with a prefix and map the corresponding paths inside your Django project:
1. Configure the Plugin Prefix¶
Define your API route path namespace in rxconfig.py:
# rxconfig.py
from reflex_django import ReflexDjangoPlugin
config = rx.Config(
app_name="frontend",
plugins=[
ReflexDjangoPlugin(
settings_module="backend.settings",
backend_prefix="/api", # Matches our API routes namespace
),
],
)
2. Map the URL Patterns¶
Add the endpoint in your main Django backend routing file:
# backend/urls.py
from django.urls import path, include
urlpatterns = [
# Include application views under the matching prefix
path("api/shop/", include("shop.urls")),
]
3. Write a Standard Django View¶
Now, implement a standard Django view that returns JSON data:
# shop/views.py
from django.http import JsonResponse
from django.views.decorators.http import require_GET
from shop.models import Product
@require_GET
def active_products_view(request):
"""Exposes active products as a standard JSON payload."""
products = Product.objects.filter(is_active=True).order_by("-id")
data = [
{
"id": p.id,
"name": p.name,
"price": float(p.price),
}
for p in products
]
return JsonResponse({"results": data}, safe=False)
2. Integrating Django REST Framework (DRF)¶
[!NOTE] Third-Party Dependency:
djangorestframeworkis not installed byreflex-django. If you want to use DRF, you must add it to your project dependencies manually (e.g.,uv add djangorestframework).
Once DRF is installed and added to your INSTALLED_APPS, you can build REST ViewSets exactly as you would in a traditional Django API project:
# shop/serializers.py
from rest_framework import serializers
from shop.models import Product
class DRFProductSerializer(serializers.ModelSerializer):
"""Standard Django REST Framework Serializer."""
class Meta:
model = Product
fields = ["id", "name", "price", "sku", "is_active"]
# shop/views.py
from rest_framework import viewsets
from shop.models import Product
from shop.serializers import DRFProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
"""DRF ViewSet exposed under the backend prefix."""
queryset = Product.objects.all()
serializer_class = DRFProductSerializer
Register this viewset inside your application routing module:
# shop/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from shop.views import ProductViewSet
router = DefaultRouter()
router.register(r"products", ProductViewSet, basename="product")
urlpatterns = [
path("", include(router.urls)),
]
This registers standard CRUD routes at http://localhost:3000/api/shop/products/ using DRF's standard rendering and authorization stack.
CORS & Single-Origin Architecture¶
One of the greatest benefits of reflex-django is the Single-Origin Architecture.
- Under Development / Production: Because
reflex runhosts both the Reflex frontend SPA and Django under the same network origin (sharing ports and domains), the browser treats them as a single application. - No CORS Needed: You do not need to install or configure
django-cors-headersto make requests from your frontend components to your API views. This eliminates standard preflight request overhead and configuration complexities.
Serializers Clarification: Reflex vs DRF¶
It is important not to confuse the two distinct serializer interfaces used in this stack:
+--------------------------------------------------------------------------------+
| Serialization Choices |
+--------------------------------------------------------------------------------+
│
┌──────────────────────────────┴──────────────────────────────┐
▼ ▼
+─────────────────────────────────+ +──────────────────────────────────+
| ReflexDjangoModelSerializer | | DRF ModelSerializer |
| (Included in reflex-django) | | (Optional, requires DRF install) |
+─────────────────────────────────+ +──────────────────────────────────+
│ │
▼ ▼
* Runs inside WebSocket state events * Runs inside standard HTTP Views
* Converts models to serializable dicts * Converts models to REST API responses
* Binds results to rx.State variables * Handles JSON input parsing & validation
ReflexDjangoModelSerializer: Provided natively byreflex-django. It is designed specifically to convert Django models into JSON-safe dictionaries to bind them directly onto Reflex states.- DRF
ModelSerializer: Part ofdjangorestframework. It should only be used inside traditional HTTP endpoints and views served under your backend prefixes.
Advanced Routing: Exposing Webhooks¶
If you are integrating third-party webhooks (like Stripe checkout events), these endpoints must bypass CSRF verification and handle raw POST payloads. Add them to extra_prefixes in rxconfig.py to route them directly to Django ASGI:
# rxconfig.py
ReflexDjangoPlugin(
settings_module="backend.settings",
extra_prefixes=("/webhooks",),
)
Map them inside your Django backend routing, using the @csrf_exempt decorator:
# shop/urls.py
from django.urls import path
from shop.views import stripe_webhook_view
urlpatterns = [
path("webhooks/stripe/", stripe_webhook_view),
]
Navigation: ← Routing & URL Dispatching | Next: State Management →