如何通过多对多字段的模型进行过滤?
How to filter through Model of a many-to-many field?
我正在尝试为卡车车队实施地理围栏。我必须将边界列表与车辆相关联。最重要的是,其中一项要求是保留所有内容,即使出于审计目的而将其删除。因此我们必须对所有内容进行软删除。这就是问题所在。我的多对多字段不符合软删除管理器,它包括查找数据集中的活动记录和非活动记录。
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_choices_to 但结果是外来模型只是不是我想要的 "through" 型号。如果您有任何建议或建议,我很乐意听取您的意见。
谢谢!
第一个问题:您对 limit_choices_to
的使用不起作用,因为 documentation says:
limit_choices_to
has no effect when used on a ManyToManyField
with a custom intermediate table specified using the through
parameter.
您正在使用 through
,因此 limit_choices_to
无效。
第二个问题:你使用use_for_related_fields = True
也是无效的。 documentation 表示这个属性:
If this attribute is set on the default manager for a model (only the default manager is considered in these situations), Django will use that class whenever it needs to automatically create a manager for the class.
您的自定义管理器分配给了 VehicleBoundaryMap
的 alive
属性,而不是 objects
,因此它被忽略了。
我认为可能有效的一种方法是:
为 VehicleBoundaryMap
创建一个 proxy model。我们称它为 VehicleBoundaryMapProxy
。设置它,使其默认管理器是 SoftDeleteManager()
类似于:
class VehicleBoundaryMapProxy(VehicleBoundaryMap):
class Meta:
proxy = True
objects = SoftDeleteManager()
你的ManyToManyField
有through='VehicleBounddaryMapProxy'
:
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
特征无论如何都是 disabled 因为中间模型。
我正在尝试为卡车车队实施地理围栏。我必须将边界列表与车辆相关联。最重要的是,其中一项要求是保留所有内容,即使出于审计目的而将其删除。因此我们必须对所有内容进行软删除。这就是问题所在。我的多对多字段不符合软删除管理器,它包括查找数据集中的活动记录和非活动记录。
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_choices_to 但结果是外来模型只是不是我想要的 "through" 型号。如果您有任何建议或建议,我很乐意听取您的意见。
谢谢!
第一个问题:您对 limit_choices_to
的使用不起作用,因为 documentation says:
limit_choices_to
has no effect when used on aManyToManyField
with a custom intermediate table specified using thethrough
parameter.
您正在使用 through
,因此 limit_choices_to
无效。
第二个问题:你使用use_for_related_fields = True
也是无效的。 documentation 表示这个属性:
If this attribute is set on the default manager for a model (only the default manager is considered in these situations), Django will use that class whenever it needs to automatically create a manager for the class.
您的自定义管理器分配给了 VehicleBoundaryMap
的 alive
属性,而不是 objects
,因此它被忽略了。
我认为可能有效的一种方法是:
为
VehicleBoundaryMap
创建一个 proxy model。我们称它为VehicleBoundaryMapProxy
。设置它,使其默认管理器是SoftDeleteManager()
类似于:class VehicleBoundaryMapProxy(VehicleBoundaryMap): class Meta: proxy = True objects = SoftDeleteManager()
你的
ManyToManyField
有through='VehicleBounddaryMapProxy'
: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
特征无论如何都是 disabled 因为中间模型。