Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Django – How to use delete() in ManyToMany relationships to only delete a single relationship

I have a model Voucher that can be allocated to several users.

I used a M2M relationship for it.

I want, in the template, the possibility to delete the voucher allocated to the logged in user, and the logged in user only (not all relationships).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

The problem I have is that the current model deletes the entire model for all users, instead of the single user requesting "delete".

The alternative would obvioulsy be to simply create a model Voucher on a ForeignKey, but something tells I can probably do it with a M2M in the views.

Is there a way to focus my delete function specific to the user? In the example below, I tried to filter based on user.request which is not working. Looking at the data inside the model, users IDs are listed. Is it not what request.user does?

models

class Voucher(models.Model):
    user = models.ManyToManyField(User, blank=True)

views

def delete_voucher(request, voucher_id):
    voucher = Voucher.objects.filter(pk=voucher_id).filter(user=request.user)
    voucher.delete()
    return redirect('account')

template

<a class="button3 btn-block mybtn tx-tfm" href="{% url 'delete-voucher' voucher.id %}">Delete</a>

url

path('delete_voucher/<voucher_id>', views.delete_voucher, name='delete-voucher'),

>Solution :

Use the .remove method. See the M2M documentation.

So

def delete_voucher(request, voucher_id):
    voucher = Voucher.objects.filter(pk=voucher_id).filter(user=request.user)
    voucher.user.remove( request.user) 
    # note, more readable if the M2M field has a plural name voucher.users
    return redirect('account')

It’s symmetrical so you could also do request.user.voucher_set.remove( voucher)

It may help to know that there’s an intermediate table maintaining the relationship between a voucher object (row in the vouchers table) and a user object. Each row in this table contains a foreign key to one user and a foreign key to one voucher. .remove deletes the row in this intermediate table, leaving the user and voucher objects unchanged.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading