Ok, quindi ho prima mosso e implementato la soluzione di Narendra prima di rendermi conto che non poteva funzionare poiché javascript non può impostare valori di input type = "file". Vedere: http://www.w3schools.com/jsref/prop_fileupload_value.asp
Ma ecco una soluzione che funziona:
- Separare il resto del modulo, dai file che hanno bisogno di essere caricati.
- Salvare sempre il file (o eseguire la convalida per vedere se il file deve essere salvato) e salvare nel modello temporaneo.
- Nel modello, avere un campo nascosto che dice l'id dell'istanza del modello temporaneo, quindi se si modifica il file la modifica si propaga. È possibile ottenere file aggiuntivi salvati sul server, ma è possibile eseguire la pulizia esterna.
- Quando è possibile salvare il modulo meno tutti i file, salvarlo, associare i file salvati al modello originale ed eliminare il modello di file caricato intermedio.
Ok, ecco uno schizzo della procedura, che lavora per me di un esempio in cui si sta tentando di salvare un PDF di un libro con un indirizzo email (scelto come messaggi di posta elettronica a volte non convalidare) di un autore.
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>
fonte
2011-05-02 19:23:59
Ho la stessa domanda. Se sto utilizzando un campo modello, devo davvero salvare il file quando la convalida fallisce, così posso caricarlo quando la convalida ha successo? Poi devo anche fare un carico di garbage collection per rimuovere i file che sono stati caricati ma l'utente non ha mai completato correttamente il modulo. Sono sicuro che Django ha un bel modo di farlo! – PhoebeB