2010-06-22 8 views
18
이제
form = AddItemForm(request.POST, request.FILES) 

if form.is_valid() 

    do_stuff 

return render_to_response(blah.html, {'form':form}) 

필드의 원래 값과 함께 오류 정보를 가질 것이다 형성을 실패한 후 파일을 유지하기 위해,하지만 내가 선택한 파일을 유지하려면 어떻게 선택한 파일 을 유지하지 않는 방법 폼이 검증에 실패하면?장고 양식 유효성 검사

+0

동일한 질문이 있습니다. 모델 필드를 사용하는 경우 유효성 검사가 실패 할 때 파일을 저장해야 유효성 검사가 성공하면 업로드 할 수 있습니까? 그런 다음 업로드 된 파일을 제거하기 위해 가비지 컬렉션을로드해야하지만 사용자가 양식을 성공적으로 완료하지 못했습니다. 나는 장고가 이것을하는 좋은 방법을 가지고 있다고 확신한다! – PhoebeB

답변

2

Django는 modelForm을 사용하고 fileField가있는 해당 모델의 새 인스턴스를 성공적으로 저장하는 경우에만 파일을 디스크에 저장합니다.

당신이해야 할 일은 request.FILES 사전에서 파일을 가져 와서 직접 디스크에 저장하는 것입니다. 이런 식으로 보일 것입니다.

input_file = request.FILES['fileformfieldname'] 
new_file = open('/path/to/file.xxx') 
new_file.write(input_file.read()) 

이제 디스크에 저장 한 파일을 가지고, 당신은 단지 파일의 경로를 기억해야하므로 사용자가 실패한 양식을 다시 제출하면 다시 열 수 있습니다.

9

보안상의 이유로 브라우저는 파일로드시 파일 입력 상자에 미리 선택된 값을 허용하지 않습니다. 동일한 페이지의 이전 인스턴스에서 단순히 값을 유지하는 경우에도 마찬가지입니다. 장고가 이것을 바꿀 수있는 방법은 없습니다.

사용자가 파일을 다시 선택하고 다시 업로드하지 않도록하려면 유효성 검사가 실패한 경우에도 업로드 한 파일을 저장하고 파일 입력 필드를 바꿀 필요가 있습니다. 데이터를 가져라. 또한 사용자가 다른 파일을 넣으려는 경우 일부 JavaScript를 실행하여 파일 필드를 다시 활성화하는 버튼이 필요할 수도 있습니다. 장고는 이것에 대해 어떤 기계를 가지고 온다고 생각하지 않는다. 그래서 직접 코딩해야 할 것이다.

1

조금 까다 롭지 만 여기 논리는 있습니다.

  1. HTML 입력 파일과 함께 다른 숨겨진 필드가 있습니다.
  2. 이 숨겨진 필드에 선택한 파일 경로 + 이름을 보관할 자바 스크립트를 작성하십시오.
  3. 페이지가로드되는 동안 JavaScript는 숨겨진 필드의 값을 확인하고 파일 필드가있는 경우이를 설정해야합니다.

첫 번째로드시 숨겨진 필드는 비어 있으므로 아무 일도 발생하지 않습니다.
파일 선택시 숨김 필드에 경로 + 이름을 저장합니다.
두 번째로드시 숨김 필드가 비어 있지 않으므로 파일 경로가 설정됩니다.

이렇게하면 모든 잘못된 작업이 브라우저에서 발생하며 올바른 양식이없는 한 파일을 저장할 필요가 없습니다. 섬기는 사람.

+6

이것은 작동하지 않습니다. Javascript는 입력 유형을 변경할 수 없습니다 = 파일 값 또는 악의적 인 사용자가 임의로 추측 한 파일 이름을 컴퓨터에서 다운로드 할 수 있습니다. –

3

좋아, 그래서 먼저 입력 된 type = "파일"값을 설정할 수 없으므로 Narendra의 솔루션을 작동시키기 전에 upvoted 및 구현했습니다. http://www.w3schools.com/jsref/prop_fileupload_value.asp

을하지만, 여기에 작동하는 솔루션입니다 : 참조 형태의

  1. 별도의 나머지는 업로드 할 필요 파일에서.
  2. 항상 파일을 저장하거나 파일을 저장해야하는지 확인하기 위해 실행하여 임시 모델에 저장하십시오.
  3. 임시 모델의 인스턴스 ID를 나타내는 숨김 필드가 있으므로 파일을 변경하면 변경 내용이 적용됩니다. 서버에 저장된 추가 파일을 얻을 수 있지만 외부에서 정리할 수 있습니다.
  4. 양식을 뺀 파일을 저장할 수 있으면 저장하고 저장된 파일을 원래 모델에 바인딩 한 다음 중간에 업로드 된 파일 모델을 삭제하십시오.

좋아, 여기에 당신이 저자의 (이메일 때로는 유효성을 검사하지 않는 선택) 이메일 주소와 함께 책의 PDF 파일을 저장하려는 일례 나를 위해 작동 절차의 스케치입니다.

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> 
9

시도 django-file-resubmit

insallation

pip install django-file-resubmit 

settings.py

INSTALLED_APPS = { 
    ... 
    'sorl.thumbnail', 
    'file_resubmit', 
    ... 
} 

CACHES = { 
    'default': { 
     'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 
    }, 
    "file_resubmit": { 
     'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 
     "LOCATION": project_path('data/cache/file_resubmit') 
    }, 
} 

사용

from django.contrib import admin 
from file_resubmit.admin import AdminResubmitMixin 

class ModelAdmin(AdminResubmitMixin, ModelAdmin): 
    pass 

또는

from django.forms import ModelForm 
from file_resubmit.admin import AdminResubmitImageWidget, AdminResubmitFileWidget 

class MyModelForm(forms.ModelForm) 

    class Meta: 
     model = MyModel 
     widgets = { 
      'picture': AdminResubmitImageWidget, 
      'file': AdminResubmitFileWidget, 
     } 
+0

업로드를 처음 시도하면 파일이 사라집니다. 두 번째 시도는 성공적입니다. 이것에 대한 설명이 있습니까? – Benjamin