Carga en la vista la imagen principal del formulario

Cuando la vista de edición de receta recibe un formulario precargado con datos, introduce en el formulario html la imagen principal de la receta, si existe.
Para ello la plantilla lee el campo con el id de la imagen y lo introduce en unos atributos del campo html.
Una etiqueta de django propia obtiene la url de la imagen a partir del id, y un método JavaScript se encarga de colocar la foto en su sitio si se encontró.

Temporalmente la vista de crear receta devuelve siempre a la misma vista pasándole la información del formulario, para facilitar el debugging.
Carga en la vista la lista de imágenes en la galería

Cuando la vista de edición de receta recibe un formulario precargado con datos, introduce en el formulario html la imagen principal de la receta, si existe.
Para ello la plantilla llama a un método del formulario que devuelve la lista de ids de las fotos, y genera un elemento html lista conteniendo la lista de urls.
Una etiqueta de django propia obtiene las urls de las imágenes a partir de los ids, y un método JavaScript se encarga de leer las fotos y añadirlas a la galería.
Carga en el formulario de edición de receta la lista de ingredientes.

Inserta una serie de elementos compatibles con repeatable-fields
Carga en el formulario de edición de receta la lista de pasos.

Inserta una serie de elementos compatibles con repeatable-fields
En caso de error rellena todos los campos del formulario. de Receta incluido la asociacion entre pasos y recta.
Creada URL para la edicion de recetas y la vista para mostrar los datos dentro del formulario.
Corregido error al guardar las imagenes de cada paso. Ya se muestran todos los datos en el formulario incluida las imagenes, los pasos y los ingredientes.
Arreglado redireccion a pagina principal cuando se crea una nueva receta.
Añadido login_required y comprobado que el usuario edita solo sus recetas, en caso contrario devuelve 404 (esto ultimo revisable).
Edición completada.
Devolucion de Unauthorized en vez de 404 Not Found cuando se edita una receta de la que no se es propietario.
Puesto devolucion del http response en una linea, para tener contento a rafa xD
Arreglado problemas con duplicado de pasos, fotos e ingredientes.
Refactorizado formulario de receta para usar JSON

Utiliza JSON para los campos dinámicos, sustituyendo las movidas raras por un campo de texto en el Form que contiene los datos en formato JSON.
Estos campos son las imágenes de la galería, los ingredientes y los pasos (con su asociación de foto).
Añade una serie de métodos al Form para obtener la lista de objetos del JSON, para manipularse mediante python fácilmente.

Quedan muchos campos ocultos y mucha basurilla suelta.
Refactorizada vista de edición de receta

Sacado código de creación de la receta a un método aparte, que llama la vista de crear receta.
Añadido método estático al NewRecipeForm que recibe una receta y devuelve un form relleno con los datos.
Este método se usa en la vista de editar receta.
Corregido editar creaba una receta nueva.

Modificado el método de store_recipe para recibir una receta, que por defecto valga None.
Si no se recibe receta se crea una nueva. Si se recibe se modifica.
Añadida función de clonar receta

Reaprovecha la vista de editar, pasándole un parámetro opcional (flag) desde la url.
Si el parámetro de clonar está activado, pasa la receta como padre al método para guardar la receta.
Este método detecta crea una receta nueva, y le inserta el parent.
Cambiado nombre del formulario de receta

NewRecipeForm por RecipeForm. Ya no se usa sólo para nuevas, también para editar y clonar.
Corregido que pueda clonar cualquier usuario.

Hacía la comprobación de que el usuario actual sea el propietario de la receta antes de mirar si estoy clonando o editando.
Sólo se debe restringir al editar.
Corregido que un usuario no pueda editar la receta de otro.

Se hacía la comprobación de que el usuario de la receta sea el actual sólo cuando se accedía mediante POST, por lo que se mostraba el formulario de edición por GET (aunque luego no se pudiera guardar). Ahora ya no te deja acceder al formulario tampoco.