[英]Django FileField on Model, Delete File When Deleting Model and Confirmation
我有一個上傳儀表板,其中包含一個上傳表單和一個顯示文件的表格。 在最后一欄中是諸如刪除之類的操作。 但是,當我按Delete時,它會刪除數據庫中的模型,但文件仍在文件夾中。 我也希望從該文件夾中刪除該文件,如果我可以將已刪除的文件移動到另一個目錄(例如回收站),這樣管理員就可以看到文件,即使它們被上載的用戶刪除了也更好。 (用戶數不到10,因此很簡單)
除此之外,我想知道是否有一種方法可以在pre_delete中包含某種確認警報框,以便當他們按下Delete時,它會要求對話框進行確認。
這是我到目前為止的代碼:
我的視圖一個用於儀表板,一個用於刪除:
@login_required(login_url='/dashboard-login/')
def dashboard(request):
current_user = request.user
current_client = request.user.client
files = ClientUpload.objects.filter(client=current_client)
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
dz_files = request.FILES.getlist('file_upload')
for f in dz_files:
new_file = ClientUpload(client=current_client, file_upload=f)
new_file.save()
logger = logging.getLogger(__name__)
logger.info("File uploaded from " + current_client.company)
else:
logger = logging.getLogger(__name__)
logger.warning("Upload Failed")
return HttpResponseRedirect(reverse('dashboard'))
else:
form = UploadFileForm()
data = {'form': form, 'client': current_client, 'files': files}
return render_to_response('dashboard.html', data, context_instance=RequestContext(request))
def dashboard_delete(request, upload_id):
current_user = request.user
current_client = request.user.client
form = UploadFileForm()
p = ClientUpload.objects.get(pk=upload_id)
p.delete()
files = ClientUpload.objects.filter(client=current_client)
data = {'form': form, 'client': current_client, 'files': files}
return render_to_response('dashboard.html', data, context_instance=RequestContext(request))
我的型號和信號:
@python_2_unicode_compatible
class ClientUpload(models.Model):
client = models.ForeignKey(Client)
created_at = models.DateTimeField(auto_now_add=True)
file_upload = models.FileField(upload_to=generate_filename)
def __str__(self):
return self.client.company
class Meta:
verbose_name_plural = _("Client Uploads")
verbose_name = _("Client Upload")
@receiver(post_delete, sender=ClientUpload)
def clientupload_delete(sender, instance, **kwargs):
if instance.file:
# Pass false so FileField doesn't save the model.
instance.file.delete(False)
else:
# log failure
我的文件列表模板:
{% load i18n %}
{% load staticfiles %}
{% load sasite_filters %}
<table class="table">
<tr>
<th>{% blocktrans %}Filename{% endblocktrans %}</th>
<th>{% blocktrans %}Size (Bytes){% endblocktrans %}</th>
<th>{% blocktrans %}Upload Time{% endblocktrans %}</th>
<th>{% blocktrans %}Actions{% endblocktrans %}</th>
</tr>
{% for file in files %}
{% with uploaded_file=file.file_upload %}
<tr>
<th><a href='{{ uploaded_file.url }}'>{{ uploaded_file.name|pathend}}</a></th>
<th>{{ uploaded_file.size }}</th>
<th>{{ file.created_at }}</th>
<th><a href="{% url 'dashboard-delete' file.id %}">Delete</a></th>
{% endwith %}
{% endfor %}
</tr>
</table>
我的儀表板刪除網址:
url(r'^dashboard/delete/(?P<upload_id>\d+)$', views.dashboard_delete, name='dashboard-delete'),
這是確保文件被刪除所需要做的嗎? 我是否正確使用信號? 我錯過了一步嗎? 我只是想確定一下,因為我試圖添加信號,即希望在刪除文件之前將文件復制到“回收站”目錄,此時它不需要模型,可以是目錄中的文件。 但是無論如何,在完成刪除模型之前,我都希望它從其upload_to目錄中刪除並移至另一個目錄。
在此之前或之后刪除正確的一個嗎? 並為刪除確認框? 我應該使用pre_delete還是使用JavaScript進行確認對話? 我不確定 任何示例/建議都將大有幫助。
提前致謝。
編輯:
我不完全確定后刪除/預刪除信號的工作方式如何,但是對於文件刪除似乎有效。 但是我不確定它是否也可以用於移動文件。 使用FileStorageSystem或自定義文件存儲會更好嗎? 基本上,我想在刪除文件之前將文件移動到另一個目錄。 有人可以給我一個處理信號的示例,就像我在post_delete中所做的那樣嗎? 如果FileStorage有更好的方法,那將是一個很大的幫助,因為我一生都無法解決如何做到這一點。
我的第二個問題是addin確認刪除,我想可以通過JS / jQuery更好地實現? 有人告訴我,如果我使用DeleteView CBV,會有一個刪除確認,但我無法使它正常工作。
再次感謝。
編輯2:
這是我在刪除文件之前先移動文件的嘗試,請讓我知道是否弄亂了它,它似乎可以正常工作,但是我不確定,因為我之前從未真正使用過這種信號。
@receiver(post_delete, sender=ClientUpload)
def clientupload_postdelete(sender, instance, **kwargs):
if instance.file:
with f as open(settings.MEDIA_ROOT + '/uploads/Recycle', 'w+'):
f.write(instance.file)
f.close()
# Pass false so FileField doesn't save the model.
instance.file.delete(False)
else:
logger = logging.getLogger(__name__)
logger.Warn("Failed to delete %s" % instance.file)
我發現的解決方案是使用shutil.move()
如下所示:
@receiver(post_delete, sender=ClientUpload)
def clientupload_postdelete(sender, instance, **kwargs):
if instance.file_upload:
filename = os.path.basename(instance.file_upload.path)
client = instance.client.company
folder_path = os.path.join(settings.MEDIA_ROOT, 'uploads/Recycle/', client + '/')
if not os.path.exists(folder_path):
os.makedirs(folder_path)
if os.path.exists(os.path.join(folder_path, filename)):
filename = append_id(filename)
shutil.move(instance.file_upload.path, os.path.join(folder_path, filename))
logger = logging.getLogger(__name__)
logger.info("File %s moved to %s" % (filename, settings.MEDIA_ROOT + '/uploads/Recycle/' + client + '/'))
# Pass False so FileField doesn't save the model.
instance.file_upload.delete(False)
else:
logger = logging.getLogger(__name__)
logger.warning("Failed to find file for copying to %s." % (settings.MEDIA_ROOT + '/uploads/Recycle/'))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.