Conversión entre Objetos jQuery y DOM Nativo
Para acceder al elemento DOM real desde un objeto jQuery, se utiliza la notación de índice [0]. Para envolver un eelmento DOM nativo con jQuery, se emplea la función $().
// jQuery a DOM nativo
var elementoDOM = $(selector)[0];
// DOM nativo a jQuery
var $elementojQuery = $(elementoDOM);
Actualizar Código de Verificación Dinámicamente
Para implementar un captcha que se renueve al hacer clic, se modifica el atributo src de la imagen añadiendo un parámetro aleatorio:
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Formulario de Acceso</title>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<style>
.contenedor-formulario { margin-top: 80px; }
.mensaje-error { color: #dc3545; font-size: 0.9em; }
</style>
</head>
<body>
<div class="container">
<div class="row justify-content-center contenedor-formulario">
<div class="col-md-5">
<form id="formulario-acceso">
{% csrf_token %}
<div class="mb-3">
<label for="campo-usuario" class="form-label">Usuario</label>
<input type="text" id="campo-usuario" name="nombre_usuario" class="form-control">
</div>
<div class="mb-3">
<label for="campo-clave" class="form-label">Contraseña</label>
<input type="password" id="campo-clave" name="clave" class="form-control">
</div>
<div class="mb-3">
<label for="campo-verificacion" class="form-label">Código de verificación</label>
<div class="row align-items-center">
<div class="col-6">
<input type="text" class="form-control" id="campo-verificacion">
</div>
<div class="col-6">
<img src="/generar-captcha/" width="140" height="45" id="imagen-captcha" alt="captcha">
</div>
</div>
</div>
<button type="button" id="boton-enviar" class="btn btn-primary w-100">Iniciar Sesión</button>
<p class="mensaje-error mt-2" id="texto-error"></p>
</form>
</div>
</div>
</div>
<script src="/static/js/jquery.min.js"></script>
<script>
$('#boton-enviar').on('click', function() {
var usuario = $('#campo-usuario').val();
var contrasena = $('#campo-clave').val();
var codigo = $('#campo-verificacion').val();
$.ajax({
url: '/autenticar/',
method: 'POST',
data: {
nombre_usuario: usuario,
clave: contrasena,
codigo_verificacion: codigo
},
success: function(respuesta) {
if (respuesta.exito) {
window.location.href = '/panel/';
} else {
$('#texto-error').text(respuesta.mensaje);
}
}
});
});
$('#imagen-captcha').on('click', function() {
var elemento = this;
elemento.src = elemento.src.split('?')[0] + '?' + Date.now();
});
</script>
</body>
</html>
Métodos para Subir Archivos
Envío Mediante Formulario Tradicional
Configuración de rutas y vista en Django:
# urls.py
from django.urls import path
from aplicacion import vistas
urlpatterns = [
path('registro/', vistas.registrar_usuario),
]
# vistas.py
from django.shortcuts import render, HttpResponse
def registrar_usuario(request):
if request.method == 'POST':
nombre = request.POST.get('nombre_usuario')
archivo = request.FILES.get('documento')
if archivo:
ruta_destino = archivo.name
with open(ruta_destino, 'wb') as destino:
for fragmento in archivo.chunks():
destino.write(fragmento)
return HttpResponse('Archivo almacenado correctamente')
return render(request, 'registro.html')
Plantilla HTML con formulario estándar:
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Registro de Usuario</title>
</head>
<body>
<form action="/registro/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div>
<label>Nombre de usuario:</label>
<input type="text" name="nombre_usuario">
</div>
<div>
<label>Seleccionar archivo:</label>
<input type="file" name="documento">
</div>
<button type="submit">Enviar</button>
</form>
</body>
</html>
Envío Mediante AJAX con FormData
# urls.py (mismo esquema anterior)
# vistas.py
from django.shortcuts import render, HttpResponse
def registrar_usuario(request):
if request.method == 'POST':
nombre = request.POST.get('nombre_usuario')
archivo_subido = request.FILES.get('archivo_adjunto')
if archivo_subido:
with open(archivo_subido.name, 'wb') as destino:
for porcion in archivo_subido:
destino.write(porcion)
return HttpResponse('Procesado exitosamente')
return render(request, 'registro.html')
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Registro AJAX</title>
</head>
<body>
<div>
<label>Usuario:</label>
<input type="text" id="input-nombre">
</div>
<div>
<label>Archivo:</label>
<input type="file" id="input-archivo">
</div>
<button id="btn-registrar">Registrar</button>
<script src="/static/js/jquery.min.js"></script>
<script>
$('#btn-registrar').on('click', function() {
var datosFormulario = new FormData();
datosFormulario.append('nombre_usuario', $('#input-nombre').val());
var archivoSeleccionado = $('#input-archivo')[0].files[0];
datosFormulario.append('archivo_adjunto', archivoSeleccionado);
$.ajax({
url: '/registro/',
type: 'POST',
data: datosFormulario,
contentType: false,
processData: false,
success: function(resultado) {
console.log('Respuesta:', resultado);
}
});
});
&;/script>
</body>
</html>
Formularios de Django con Campos Personalizados
Uso del sistema de formularios de Django para generar los controles del formulario:
# vistas.py
from django.shortcuts import render, HttpResponse
from django import forms
from django.forms import widgets
class FormularioRegistro(forms.Form):
nombre_usuario = forms.CharField(
max_length=50,
label='Nombre de usuario',
widget=widgets.TextInput(attrs={'class': 'form-control'})
)
clave_acceso = forms.CharField(
max_length=50,
label='Contraseña',
widget=widgets.PasswordInput(attrs={'class': 'form-control'})
)
confirmar_clave = forms.CharField(
max_length=50,
label='Confirmar contraseña',
widget=widgets.PasswordInput(attrs={'class': 'form-control'})
)
correo_electronico = forms.EmailField(
label='Email',
widget=widgets.EmailInput(attrs={'class': 'form-control'})
)
def registrar_usuario(request):
formulario = FormularioRegistro()
if request.method == 'POST':
formulario = FormularioRegistro(request.POST)
if formulario.is_valid():
nombre = formulario.cleaned_data['nombre_usuario']
clave = formulario.cleaned_data['clave_acceso']
archivo_avatar = request.FILES.get('imagen_perfil')
if archivo_avatar:
with open(archivo_avatar.name, 'wb') as f:
for chunk in archivo_avatar:
f.write(chunk)
return HttpResponse('Registro completado')
return render(request, 'registro.html', {'formulario': formulario})
Plantilla con selector de avatar oculto que se activa al hacer clic en la imagen:
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Formulario de Registro</title>
<style>
.panel-formulario { margin-top: 60px; }
#selector-avatar { display: none; }
.miniatura-avatar { width: 60px; height: 60px; border-radius: 50%; cursor: pointer; }
</style>
</head>
<body>
<div class="container">
<div class="row justify-content-center panel-formulario">
<div class="col-md-6">
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="mb-3">
<label for="{{ formulario.nombre_usuario.id_for_label }}">{{ formulario.nombre_usuario.label }}</label>
{{ formulario.nombre_usuario }}
</div>
<div class="mb-3">
<label for="{{ formulario.clave_acceso.id_for_label }}">{{ formulario.clave_acceso.label }}</label>
{{ formulario.clave_acceso }}
</div>
<div class="mb-3">
<label for="{{ formulario.confirmar_clave.id_for_label }}">{{ formulario.confirmar_clave.label }}</label>
{{ formulario.confirmar_clave }}
</div>
<div class="mb-3">
<label>Foto de perfil</label><br>
<label for="selector-avatar">
<img src="/static/img/avatar-predeterminado.png" class="miniatura-avatar" id="vista-previa">
</label>
<input type="file" id="selector-avatar" name="imagen_perfil">
</div>
<button type="submit" class="btn btn-success">Crear cuenta</button>
</form>
</div>
</div>
</div>
<script src="/static/js/jquery.min.js"></script>
<script>
$('#selector-avatar').on('change', function() {
var archivo = this.files[0];
if (archivo) {
var lector = new FileReader();
lector.onload = function(evento) {
$('#vista-previa').attr('src', evento.target.result);
};
lector.readAsDataURL(archivo);
}
});
</script>
</body>
</html>
Configuración de Rutas para Archivos Multimedia
Para almacenar los archivos subidos por los usuarios en el servidor, se configura la ruta de medios en Django:
# settings.py
import os
MEDIA_URL = '/archivos/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'aplicacion', 'media')
Se agrega una ruta para servir los archivos estáticos durante el desarrollo:
# urls.py
from django.urls import re_path
from django.views.static import serve
from django.conf import settings
urlpatterns = [
# ... otras rutas ...
re_path(r'^archivos/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]
De esta forma, los archivos subidos se organizan dentro de la carpeta media del proyecto, permitiendo una gestión ordenada de los recursos de los usuarios.