Как отфильтровать модель поля "многие ко многим"?
Я пытаюсь реализовать геозону для парка грузовиков. Я должен связать список границ с транспортным средством. Кроме того, одно из требований-сохранить все, даже если оно удалено для целей аудита. Поэтому мы должны реализовать soft delete на всем. Вот в чем проблема. Поле "многие ко многим" не соответствует менеджеру мягкого удаления, оно включает как активные, так и неактивные записи в наборе данных поиска.
class Vehicle(SoftDeleteModel):
    routes = models.ManyToManyField('RouteBoundary', through='VehicleBoundaryMap', verbose_name=_('routes'),
                                    limit_choices_to={'active': True})
class VehicleBoundaryMap(SoftDeleteModel):
    vehicle = models.ForeignKey(Vehicle, verbose_name="vehicle")
    route_boundary = models.ForeignKey(RouteBoundary, verbose_name="route boundary")
    # ... more stuff here
    alive = SoftDeleteManager()
class SoftDeleteManager(models.Manager):
    use_for_related_fields = True
    def get_queryset(self):
        return SoftDeleteQuerySet(self.model).filter(active=True)
Как вы см. выше я попытался убедиться, что менеджер по умолчанию-это менеджер мягкого удаления (т. е. фильтр только для активных записей), а также попробуйте использовать limit limit_choices_to, но это, оказывается, поле внешней модели только не "через" модель, которую я хотел. Если у вас есть какие-либо предложения или рекомендации, я хотел бы услышать от вас.
спасибо!
2 ответов
первая проблема: использование limit_choices_to не будет работать, так как информация:
limit_choices_toне имеет никакого эффекта при использованииManyToManyFieldС пользовательской промежуточной таблицей, указанной с помощью наVehicleBoundaryMap, а неobjectsпоэтому он игнорируется.единственный способ, который я вижу, который может работать быть:
создать прокси-модель на
VehicleBoundaryMap. Назовем этоVehicleBoundaryMapProxy. Установите его так, чтобы его менеджер по умолчанию -SoftDeleteManager()что-то типа:class VehicleBoundaryMapProxy(VehicleBoundaryMap): class Meta: proxy = True objects = SoftDeleteManager()
есть
through='VehicleBounddaryMapProxy'наManyToManyField:class Vehicle(SoftDeleteModel): routes = models.ManyToManyField('RouteBoundary', through='VehicleBoundaryMapProxy', verbose_name=_('routes'))
что, если вы просто сделаете:
class Vehicle(SoftDeleteModel):
    #you can even remove that field
    #routes = models.ManyToManyField('RouteBoundary', through='VehicleBoundaryMap', verbose_name=_('routes'),
    #                                limit_choices_to={'active': True})
    @property
    def routes(self):
        return RouteBoundary.objects.filter(
            vehicleboundarymap__active=True,
            vehicleboundarymap__vehicle=self,
        )
а теперь вместо vehicle.routes.clear() использовать vehicle.vehicleboundarymap_set.delete(). Вы потеряете только обратное отношение (RouteBoundary.vehicles), но вы можете реализовать его обратно, используя тот же способ. 
остальное M2M field функции отключен в любом случае из-за промежуточной модели.
