Home > OS >  How to delete model by filtering with pk
How to delete model by filtering with pk

Time:11-19

I am trying to delete an entire model using pk, but when I click on "delete" I am redirected to the given page but nothing happens model is still there and not being deleted, but when I write the 'room_name' instead of 'pk' it does work, (thanks in advance)

*Views.py:
def delete_room(request, pk):
    Room.objects.filter(name=pk).delete()
    return redirect('home')

Urls.py:
    path("delete/<int:pk>/", views.delete_room, name="delete_room")

Models.py:
class Room(models.Model):
    name = models.CharField(max_length=100)
    about = models.TextField(max_length=500, null=True, blank=True)
    creator = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name='room_creator')
    members = models.ManyToManyField(User, through="RoomMember")
    
    
class RoomMember(models.Model):
    approved = models.BooleanField(default=False, blank=False)
    room = models.ForeignKey(Room, related_name='memberships', on_delete=models.CASCADE)
    user = models.ForeignKey(User, related_name='user_groups', on_delete=models.CASCADE)
    
        
class Messages(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=False, blank=False)
    text = models.CharField(max_length=10000, blank=False, null=False)
    date = models.DateTimeField(default=datetime.now)
    room = models.ForeignKey(Room, null=True, blank=False, on_delete=models.CASCADE)

Html:
    <a class="btn btn-danger" href="{% url 'delete_room' pk=room.pk %}">Delete Room</a>*

CodePudding user response:

Whereas @Willem's answer is totally fine, I can also show you a simpler and beginner friendly way of handling request methods from the request object.

def delete_room(request):
    if request.method == "POST" or request.method == "DELETE":
        #Handle your post and delete requests here
        #e.g, deleting as was in the question
        Room.objects.filter(pk=pk).delete()
        #user will never get in here unless they hit via .delete or .post 
        #requests
    return redirect('home')

CodePudding user response:

You can filter on the primary key pk of the item, so:

def delete_room(request, pk):
    Room.objects.filter(pk=pk).delete()
    return redirect('home')

But you should not do this for a GET request. Removing items should be done through a POST request or a DELETE request. As the W3 organization says:

In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered “safe”.

If you accept GET requests, search engines, and some browsers that already retrieve links of a page, might accidentally visit that view, and thus accidentally remove data.

You thus should limit the HTTP methods with:

from django.views.decorators.http import require_http_methods

@require_http_methods(['DELETE', 'POST'])
def delete_room(request, pk):
    Room.objects.filter(pk=pk).delete()
    return redirect('home')

For the HTML you should make a mini form like:

<form method="post" action="{% url 'delete_room' pk=room.pk %}">
    {% csrf_token %}
    <button type="submit" class="btn btn-danger">Delete Room</button>
</form>
  • Related