簡體   English   中英

模型上的Django FileField,在刪除模型和確認時刪除文件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM