<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>{% block title %}Django REST + JWT{% endblock %}</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<nav class="navbar">
<a href="/">🚀 Mi Proyecto</a>
<ul>
<li><a href="/dashboard/">Dashboard</a></li>
<li><a href="/login/">Login</a></li>
</ul>
</nav>
{% block content %}{% endblock %}
<footer>
<p>© 2024 Mi Proyecto Django</p>
</footer>
</body>
</html>
{% extends 'base.html' %}
{% load static %}
{% block title %}Login - JWT{% endblock %}
{% block content %}
<div class="auth-container">
<div class="auth-card">
<h2>🔐 Iniciar Sesión</h2>
<form id="loginForm">
<div class="form-group">
<label>Usuario:</label>
<input type="text" id="username" required>
</div>
<div class="form-group">
<label>Contraseña:</label>
<input type="password" id="password" required>
</div>
<button type="submit" class="btn btn-primary">
Iniciar Sesión
</button>
</form>
<div class="oauth-buttons">
<a href="/api/auth/google/" class="btn btn-google">
Login con Google
</a>
<a href="/api/auth/github/" class="btn btn-github">
Login con GitHub
</a>
</div>
</div>
</div>
{% endblock %}
{% extends 'base.html' %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<div class="dashboard-container">
<h1>📊 Dashboard</h1>
<p>Bienvenido, <span id="username"></span></p>
<div class="dashboard-grid">
<div class="card">
<h3>👤 Perfil</h3>
<div id="profile-info"></div>
</div>
<div class="card">
<h3>📚 Libros</h3>
<div id="books-list"></div>
</div>
</div>
</div>
{% endblock %}
/* Estilos principales */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.navbar {
background: white;
padding: 1rem;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
}
// Autenticación JWT
const API_URL = window.location.origin;
function getAccessToken() {
return localStorage.getItem('access_token');
}
function saveTokens(access, refresh) {
localStorage.setItem('access_token', access);
localStorage.setItem('refresh_token', refresh);
}
async function login(username, password) {
const response = await fetch(`${API_URL}/api/login/`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ username, password })
});
if (response.ok) {
const data = await response.json();
saveTokens(data.access, data.refresh);
window.location.href = '/dashboard/';
}
}
FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1
WORKDIR /app
RUN apt-get update && apt-get install -y \
gcc \
default-libmysqlclient-dev \
pkg-config
COPY requirements.txt .
RUN pip install --upgrade pip && \
pip install -r requirements.txt
COPY . .
RUN python manage.py collectstatic --noinput
EXPOSE 8000
CMD ["daphne", "-b", "0.0.0.0", "-p", "8000", "biblioteca_digital.asgi:application"]
version: '3.8'
services:
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: mi_base_datos
MYSQL_ROOT_PASSWORD: root_password
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
web:
build: .
command: daphne -b 0.0.0.0 -p 8000 biblioteca_digital.asgi:application
volumes:
- .:/app
ports:
- "8000:8000"
depends_on:
- db
- redis
volumes:
mysql_data: