2011-01-29 3 views
2

Я загружаю файлы и сохраняю метаданные в db. Часть метаданных - это имя файла. Однако, где-то вниз, имя файла, похоже, не будет спасено! Я буду вставлять только то, что, по моему мнению, является соответствующими частями кода, чтобы сохранить это короткое.Загрузка файла Django: filename not sticking

class UploadFile(models.Model): 
    ... 
    theFile = models.FileField(upload_to = "Genius/Uploads/", null = True) 
    filename = models.CharField(max_length = 50, blank = True, null = False) 

class UploadFileForm(ModelForm): 
    class Meta: 
     model = UploadFile 
     fields = ('title', 'theFile', 'date_uploaded',) # Don't prompt for filename 


def files_upload(request): 
    if request.method == 'POST': 
     form = UploadFileForm(request.POST, request.FILES) 
     if form.is_valid(): 
      form.filename = request.FILES['theFile'].name # TODO: sanitize! 
      # form.filename = 'foo' 
      form.save() 
      return HttpResponseRedirect('/files/upload/successful/') 
     else: 
      form = UploadFileForm() 
     return render_to_response('files/upload_file.html', { 'form': form }) 

Я проверил значение request.FILES [ 'theFile']. Имя перед & после сохранения формы. По какой-то причине он не поврежден, но никогда не кажется, что он попадает в БД.

+0

Просто обойти: некоторые браузеры отправляют вам только имя файла, другие отправляют вам весь путь. – CodesInChaos

ответ

2

Это потому, что form.filename - это поле формы, а не значение, которое оно будет сохранять.

Вы ищете что-то вроде этого:

class UploadFileForm(ModelForm): 
    def save(self, commit=True): 
     instance = ModelForm.save(self, commit=False) 
     instance.filename = self.files['theFile'].name 

     if commit: 
      instance.save() 

     return instance 

    class Meta: 
     model = UploadFile 
     fields = ('title', 'theFile', 'date_uploaded',) # Don't prompt for filename 

Альтернативное решение: значения поля

upload_file = form.save(commit=False) 
upload_file.filename = request.FILES['theFile'].name 
upload_file.save() 
+0

Ох. Таким образом, upload_file становится экземпляром .. err wait. Я смущен. Можете ли вы подробнее остановиться? Noob здесь. – Harv

+0

@ Харв: ты прав. Метод 'form.save()' возвращает экземпляр (и с 'commit = True', он сначала сохраняет его). Есть и другие варианты, вы можете добавить поле формы в форму и изменить аргумент 'data' в форме. Вы можете изменить метод 'save()' формы, чтобы он автоматически делал это внутри формы (у вас должно быть 'self.files' доступно в форме). – Wolph

+0

Хорошо, потрясающе. Спасибо, что освободил меня. И за ответ так быстро! – Harv

1

Форма не доступны через атрибуты в форме. Поэтому установка 'form.filename' не устанавливает значение, которое будет сохранено в поле имени файла. Вместо этого установите значение в экземпляре, возвращаемом формой .save().

upload_file = form.save(commit=False) 
upload_file.filename = filename 
upload_file.save() 
0

Я просто хотел добавить, что в будущем вы можете попытаться избежать такой бизнес-логики в форме модели. В то время как ответ WoLpH's является правильным и отличным примером того, как обрабатывать дополнительную обработку экземпляра модели с помощью ModelForm, конкретные случаи наличия полей, зависящих от данных других полей, обрабатываются в API , Form и ModelForm через их уважаемые методы clean() и упоминается в нескольких места в официальных справочных документах (здесь один на forms, хотя то же самое справедливо и для API Model и ModelForm).

В вашем случае это будет означать:

import os 

class UploadFile(models.Model): 

    # ... 

    def clean(self): 
      # Field data has already been populated by this point. 
      # Note that `FieldFile` inherits from `File` and that 
      # `File.name` is actually the full path to the file 
      # so we need to get the base path component sans the extension 

      path, extension = os.path.splitext(self.thefile.file.name) 
      self.filename = os.path.basename(path) 

И вот об этом! Если вы правильно установите атрибутв своих полях модели, вы обнаружите, что вы можете положиться на Django, чтобы автоматически генерировать ModelForm для модели UploadFile. Это означает, что вам не нужно определять ModelForm для общих представлений создания, обновления или ModelAdmin вашей модели, и это меньше строк кода для управления!

Общее правило состоит в том, что вы дважды задумываетесь о том, оправданно ли само по себе поведение по умолчанию, особенно когда вы работаете в дальнем конце цепочки бизнес-логики, иначе вы можете почувствовать гнев неожиданных провалов ,

Смежные вопросы