4

Case I am in /notes/get/1/ where id=1 and I have created a "Delete Note" link in note.html. I need it to delete the current note from database and app and redirect to /notes/all. Can you help me with the code in def delete?

models.py:

class Note(models.Model): 
   title = models.CharField(max_length=200)
   body = models.TextField()
   cr_date = models.DateTimeField(auto_now_add=True)

urls.py:

urlpatterns = patterns('',

  url(r'^all/$', 'note.views.notes'), 
  url(r'^get/(?P<note_id>\d+)/$', 'note.views.note'), #
  url(r'^language/(?P<language>[a-z\-]+)/$', 'note.views.language'), # 
  url(r'^create/$', 'note.views.create'),
  url(r'^delete/$', 'note.views.delete'), <--------------------------
  url(r'^search/$', 'note.views.search_titles'),
 )

views.py:

def delete(??????):
    ?????  <-------------------------------------------
    return HttpResponseRedirect('/notes/all')
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129

5 Answers5

10
from django.shortcuts import get_object_or_404
from django.core.urlresolvers import reverse


def delete(request, id):
    note = get_object_or_404(Note, pk=id).delete()
    return HttpResponseRedirect(reverse('notes.views.notes'))

And in urls.py

url(r'^delete/(?P<id>\d+)/$','project.app.views.delete'),

Make sure that you check the user permissions before deleting an object, you can use the @permission_required decorator https://docs.djangoproject.com/en/1.5/topics/auth/default/#the-permission-required-decorator. If you don't check this an user can delete all notes easily.

Usually it's a good idea to remove objects from the DB using a POST or DELETE request, instead of a GET. Imagine that google-bot crawls your site and visits notes/delete/2.

fasouto
  • 4,386
  • 3
  • 30
  • 66
  • I would recommend, `get_object_or_404(Note, pk=id)` instead of `.get()` – karthikr Oct 15 '13 at 13:51
  • It makes so much sence , but there is something wrong with the url Page not found (404) Request Method: GET Request URL: http://127.0.0.1:8000/notes/delete/ – Konstantinos Korovesis Oct 15 '13 at 13:58
  • did you try `127.0.0.1:8000/notes/delete/1/` ? (Note the trailing slash) – karthikr Oct 15 '13 at 14:00
  • @KonstantinosKorovesis do you have your urls.py in notes/urls.py or in the project root? If you have in the project root try with `url(r'^notes/delete/(?P\d+)/$','project.app.views.delete'),` – fasouto Oct 15 '13 at 14:02
  • @karthikr I tried : url(r'^/notes/delete/(?P\d)/$', 'note.views.delete'), Same error. – Konstantinos Korovesis Oct 15 '13 at 14:03
  • @ fsouto urls.py is in the app folder. – Konstantinos Korovesis Oct 15 '13 at 14:05
  • @karthikr I tried : http://127.0.0.1:8000/notes/delete/1/ in url but same error 404. Request Method: GET Request URL: http://127.0.0.1:8000/notes/delete/1/ – Konstantinos Korovesis Oct 15 '13 at 14:09
  • @KonstantinosKorovesis so to see all the notes, you need to go to 127.0.0.1:8000/all. So try to go to 127.0.0.1:8000/delete/1 and check if the note was deleted. – fasouto Oct 15 '13 at 14:17
  • @fsouto http://127.0.0.1:8000/notes/all/ this url is for all notes. so still same error Request Method:GET Request URL: http://127.0.0.1:8000/delete/1.... I am trying to see if i missed something. there problem is here: url(r'^delete/(?P\d+)/$', 'note.views.delete'), but it should have been working with http://127.0.0.1:8000/notes/delete/1 cause it matches. – Konstantinos Korovesis Oct 15 '13 at 14:24
  • @KonstantinosKorovesis are you sure that there's a note with id=1 in your DB? – fasouto Oct 15 '13 at 14:28
  • i also tired this: url(r'^delete/(?P\d+)/$', 'note.views.delete'), but still the same. QUESTION : Do i need to create a delete.html file in templates like i did with note.html , notes.html etc ??? i dont see any point in that. STILL NEED HELP ! – Konstantinos Korovesis Oct 15 '13 at 15:07
  • NEW CLUE: change some things and i try http://127.0.0.1:8000/notes/delete/1 again. and i got this error: unindent does not match any outer indentation level (views.py, line 66) .................................................................... views.py: def delete(request, id): obj = Note.objects.get(pk=id) obj.delete() return HttpResponseRedirect('/notes/all') – Konstantinos Korovesis Oct 15 '13 at 15:13
  • @EVERYONE WORKED !!! Maybe it was a minor mistake that i couldnt see. Now i just need to change to url so my link workes with the id of each note in note.html . – Konstantinos Korovesis Oct 15 '13 at 15:24
