Sebastian
Sebastian

Reputation: 2570

Delete object with form in django

I'm displaying a table. In every line there should be a delete button which deletes the element from the table.

My problem is, I'm not sure how to pass the id of the element to the view.

html:

{% for post in posts %}
    <div>
        <h3>Zuletzt ausgewählt:</h3>
        <p>published: <b>{{ post.pub_date }}</b>
        </p>
        <p>
            name: <b>{{ post.Name }}</b>
            anmeldung: <b>{{ post.get_Anmeldung_display }}</b>
            essen: <b>{{ post.get_Essen_display }}</b>
                <form action="" method="POST">
                  {% csrf_token %}
                  <input class="btn btn-default btn-danger" name="delete" type="submit" value="Löschen"/>
                </form>
        </p>
        <p>
            Email: <b>{{ post.Email }}</b>
        </p>
    </div>
{% endfor %}

views.py

if request.method == 'POST' and 'delete' in request.POST:
    Eintrag.objects.filter(pk=id).delete()
    return HttpResponseRedirect(request.path)  

So I need to pass post.pub_date of every post to the view, how can I accomplish that?

Upvotes: 6

Views: 16106

Answers (3)

Denis
Denis

Reputation: 1258

Using POST is our priority, but I thought that adding another form will be redundant.

Found solution in django-allauth' email view.
Though it doesn't include confirmation step (as in docs, mentioned by @HoneyNutIchiros or in more details, or via onclick), it can be useful.
They add name (action_remove) to button and check it in the request.POST dict:

# account/email.html
<button type="submit" name="action_primary" >{% trans 'Make Primary' %}</button>
<button type="submit" name="action_send" >{% trans 'Re-send Verification' %}</button>
<button type="submit" name="action_remove" >{% trans 'Remove' %}</button>
...
<button name="action_add" type="submit">{% trans "Add E-mail" %}</button>

# account/views.py
class EmailView(AjaxCapableProcessFormViewMixin, FormView):
    ...
    def post(self, request, *args, **kwargs):
        ...
        if "action_add" in request.POST:
            res = super(EmailView, self).post(request, *args, **kwargs)
        elif "action_remove" in request.POST:
            res = self._action_remove(request)
        ...
        return res

Upvotes: 0

xyres
xyres

Reputation: 21734

My problem is, I'm not sure how to pass the id of the element to the view.

I can think of two ways to do this. I'll cover them both one by one.

1. Create a separate url route in your app specifically for deleting objects:

('/post/<pk>/delete/', name="delete_post"),

Then point your form's action to this url:

<form action="{% url 'delete_post' post.pk %}" method="POST">
    ...

Finally, modify your view function to accept the pk argument:

def my_view(request, pk): 
    ...

2. Second method is to just create another field in your form and pass it the pk of the object:

Just create another field in your form.

<form action="" method="POST">
    <input type="hidden" value="{{ post.pk }}" name="pk">
    ...

Then in your view just look at request.POST['pk'] to get the pk of the post.

Upvotes: 5

HoneyNutIchiros
HoneyNutIchiros

Reputation: 551

A non-ajax way which is super easy to implement as it uses the Django generic views is this:

template.html

{% for post in posts %}
<div>
    <h3>Zuletzt ausgewählt:</h3>
    <p>published: <b>{{ post.pub_date }}</b>
    </p>
    <p>
        name: <b>{{ post.Name }}</b>
        anmeldung: <b>{{ post.get_Anmeldung_display }}</b>
        essen: <b>{{ post.get_Essen_display }}</b>
            <form action="" method="POST">
              {% csrf_token %}
              <input class="btn btn-default btn-danger" name="delete" type="submit" value="Löschen"/>
            </form>
    </p>
    <p>
        Email: <b>{{ post.Email }}</b>
    </p>
    <a href="/deleteurl/{{ post.pk }}">
        Delete this!
    </a>
</div>
{% endfor %}

Once the user clicks on the delete link they will be redirected to the delete view and template which will have a URL that looks like this "/deleteurl/1/".

Then your set of views, url, and template for processing the delete could look like this:

views.py

class DeleteMe(generic.DeleteView):
    template_name = 'deleteconfirmation.html'
    model = YourModel
    success_url = '/YourRedirectUrl/'

urls.py

url(r'^deleteurl/(?P<pk>\d+)/$', 
    views.DeleteMe.as_view(), name='deletemeview'),     

deleteconfirmation.html

<form action="" method="post">{% csrf_token %}
    <p>Are you sure you want to delete "{{ object }}"?</p>
    <input type="submit" value="Confirm" />
</form>

Again, this is without the use of Ajax.

The views and template are taken directly from the Django Docs

Upvotes: 3

Related Questions