Programación Back-End

Unidad 2: Framework Back-End

La U y la D en CRUD

Redactado por Criz
Publicado el 11 de junio de 2024 a las 14:48
Última actualización el 11 de junio de 2024 a las 14:48

Acciones rapidas
Editar
Siguiente
Previo

CRUD

Vamos a crear un CRUD para nuestra app tienda.
Con todo lo que hemos visto, ya podemos dar este paso.

Ya vimos el C y el R del CRUD:

Ahora vamos por el U y el D:

U update: actualizar

Para actualizar un registro existente, podemos usar el formulario que hemos creado.
Además, podemos instanciar un objeto de nuestra base de datos para indicarle a Django que estamos editando un registro.

Entonces, en views.py de nuestra app tienda, generamos una vista para controlar la edición:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#                                              👇 si no se encuentra el producto...
from django.shortcuts import render, redirect, get_object_or_404
#                                                         lanza un error 404
...
def editar(request, uid):
    #           👇 buscamos el producto segun slug
    producto = get_object_or_404(Producto, slug=uid)
    #                                                   👇 instanciamos el producto dentro del formulario
    formulario = ProductoForm(request.POST or None, instance=producto)
    # mismo comportamiento que 'crear'
    if request.method == "POST":
        if formulario.is_valid():
            formulario.save()
            messages.success(request, "Producto '{}' editado correctamente!".format(formulario.cleaned_data["nombre"]))
            # patron para evitar duplicacion de ediciones
            return redirect("tienda:editar", uid)
            #                                👆 le pasamos la uid. (para utilizarla en urls.py)
    return render(request, "tienda/crud.html", {"form":formulario})

Pudimos haber usado la vista crear pero es mejor dividir para conquistar.

Ahora, registramos en urls.py:

1
2
3
4
urlpatterns = [
    ...
    path('editar/<slug:uid>/', app.editar, name="editar"),
]

Y ahora, al ir a, por ejemplo, http://127.0.0.1:8000/editar/martillo-de-cristal/, podemos ver que el formulario se autocompleto con los datos correspondientes al objeto producto con ese slug.

Si editamos un campo y clicamos el botón Submit, deberíamos ver que nuestro producto fue modificado.

Nótese que, si cambiamos el nombre, nuestro formulario sobrescribirá el slug y esta url dejaría de ser valida.
Una solución es verificar que si un objeto ya está guardado, el slug no se pueda modificar.
Esto se puede realizar modificando el método save() nuevamente.
En https://stackoverflow.com/a/21756188 hay una respuesta a este problema...
Entonces, el metodo save() de nuestro modelo producto quedaría:

1
2
3
4
5
6
...
def save(self, *args, **kwargs):
    if self.pk is None: # si no hay ID, entonces el objeto no existe
        self.slug = slugify(self.nombre) # generamos un slug
    super(Producto, self).save(*args, **kwargs)
...

El campo pk devolverá None si la instancia no tiene un objeto dentro de la base de datos.

D delete: eliminar

El eliminar es más sencillo...
Creamos una vista llamada eliminar que aceptara una uid.

1
2
3
4
5
6
7
8
def eliminar(request, uid):
    producto = get_object_or_404(Producto, slug=uid)
    # mostramos un mensaje
    messages.error(request, "Producto '{}' eliminado correctamente!".format(producto.nombre))
    #           👇 *c elimina*
    producto.delete()
    #                     👇 redirigimos a inicio
    return redirect("tienda:index")

Nótese que, por lógica, si eliminamos el producto y luego mostramos el mensaje, se generara un error, ya que el objeto no existe.

Luego, registramos la vista en urls.py:

1
2
3
4
urlpatterns = [
    ...
    path('eliminar/<slug:uid>/', app.eliminar, name="eliminar"),
]

Y ya está. Al navegar a http://127.0.0.1:8000/eliminar/filorte/, el objeto filorte será eliminado.


Siguiente
Previo