mb52089
mb52089

Reputation: 872

django many-to-many relationships: how to remove items but not delete them from related Models

Django Newbie question. I have the following model:

class Leg(models.Model):
  drive_date = models.DateField()
  startpoint = models.CharField(max_length=50)
  endpoint = models.CharField(max_length=50)
  start_time = models.TimeField()
  riders = models.ManyToManyField(Rider, blank=True)
  drivers = models.ManyToManyField(Driver, blank=True)
  carpool = models.ForeignKey(Carpool,  blank=True, null=True)

for certain instances of Leg, I want to remove any existing riders and drivers from the Leg model, but NOT delete them from the Rider or Driver Models (not shown) respectively. Can't figure out how to do it. When I iterate with:

for driver in leg.drivers.all():
    driver.delete()

It appears to delete the actual Driver object, which I don't want to do.

Any help is greatly appreciated. Thanks!

Upvotes: 1

Views: 4953

Answers (3)

naren
naren

Reputation: 15233

Do this

leg.drivers.clear()

.clear() to completely remove completely(efficiently)
.remove(<related obj>) to remove one relation
.remove([<related obj>, <related obj>...]) to remove one or more relation

Upvotes: 0

jrsupplee
jrsupplee

Reputation: 121

The correct code to remove the items from the relationship is:

for driver in leg.drivers.all():
    leg.drivers.remove( driver )

Upvotes: 12

Jeffrey Bauer
Jeffrey Bauer

Reputation: 14080

One way I might approach this would be to create a custom manager for the Driver model. Untested code below:

from django.db import models

class DriverManager(models.Manager):
    def get_query_set(self):
        return super(DriverManager, self).get_query_set().filter(removed=False)

class Driver(models.Model):
    # new stuff to add ...
    removed = models.BooleanField(default=False)
    objects = models.Manager()  # default manager
    active = DriverManager()  # custom manager

Explanation: A new field, removed, is added to the Driver model. Instead of deleting the record, you set it to True and save. Then, where you would normally filter Driver.objects, use Driver.active instead.

Upvotes: 1

Related Questions