Ok, así que primero elevé e implementé la solución de Narendra antes de darme cuenta de que no podía funcionar, ya que javascript no puede establecer valores de tipo de entrada = "archivo". Ver: http://www.w3schools.com/jsref/prop_fileupload_value.asp
Pero he aquí una solución que funciona:
- separada del resto de la forma, a partir de los archivos que necesitan ser cargados.
- Guarde siempre el archivo (o ejecute la validación para ver si el archivo debe guardarse) y guárdelo en el modelo temporal.
- En la plantilla, tenga un campo oculto que indique la identificación de la instancia del modelo temporal, de modo que si cambia el archivo, la modificación se propaga. Puede obtener archivos extra guardados en su servidor, pero puede limpiarlos externamente.
- Cuando se puede guardar el formulario sin ningún archivo, guárdelo, vincule los archivos guardados con el modelo original y elimine el modelo de archivo cargado intermedio.
autorización, aquí es un esbozo del procedimiento, que trabaja para mí de un ejemplo en el que está intentando guardar un archivo PDF de un libro con una dirección de correo electrónico (elegido como mensajes de correo electrónico a veces no validan) de un autor.
models.py
class Book(models.Model):
pdf = models.FileField("PDF", upload_to="books/")
author_email = models.EmailField("Author Email")
class TempPDF(models.Model):
pdf = models.FileField("PDF", upload_to="books/")
forms.py
from project_name.app_name.models import Book, TempPDF
from django.forms import ModelForm
from django.contrib.admin.widgets import AdminFileWidget
class BookForm(ModelForm):
class Meta:
model = Book
exclude = ['pdf',]
class TempPDFForm(ModelForm):
class Meta:
model = TempPDF
widgets = dict(pdf = AdminFileWidget)
# The AdminFileWidget will give a link to the saved file as well as give a prompt to change the file.
# Note: be safe and don't let malicious users upload php/cgi scripts that your webserver may try running.
views.py
def new_book_form(request):
if request.method == 'POST':
## Always try saving file.
try:
temp_pdf_inst = TempPDF.objects.get(id=request.POST.has_key('temp_pdf_id'))
except: ## should really catch specific errors, but being quick
temp_pdf_inst = None
temp_pdf_form = TempPDFForm(request.POST, request.FILES, instance=temp_pdf_inst, prefix='temp_pdf')
if temp_pdf_form.is_valid() and len(request.FILES) > 0:
temp_pdf_inst = temp_pdf_form.save()
temp_pdf_id = temp_pdf_inst.id
book_form = BookForm(request.POST, prefix='book')
if book_form.is_valid(): # All validation rules pass
book = book_form.save(commit=False)
book.pdf = temp_pdf_inst.pdf
book.save()
if temp_pdf_inst != None:
temp_pdf_inst.delete()
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
book_form = BookForm() # An unbound form
temp_pdf_form = TempPDFForm()
temp_pdf_id = None
return render_to_response('bookform_template.html',
dict(book_form = book_form,
temp_pdf_form = temp_pdf_form,
temp_pdf_id = temp_pdf_id)
)
bookform_template.html
<table>
{{ book_form }}
{{ temp_pdf_form }}
<input type="hidden" name="temp_pdf_id" value="{{ temp_pdf_id }}">
</table>
Tengo la misma pregunta. Si estoy usando un campo de modelo, ¿realmente tengo que guardar el archivo cuando falla la validación para que pueda subirlo cuando la validación sea exitosa? Luego, tengo que cargar un montón de basura para eliminar los archivos que se cargaron pero el usuario nunca completó el formulario. ¡Estoy seguro de que Django tiene una buena manera de hacer esto! – PhoebeB