2016-06-10 194 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

我喜歡你的想法,它在盒子外面跳動。但是因爲我不能使用預取,所以對我來說這是一個很大的不行。 –