Mehran Bahrami
Mehran Bahrami

Reputation: 139

Remove specific object from Many-to-many relationship

I have Two models :

class Product(models.Model):
product_model = models.CharField(max_length=255, default='') 
...

class Discount(models.Model):
    name = models.CharField(max_length=255, default='')
    items = models.ManyToManyField(Product, blank=True) 
    discount_percent = models.IntegerField(default=0,
        validators=[
            MaxValueValidator(100),
            MinValueValidator(1),
        ]
    )

I want to delete specific item from items(ManyToManyField)

my views :

def delete_from_discount(request, id, product_url):
    if request.user.is_staff or request.user.is_superuser:
        a = Product(product_url=product_url)
        b = Discount(id=id)
        b = b.items.remove(a)
        return redirect("/staff/discount/"+id)
    else:
        return redirect('/staff') 

There is no error but also nothing change from my models, no remove my html:

{% for dis in discount.items.all %}

<a href="/staff/discount/delete-from-discount/{{discount.id}}/{{dis.product_url}}/">delet</a>
{% endfor %}

Upvotes: 1

Views: 453

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476624

The object you aim to remove should have a primary key, or the field where the ManyToManyField is referring to, not a Product object without a primary key.

You thus should work with:

from django.shortcuts import get_object_or_404

def delete_from_discount(request, id, product_url):
    if request.user.is_staff or request.user.is_superuser:
        a = get_object_or_404(Product, product_url=product_url)
        b = get_object_or_404(Discount, id=id)
        b.items.remove(a)
        return redirect("/staff/discount/"+id)
    else:
        return redirect('/staff')

You can prevent obtaining the Discount object from the database by working on the through model directly:

from django.shortcuts import get_object_or_404

def delete_from_discount(request, id, product_url):
    if request.user.is_staff or request.user.is_superuser:
        a = get_object_or_404(Product, product_url=product_url)
        Discount.items.through.objects.filter(discount_id=id, product=a)
        b.items.remove(a)
        return redirect("/staff/discount/"+id)
    else:
        return redirect('/staff')

Upvotes: 2

Related Questions