2016-06-10 6 views
6

Ich versuche ein Geofencing für eine Flotte von LKWs zu implementieren. Ich muss einem Fahrzeug eine Liste von Grenzen zuordnen. Darüber hinaus ist eine der Voraussetzungen, alles zu behalten, auch wenn es zu Prüfzwecken gelöscht wird. Daher müssen wir Soft Delete für alles implementieren. Hier liegt das Problem. Mein Viele-zu-viele-Feld entspricht nicht dem Soft-Lösch-Manager, es enthält sowohl die aktiven als auch die inaktiven Datensätze im Such-Dataset.Wie wird gefiltert? Modell eines Viele-zu-Viele-Feldes?

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) 

Wie Sie sehen oben ich sicher, dass Standard-Manager zu machen versucht, ist ein weicher Lösch-Manager (dh. Filter für aktive Datensätze nur) und auch Nutzgrenze limit_choices_to versuchen aber, dass sich herausstellen das ausländische Modell Feld nicht nur das "durch" -Modell, das ich wollte. Wenn Sie irgendwelche Vorschläge oder Empfehlungen haben, würde ich mich freuen, von Ihnen zu hören.

Danke!

+0

Statt Soft-Deletes selbst zu implementieren, verwenden Sie etwas wie [Django-Reversion] (https://github.com/etianen/django-reversion). – Anonymous

+0

Das soft delete ist bereits überall implementiert, ich kann es nicht mehr ändern. Ich wünschte, wir würden Reversion verwenden, es würde uns viele Kopfschmerzen ersparen. –

Antwort

5

Erstes Problem: Ihre Verwendung von limit_choices_to nicht, weil Arbeit als documentation says:

limit_choices_to hat keine Wirkung, wenn sie auf einem ManyToManyField mit einer benutzerdefinierten Zwischentabelle verwendet spezifizierte mit dem through Parameter.

Sie verwenden through, also limit_choices_to hat keine Wirkung.

Zweites Problem: Ihre Verwendung von use_for_related_fields = True ist auch unwirksam. Die documentation sagt über dieses Attribut:

Wenn dieses Attribut auf den Standard Manager für ein Modell (nur der Standardmanager in diesen Situationen in Betracht gezogen wird) gesetzt ist, wird Django diese Klasse verwenden, wenn es automatisch muss erstellen ein Manager für die Klasse.

Dein personalisierter Manager ist mit dem eher alive Attribut VehicleBoundaryMap zugewiesen als objects so wird er ignoriert.

Der einzige Weg, ich sehe das wäre funktionieren kann:

  1. erstellen proxy model für VehicleBoundaryMap. Nennen wir es VehicleBoundaryMapProxy. Stellen Sie es so, dass seine Standardmanager SoftDeleteManager() ist so etwas wie:

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

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

Lassen Sie mich dies versuchen, bis jetzt sieht es vielversprechend aus. –

+0

Es funktioniert ganz schön, danke Louis für die Lösung. –

+0

Gern geschehen! – Louis

1

Was ist, wenn Sie gerade tun:

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, 
     ) 

Und jetzt anstelle von vehicle.routes.clear()verwenden. Sie werden nur die umgekehrte Beziehung verlieren (RouteBoundary.vehicles), aber Sie können es auf die gleiche Weise zurück implementieren.

Der Rest der M2M field Features sind disabled sowieso wegen des Zwischenmodells.

+0

Ich mag deine Idee, es kinna außerhalb der Box. Aber da ich Prefetch nicht benutzen kann, ist das ein großes Nein für mich. –