#17746 closed Bug (duplicate)
use_for_related_fields=False is not honored for m2m relation
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.3 |
Severity: | Normal | Keywords: | use_for_related_fields m2m |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Considering the following model: Trip <-> TripDestination <-> Destination (many to many relation). When I delete a Trip, the SoftDeleteManager filters out all the deleted trip. However, if I request all the destinations of a trip (using get_object_or_404(Trip, pk = id)), I also get the deleted ones (i.e. TripDestination models with deleted_at == null OR deleted_at != null). The SoftDeleteManager should have filtered it out.
Repro Steps
class SoftDeleteManager(models.Manager): use_for_related_fields = True def get_query_set(self): query_set = super(SoftDeleteManager, self).get_query_set() return query_set.filter(deleted_at__isnull = True) class LifeTimeTrackingModel(models.Model): created_at = models.DateTimeField(auto_now_add = True) updated_at = models.DateTimeField(auto_now = True) deleted_at = models.DateTimeField(null = True) objects = SoftDeleteManager() all_objects = models.Manager() class Meta: abstract = True class Destination(LifeTimeTrackingModel): city_name = models.CharField(max_length = 45) class Trip(LifeTimeTrackingModel): name = models.CharField(max_length = 250) destinations = models.ManyToManyField(Destination, through = 'TripDestination') class TripDestination(LifeTimeTrackingModel): trip = models.ForeignKey(Trip) destination = models.ForeignKey(Destination)
- Create a new Trip object with deleted_at set to null
- Create a new Destination object with deleted_at set to null
- Create a new TripDestination object with deleted_at set to datetime.now() linking the previously created Trip and Destionation objects
Actual Result
- Trip.objects.destinations returns the Destination objects
Expected Result
- Trip.objects.destinations shouldn't returns the Destination objects due to the SoftDeleteManager logic which should have filter it out
Other
http://stackoverflow.com/questions/9374962/how-to-soft-delete-many-to-many-relation-with-django
Change History (3)
comment:1 by , 13 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
comment:2 by , 12 years ago
I do not believe this is a duplicate of #14891. The issue in that bug is that use_for_related = False is not respected.
This bug (if it is one) seems to be related to the fact that the manager on the Destination object is used, and the manager on the through model never enters the equation.
i.e., trip_object.destinations.model == Destination
I think the documentation and/or the API design is unclear about this. Is there a way to make trip_object.destinations.all() only return the non-deleted destinations?
comment:3 by , 11 years ago
I also had problems with this. Now I don't see it as a bug, but as a badly documented API. Related managers are the managers of the remote model, not of a through model. So:
trip_object.destinantions.some_method()
calls Destination manager.
destinantion_object.trip_set.some_method()
calls Trip manager.
TripDestination manager is not called at any time.
You can call it with trip_object.destinantions.through.objects.some_method()
, however.
My application differs, but I may suggest modifing the remote manager to check TripDestination.deleted_at field at its get_queryset.
Duplicate of #14891.