Tutorial Django React: Construye una Aplicación CRUD Fullstack Paso a Paso
En este tutorial detallado aprenderás a construir una aplicación web completa con backend en Django y frontend en React, ideal para desarrolladores con nivel intermedio que quieren iniciar en el desarrollo fullstack moderno. Cubriremos desde la configuración del entorno, creación de una API RESTful usando Django REST Framework, hasta la construcción de una interfaz React que consume esta API para realizar operaciones CRUD (Crear, Leer, Actualizar y Eliminar).
Este proyecto práctico te permitirá dominar la integración completa entre ambas tecnologías, además de enseñarte buenas prácticas en el manejo del estado con hooks y la conexión eficiente entre frontend y backend.
Índice
- Configuración y creación del proyecto Django
- Definición de modelos y migraciones
- Configuración de Django REST Framework y creación de API
- Configuración del entorno React
- Implementación de componentes React para operaciones CRUD
- Manejo del estado con hooks en React
- Conexión entre frontend y backend
- Conclusión y mejores prácticas
Configuración y creación del proyecto Django
Paso 1: Crear y activar un entorno virtual
1 2 3 4 |
python -m venv env source env/bin/activate # MacOS/Linux env\Scripts\activate # Windows |
Paso 2: Instalar Django y Django REST Framework
1 2 |
pip install django djangorestframework |
Paso 3: Crear el proyecto y una aplicación para la API
1 2 3 4 |
django-admin startproject backend cd backend python manage.py startapp api |
Paso 4: Añadir la aplicación y REST Framework a INSTALLED_APPS
Edita backend/settings.py
:
1 2 3 4 5 6 |
INSTALLED_APPS = [ ... 'rest_framework', 'api', ] |
Paso 5: Configurar permiso básico para la API (opcional)
Puedes añadir la configuración básica para que todas las vistas usen permisos abiertos (útil en desarrollo):
1 2 3 4 5 6 |
REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', ] } |
Definición de modelos y migraciones
Para este ejemplo, vamos a crear un modelo simple para administrar Tareas (Tasks) con un título y descripción.
Paso 6: Definir el modelo Task en api/models.py
1 2 3 4 5 6 7 8 9 10 |
from django.db import models class Task(models.Model): title = models.CharField(max_length=100) description = models.TextField(blank=True) completed = models.BooleanField(default=False) def __str__(self): return self.title |
Paso 7: Crear y aplicar migraciones
1 2 3 |
python manage.py makemigrations python manage.py migrate |
Configuración de Django REST Framework y creación de API
Paso 8: Crear un serializer para Task en api/serializers.py
1 2 3 4 5 6 7 8 |
from rest_framework import serializers from .models import Task class TaskSerializer(serializers.ModelSerializer): class Meta: model = Task fields = '__all__' |
Paso 9: Crear vistas basadas en clases para la API en api/views.py
Utilizaremos las vistas genéricas para simplificar el CRUD.
1 2 3 4 5 6 7 8 9 10 11 12 |
from rest_framework import generics from .models import Task from .serializers import TaskSerializer class TaskListCreateAPIView(generics.ListCreateAPIView): queryset = Task.objects.all() serializer_class = TaskSerializer class TaskRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView): queryset = Task.objects.all() serializer_class = TaskSerializer |
Paso 10: Configurar las URLs para la API en api/urls.py
1 2 3 4 5 6 7 8 |
from django.urls import path from .views import TaskListCreateAPIView, TaskRetrieveUpdateDestroyAPIView urlpatterns = [ path('tasks/', TaskListCreateAPIView.as_view(), name='task-list-create'), path('tasks/<int:pk>/', TaskRetrieveUpdateDestroyAPIView.as_view(), name='task-detail'), ] |
Paso 11: Referenciar las URLs de la app en backend/urls.py
1 2 3 4 5 6 7 8 |
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('api.urls')), ] |
Paso 12: Probar que la API funciona
Ejecuta el servidor:
1 2 |
python manage.py runserver |
Abre en el navegador: http://localhost:8000/api/tasks/ – deberías ver una respuesta JSON vacía. La API ya está lista para interactuar.
Configuración del entorno React
Paso 13: Crear proyecto React con Create React App
En un directorio paralelo (o fuera de backend), ejecuta:
1 2 3 |
npx create-react-app frontend cd frontend |
Paso 14: Instalar Axios para las peticiones HTTP
1 2 |
npm install axios |
Paso 15: Ejecutar la aplicación React
1 2 |
npm start |
Implementación de componentes React para operaciones CRUD
Vamos a crear un CRUD simple para administrar las tareas consumiendo la API Django.
Paso 16: Estructura básica en src/App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
import React, { useState, useEffect } from 'react'; import axios from 'axios'; function App() { const [tasks, setTasks] = useState([]); const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const [editingId, setEditingId] = useState(null); // Cargar tareas al montar componente useEffect(() => { fetchTasks(); }, []); const fetchTasks = async () => { try { const res = await axios.get('http://localhost:8000/api/tasks/'); setTasks(res.data); } catch (error) { console.error('Error fetching tasks:', error); } }; const handleSubmit = async (e) => { e.preventDefault(); try { if (editingId) { // Actualizar tarea existente await axios.put(`http://localhost:8000/api/tasks/${editingId}/`, { title, description, completed: false }); } else { // Crear tarea await axios.post('http://localhost:8000/api/tasks/', { title, description, completed: false }); } setTitle(''); setDescription(''); setEditingId(null); fetchTasks(); } catch (error) { console.error('Error saving task:', error); } }; const handleEdit = (task) => { setEditingId(task.id); setTitle(task.title); setDescription(task.description); }; const handleDelete = async (id) => { try { await axios.delete(`http://localhost:8000/api/tasks/${id}/`); fetchTasks(); } catch (error) { console.error('Error deleting task:', error); } }; return ( <div style={{ padding: '20px', maxWidth: '600px', margin: 'auto' }}> <h1>Administrador de Tareas</h1> <form onSubmit={handleSubmit}> <input type="text" placeholder="Título" value={title} onChange={e => setTitle(e.target.value)} required style={{ width: '100%', padding: '8px', marginBottom: '10px' }} /> <textarea placeholder="Descripción" value={description} onChange={e => setDescription(e.target.value)} style={{ width: '100%', padding: '8px', marginBottom: '10px' }} /> <button type="submit" style={{ padding: '10px 15px' }}> {editingId ? 'Actualizar' : 'Crear'} Tarea </button> </form> <ul style={{ listStyle: 'none', padding: 0 }}> {tasks.map(task => ( <li key={task.id} style={{ borderBottom: '1px solid #ccc', padding: '10px 0' }}> <h3>{task.title}</h3> <p>{task.description}</p> <button onClick={() => handleEdit(task)} style={{ marginRight: '10px' }}>Editar</button> <button onClick={() => handleDelete(task.id)}>Eliminar</button> </li> ))} </ul> </div> ); } export default App; |
Manejo del estado con hooks en React
- Utilizamos
useState
para el estado local de tareas, inputs y edición. useEffect
realiza la carga inicial del listado de tareas.- Las funciones
fetchTasks
,handleSubmit
,handleEdit
yhandleDelete
modifican el estado y actualizan la UI.
Esta estructura simple con hooks es suficiente para aplicaciones CRUD medianas y demuestra cómo manejar los datos consumiendo una API REST.
Conexión entre frontend y backend
Paso 17: Configurar CORS para permitir solicitudes desde React
Instala django-cors-headers:
1 2 |
pip install django-cors-headers |
Añádelo al INSTALLED_APPS
y middleware en settings.py
:
1 2 3 4 5 6 7 8 9 10 11 |
INSTALLED_APPS += ['corsheaders'] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', ... ] CORS_ALLOWED_ORIGINS = [ 'http://localhost:3000', ] |
Esto permite que React (puerto 3000) acceda a la API Django sin problemas de CORS.
Paso 18: Ejecuta ambos servidores simultáneamente
- Backend Django:
1 2 |
python manage.py runserver |
- Frontend React:
1 2 |
npm start |
Paso 19: Prueba la integración
Usa la interfaz React para crear, actualizar y eliminar tareas. Verás cómo la UI se actualiza reflejando los cambios y la API responde con los datos correspondientes.
Conclusión y mejores prácticas
En este tutorial aprendiste a crear una aplicación CRUD completa usando Django para el backend y React para el frontend, integrando ambas tecnologías mediante una API RESTful desarrollada con Django REST Framework. También manejamos el estado en React con hooks y configuramos el entorno para el desarrollo local conjunto.
Buenas prácticas para proyectos similares:
- Usa variables de entorno para URLs y configuraciones en frontend y backend.
- Implementa manejo de autenticación y permisos en Django REST Framework.
- Separa componentes React en archivos individuales para mantener el código ordenado.
- Añade validaciones robustas en frontend y backend.
- Considera usar React Router para una aplicación SPA con navegación.
¡Lleva tu aprendizaje más lejos!
- Experimenta añadiendo autenticación con JWT.
- Integra Redux o Context API para manejo avanzado del estado.
- Despliega tu aplicación en plataformas como Heroku o Vercel.
Si te ha gustado este tutorial Django React para principiantes e intermedios, compártelo y síguenos para más contenido de desarrollo fullstack con Django y React.