0

I followed this tutorial: Need a minimal Django file upload example

Obviously it works. But I want to be able to delete a file as well. Now even if I delete it manually from disc, it still appears on list, even after reconnecting to a server (why?)

I changed the list.html file by adding another form in the loop:

    <!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Minimal Django File Upload Example</title>   
    </head>

    <body>
        <!-- List of uploaded documents -->
        {% if documents %}
            <ul>
            {% for document in documents %}
                <li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a>
                {% if user.is_staff %}
                <form action="{% url 'delete' %}" method="post" enctype="multipart/form-data">
                {% csrf_token %}
                <input type="submit" value="Delete" />
                </form>
                {% endif %}
                </li>
            {% endfor %}
            </ul>
        {% else %}
            <p>No documents.</p>
        {% endif %}

        <!-- Upload form. Note enctype attribute! -->
        <form action="{% url 'list' %}" method="post" enctype="multipart/form-data">
            {% csrf_token %}
            <p>{{ form.non_field_errors }}</p>
            <p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
            <p>
                {{ form.docfile.errors }}
                {{ form.docfile }}
            </p>
            <p><input type="submit" value="Upload" /></p>
        </form>

    </body>

</html> 

As you can see, I added Delete button in a form. By doing so, I have a button near each file. I added this to my views :

def delete(request):
    if request.method != 'POST':
        raise HTTP404
    else:
        docId = request.POST.get('docfile', None)

    if docId is not None:
        docToDel = Document.objects.get(pk=docId)
        docToDel.delete()

    form = DocumentForm(request.POST, request.FILES)
    documents = Document.objects.all()  
    return HttpResponseRedirect(reverse('myapp.views.list'))

But that does not do anything, just reloads the page. As I said, now I cannot even delete them manually. What am I doing wrong?

Community
  • 1
  • 1
Fengson
  • 4,751
  • 8
  • 37
  • 62

1 Answers1

4

First of all file on disk and model in DB are different things. To delete file from disk and DB you may try this

from django.shortcuts import get_object_or_404

def delete(request):
    if request.method != 'POST':
        raise HTTP404

    docId = request.POST.get('docfile', None)
    docToDel = get_object_or_404(Document, pk = docId)
    docToDel.docfile.delete()
    docToDel.delete()

    return HttpResponseRedirect(reverse('myapp.views.list'))

Also you forgot to specify ID of Document to delete

<!-- List of uploaded documents -->
{% if documents %}
<ul>
    {% for document in documents %}
    <li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a>
    {% if user.is_staff %}
        <form action="{% url 'delete' %}" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="hidden" name="docfile" value="{{ document.pk }}" />
        <input type="submit" value="Delete" />
        </form>
    {% endif %}
    </li>
    {% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}
twil
  • 6,032
  • 1
  • 30
  • 28
  • It works, thanks. I have one more question - how do I delete folders in MEDIA if they are empty ? I have folder 2013/11/26 and both 26 folder as well as 11 and 2013 are now empty after my file is gone. – Fengson Nov 26 '13 at 09:47
  • Well, either put the logic inside `delete()` view or create a cron script. In python you can check if dir is empty with [`os.listdir`](http://docs.python.org/2.7/library/os.html?highlight=os.rmdir#os.listdir) or rather just fire [`os.removedirs`](http://docs.python.org/2.7/library/os.html?highlight=os.rmdir#os.removedirs) catching and ignoring `OSError`. – twil Nov 26 '13 at 11:07