2016-06-10 195 views
6

我正在尝试为一队卡车实施地理围栏。我必须将一系列边界与车辆联系起来。除此之外,其中一项要求是保留所有内容,即使一旦删除以用于审计目的。因此,我们必须对所有内容实施软删除。这是问题所在。我的许多字段不符合软删除管理器,它包含查找数据集中的活动记录和非活动记录。如何过滤多对多字段的模型?

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但转出到外地外国模型只不我想要的“通过”模式。如果您有任何建议或建议,我很乐意听取您的意见。

谢谢!

+0

不要自己实施软删除,而应使用类似[django-reversion](https://github.com/etianen/django-reversion)的东西。 – Anonymous

+0

那软删除已经到处都已经实现了,我无法再改变它了。我希望我们会使用逆转,它会为我们节省很多头痛。 –

回答

5

第一个问题:使用自定义中间表使用through参数指定在ManyToManyField使用时

limit_choices_to没有任何效果:你的limit_choices_to使用不会因为随着documentation says工作。

您正在使用through所以limit_choices_to没有效果。

第二个问题:您使用use_for_related_fields = True也是无效的。该documentation说,关于这个属性:

如果这个属性在默认经理设定的模型(只默认管理器在这些情况下考虑),Django会使用这个类,每当它需要自动创建班级经理。

您的自定义的经理被分配到alive属性VehicleBoundaryMap而不是objects因此将其忽略。

的一个方式,我看到它可以工作将是:

  1. 创建proxy modelVehicleBoundaryMap。我们称之为VehicleBoundaryMapProxy。设置它,以便其默认经理SoftDeleteManager()喜欢的东西:

    class VehicleBoundaryMapProxy(VehicleBoundaryMap): 
        class Meta: 
         proxy = True 
    
        objects = SoftDeleteManager() 
    
  2. through='VehicleBounddaryMapProxy'ManyToManyField

    class Vehicle(SoftDeleteModel): 
        routes = models.ManyToManyField('RouteBoundary', 
                through='VehicleBoundaryMapProxy', 
                verbose_name=_('routes')) 
    
+0

让我试试看,到目前为止它看起来很有希望。 –

+0

它的作品非常漂亮,感谢路易斯的解决方案。 –

+0

不客气! – Louis

1

怎么样,如果你只是做:

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无论如何因为中间模型。

+0

我喜欢你的想法,它在盒子外面跳动。但是因为我不能使用预取,所以对我来说这是一个很大的不行。 –