7

You don't need to write these views by hand because django comes with these, and they are called generic views.

For example, the contributed delete view does the following:

  1. Asks the user to confirm that they really want to delete an object.
  2. Deletes the object.
  3. Redirects to a view.

Here is how you would use it:

In your views.py:

from django.views.generic.edit import DeleteView # this is the generic view
from django.core.urlresolvers import reverse_lazy
from yourapp.models import Note

class NoteDelete(DeleteView):
    model = Note
    success_url = reverse_lazy('all_notes') # This is where this view will
                                            # redirect the user
    template_name = 'delete_note.html'

Create the delete_note.html template, which has only this:

Hey, are you sure you want to delete {{ object.title }}?
<form method="post">
  {% csrf_token %}
  <button type="submit" class="btn btn-danger">Yeap, I'm sure.</button>
</form>

In your urls.py:

urlpatterns = patterns('',

  url(r'^all/$', 'note.views.notes', name='all_notes'), # Giving your urls a name
                                                        # makes it easier to refer
                                                        # to them later
  url(r'^get/(?P<note_id>\d+)/$', 'note.views.note'), #
  url(r'^language/(?P<language>[a-z\-]+)/$', 'note.views.language'), # 
  url(r'^create/$', 'note.views.create'),
  url(r'^delete/(?P<pk>\d+)/$', 'note.views.NoteDelete.as_view()', name="delete_note"),
  url(r'^search/$', 'note.views.search_titles'),
 )

Now, suppose you want to show a link to delete a note, say in your index.html:

Here are all my notes:
<ul>
{% for note in all_notes %}
   <li>{{ note.title }} - <a href="{% url 'delete_note' pk=note.pk %}">Delete</a></li>
{% endfor %}
</ul>
DrBuck
  • 822
  • 7
  • 22
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
  • I am doing this for education so i need to understand some pricipals, but am really interested in the Ask Box that you said.I ll try this for last resolt . Thanks i ll get back to you soon. – Konstantinos Korovesis Oct 15 '13 at 15:17
2

You have to put a variable into url:

url(r'^delete/(?P<id>\d+)/$', 'note.views.delete')

Then view function should be like this:

def delete(request, id):
    obj = Note.objects.get(pk=id)
    obj.delete()
    return HttpResponseRedirect('/notes/all')
adamr
  • 740
  • 6
  • 18
  • It makes so much sence , but there is something wrong with the url Page not found (404) Request Method: GET Request URL: http://127.0.0.1:8000/notes/delete/ – Konstantinos Korovesis Oct 15 '13 at 13:56
2

It's a bit of a micro-optimization, but the answers given already will take two database calls, whereas you can do it in one:

Note.objects.filter(pk=id).delete()
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Please correct me if I'm wrong. But querysets in Django are lazy, so if I get an object and delete it later, only the delete will hit the DB. – fasouto Oct 15 '13 at 14:11
  • No, that makes no sense at all. `get()` is an operation that always hits the database (as `SELECT...WHERE...`). `delete()` is a second operation which also hits the database. But `filter(...).delete()` translates to a single `DELETE`. – Daniel Roseman Oct 15 '13 at 14:19
0

I think below code will solve the problem

Urls.py

url(r'^delete/(?P<id>\d+)/$','project.app.views.delete'),

Views.py

from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect

def delete(request, id):
    note = get_object_or_404(Note, pk=id).delete()
    return HttpResponseRedirect('/notes/all')
BoJack Horseman
  • 4,406
  • 13
  • 38
  • 70