2010-06-26 7 views
18

In einer Mini-Blog-App möchte ich eine Löschfunktion erstellen, damit der Eigentümer des Blogs seine Einträge (und nur seine Einträge) löschen kann. Ich denke, dass die einzige Methode zu tun ist, ein Formular zu verwenden. Obwohl mein Löschcode klar und korrekt scheint, funktioniert es nicht. Mein Code:Löschen von Objekten in Django

def delete_new(request,id): 
    u = New.objects.get(pk=id).delete() 
    if request.method == 'POST': 
     form = DeleteNewForm(request.POST)  
     form.u.delete()    
     form.save() 
    return render_to_response('news/deleteNew.html', { 
      'form': form, 
      }, 
     context_instance=RequestContext(request)) 

und in der Vorlage:

<a href='/news/delete_new/{{object.id}}/'> Delete</a> <br /> 

Ist das ein richtiger Ansatz? Ich meine, eine Form dafür zu schaffen? auch, die einzige Möglichkeit, den Blogpost mit dem Löschlink verbunden zu machen, ist eine ID als Parameter. Ist es richtig? Ich meine, vielleicht kann jeder Benutzer eine andere ID in der URL eingeben und einen anderen Eintrag löschen (eventuell nicht einen)

Antwort

16

Im Allgemeinen sollten Sie zum Löschen von Objekten lieber POST (oder DELETE) HTTP methods verwenden.

Wenn Sie HTTP GET für Ihr Beispiel wirklich nutzen wollen, hier ist das, was Sie beheben müssen:

Wenn Sie url zu einem gewissen URL wie Ihr Hinweis haben: <a href='/news/delete_new/{{object.id}}/'> Delete</a> dann können Sie einfach Ansicht schreiben, wenn überprüfen wird Objekt gehört in Benutzer und löscht diesen Eintrag, wenn ja, wie in Code, den Sie bereits geschrieben haben, protokolliert:

def delete_new(request,id): 
    #+some code to check if New belongs to logged in user 
    u = New.objects.get(pk=id).delete() 

um zu überprüfen, ob neue belogs auf Benutzerobjekte, die Sie benötigen realation zwischen User und New (wie created_by = models.ForeignKey(User) in erstellen New Modell).

Sie können auf diese Weise angemeldeten Benutzer erhalten: request.user

Ich hoffe, dass ich Ihren Punkt bekam richtig und meine Antwort hilft Ihnen, irgendwie.

PS: Sie können auch den Tag {% url %} verwenden, anstatt URLs direkt in Ihre Vorlagen zu schreiben.

+0

es rollt reibungslos und in nur einer Zeile: u = New.objects. filter (created_by = request.user) .get (pk = id) .delete() danke! :) – dana

+0

Genau, können Sie einige Fehlerbehandlung hinzufügen, wenn es kein neues Objekt für einen bestimmten Benutzer gibt und eine nette Fehlermeldung anzeigt (mit Ihrem einen Liner wird es laut mit 500 Fehler fehlschlagen). Aber im Grunde ist das alles, was Sie hier tun müssen :) Ich bin froh, dass meine Antwort für Sie hilfreich war. – dzida

+20

Ich empfehle dringend, ein Formular zu verwenden und POST zu überprüfen, da GETs auf Seiten den Status auf dem Server nicht ändern sollen. (Obwohl in der Praxis das, was hier passiert, relativ 'sicher' ist) –

23

Sie müssen ein Formular verwenden, oder Sie sind anfällig für CSRF attacks. Sie löschen das Modell auch, bevor Sie überprüft haben, ob die Anforderung ein GET oder ein POST war.

ein einfaches Erstellen ModelForm:

from django import forms 

from .models import New 

class DeleteNewForm(forms.ModelForm): 
    class Meta: 
     model = New 
     fields = [] 

In Ihrem views.py in der gleichen Django App:

from django.shortcuts import render, get_object_or_404 

from .forms import DeleteNewForm 
from .models import New 

def delete_new(request, new_id): 
    new_to_delete = get_object_or_404(New, id=new_id) 
    #+some code to check if this object belongs to the logged in user 

    if request.method == 'POST': 
     form = DeleteNewForm(request.POST, instance=new_to_delete) 

     if form.is_valid(): # checks CSRF 
      new_to_delete.delete() 
      return HttpResponseRedirect("/") # wherever to go after deleting 

    else: 
     form = DeleteNewForm(instance=new_to_delete) 

    template_vars = {'form': form} 
    return render(request, 'news/deleteNew.html', template_vars) 
+6

Um zu erklären, warum das das Beste ist: In jedem Fall MÜSSEN POST- (oder PUT-) Anfragen, Aktualisierungen und Löschungen verwendet werden. GET-Anfragen können in ansonsten inoffiziell aussehenden Links maskiert werden. Angenommen, eine große Website hatte ein einfaches "Alles löschen" unter example.com/account/delete/, kann ich einen solchen Link in einem Blogpost oder in TinyURL-ähnlichen Diensten verbergen. Bei einem Besuch sehen Sie ein nettes "Ihr Profil wurde gelöscht." Seite. Hybridmethoden wie Wilfred Hughes 'zeigen eine Bestätigungsseite auf GET an, die ein Formular mit einem CSRF-Token enthält. POST-Anfragen validieren für CSRF und löschen schließlich die angeforderte Ressource. – sleblanc

Verwandte Themen