Как переопределить filefield в views.py ?

#django #forms #overriding #django-forms #filefield

#django #формы #переопределение #django-forms #filefield

Вопрос:

У меня есть представление для редактирования документа:

 @login_required
def document_edit(request, doc_id):
    try:
        doc = Document.objects.get(id=doc_id)
    except Document.DoesNotExist:
        raise Http404
    form = DocumentForm(instance=doc)
    if request.method == "POST":
        form = DocumentForm(request.POST, request.FILES, instance=doc)
        if form.is_valid():
            if request.POST.get('cancel'):
               return HttpResponseRedirect('/')
            if request.POST.get('delete'):
                document = Document.objects.get(id=doc_id)
                document.file.delete()
                document.delete()
                return HttpResponseRedirect('/')
            else:
                form.save(author=request.user)
                text = "Document edited!"
                return render_to_response('message.html', {'text' : text}, context_instance = RequestContext(request))
        else:
            return render_to_response('document_edit.html', {'form':form,}, context_instance = RequestContext(request))
    else:
        form = DocumentForm(instance=Document.objects.get(id=doc_id))
        return render_to_response('document_edit.html', {'form':form, 'doc':doc,}, context_instance = RequestContext(request))
  

и эта форма в forms.py:

 class DocumentForm(ModelForm):
    file = forms.FileField(label = 'file', required=True, error_messages={'required' : 'required!','empty': "this file is empty!"})
    title = forms.CharField(label = 'title', widget = forms.TextInput(attrs={'size': 93,}), error_messages={'required': 'required!'})
    description = forms.CharField(label = 'description', widget = forms.Textarea(attrs={'rows': 10, 'cols': 120,}), error_messages={'required': 'required!'})
    editable = forms.BooleanField(label='Document editable?', widget=forms.RadioSelect(choices=YES_OR_NO), required=False, initial=True)
    class Meta:
        model = Document
        exclude = ('author',)

    def save(self, author, commit=True):
        document=ModelForm.save(self,commit=False)
        document.author = author
        if commit:
            document.save()
        return document
  

Теперь я хочу возможность переопределить существующий файл (и автоматически удалить предыдущий файл). Как я могу это сделать?

Ответ №1:

Если я правильно понимаю, вы хотите заменить любой предыдущий файл в поле ‘file’ (тип данных FileField) модели документа. Это произойдет автоматически, если вы загрузите новый файл с помощью формы. Вы видите другое поведение?

Автоматическое удаление предыдущих файлов зависит от используемой вами версии Django. Начиная с версии 1.3 (на данный момент самой последней) FileField не удаляет никаких файлов (список изменений). В версии 1.2 и более ранних версиях FileField удалял файл из файловой системы при изменении и удалении. Итак, если вы измените или удалите экземпляр модели в 1.2, файл исчезнет. В версии 1.3 файл остается.

Вы поступаете правильно, вызывая doc.file.delete() . Однако, если вы выполняете какую-либо массовую операцию над экземплярами модели, этого будет недостаточно. Чтобы протестировать в версии 1.3, используйте AdminSite для выбора нескольких записей и выберите выпадающий список удалить. Хотя записи исчезнут, файлы все еще будут существовать. Эти операции массового набора запросов и любая операция удаления, которая пропускает вашу пользовательскую функцию document_edit(), оставят файлы. Лучше всего будет написать функцию удаления для всех типов данных FileField и прикрепить ее с помощью сигнала pre / post_delete.post_delete. Если вам нужна помощь с этим, я предлагаю новый вопрос SO.

Другие вещи: Вы можете привести в порядок свой код с помощью этой функции быстрого доступа

 from django.shortcuts import get_object_or_404
doc = get_object_or_404(Document, id=doc_id)
  

Вы используете Document.objects.get() три раза в опубликованном коде. Просто используйте вышеупомянутый ярлык один раз, а затем используйте переменную ‘doc’ во всех других местах