#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’ во всех других местах