2016-07-20 19 views
0

Ich habe zwei Modelle wie folgt:Django Sortieren ManyToMany Feld in einem Nicht signifikanten Auftrag

class Stop(models.Model): 
    """ 
    Showing bus stops in İzmir. 
    """ 

    code = models.PositiveIntegerField(
     unique=True, 
     primary_key=True, 
     verbose_name="Code" 
    ) 

    label = models.CharField(
     null=False, 
     blank=False, 
     max_length=64, 
     verbose_name="Label" 
    ) 

    coor = ArrayField(
     models.FloatField(), 
     size=2, 
     verbose_name="Coordination" 
    ) 

    class Meta: 
     verbose_name = "Stop" 
     verbose_name_plural = "Stops" 
     ordering = ["label"] 

    def __str__(self): 
     return self.label 

class Route(models.Model): 
    """ 
    Bus routes of İzmir. 
    """ 

    code = models.PositiveSmallIntegerField(
     unique=True, 
     primary_key=True, 
     verbose_name="Code" 
    ) 

    stops = models.ManyToManyField(
     Stop, 
     null=True, 
     blank=True, 
     related_name="routes", 
     verbose_name="Stops" 
    ) 

    terminals = ArrayField(
     models.CharField(
      null=False, 
      blank=False, 
      max_length=32, 
     ), 
     size=2, 
     default=[], 
     verbose_name="Terminals" 
    ) 

    departure_times = ArrayField(
     ArrayField(
      models.TimeField(
       null=False, 
       blank=False 
      ), 
      null=True, 
      default=[] 
     ), 
     default=[], 
     size=6, 
     verbose_name="Departure Times" 
    ) 

    class Meta: 
     verbose_name = "Route" 
     verbose_name_plural = "Routes" 
     ordering = ["code"] 

    def __str__(self): 
     return "{}: {} - {}".format(str(self.code), self.terminals[0], self.terminals[1]) 

Wie Sie sehen können, Route hat ein ManyToManyFields die Stop Instanzen nimmt.

Ich habe die Instanzen mit einem Skript, das es ein paar Webseiten ausrangiert, es scheint, ich werde Crontab verwenden, um sie auf dem neuesten Stand zu halten. In den Daten, die ich schabe, sind Stop Objekte geordnet. Die Sache ist, dass es keinen signifikanten Filter gibt, um z.B. Eine Stop Instanz kommt nach einer anderen.

Django (oder Django Rest Framework) gibt Stop Instanzen von Route Instanz in alphabetischer Reihenfolge, z.

{ 
    "code": 285, 
    "terminals": [ 
     "EVKA 1", 
     "KONAK" 
    ], 
    "stops": [ 
     40586, 
     40633, 
     12066, 
     40645, 
     40627, 
     40647, 
     40588, 
     40592, 
     40623, 
     40016, 
     40506, 
     40508, 
     40528, 
     40462, 
     40631, 
     40014, 
     40619, 
     40530, 
     12060, 
     40661, 
     40504, 
     40488, 
     40653, 
     40590, 
     40512, 
     40464, 
     10240, 
     10036, 
     12068, 
     40514, 
     40510, 
     40658, 
     40002, 
     40649, 
     12070, 
     40004, 
     40010, 
     40656, 
     12064, 
     40614, 
     40012 
    ], 
    ... 
} 

In der stops[0] gibt eine Stop Instanz mit A und Sorten wie der Anfang.

Also, gibt es eine Möglichkeit, wie eine list in Python zu bestellen? Wie, es gibt keinen wichtigen Punkt, du fügst einfach an das Ende an und gibst es zurück.


Environment

  • Python 3.5.1
  • django 1.9.7
  • djangorestframework 3.3.3
  • psycopg2 2.6.2
  • postgresql 9,5
+0

Wenn Sie auf den 'Stop' Modell einen Zeitstempel setzen, dann könnte man auf diesem Zeitstempel basiert bestellen . –

+0

Die Sache ist, eine "Stop" -Instanz könnte zu mehr als einem Route-Objekt gehören. Selbst wenn ich einen Timestamp einsetze, würde sich das Feld "Timestamp" einer "Stop" -Instanz ändern, wenn es darum geht, eine weitere "Route" -Instanz zu erstellen. –

Antwort

1

Die position einer stop ist relativ zu einer Route, z.B. Ein Stopp kann zuerst für route 1, 2. für route 2 und usw. sein. So ist dies ein perfektes Beispiel, dass Sie mehr metadata über die Route-Stop Beziehung benötigen. Djagno löst dies, indem Sie eine Intermediate Table mit zwei ForeignKey und die metadata, die Sie für die Beziehung benötigen, zur Verfügung stellen.

class Stop(models.Model): 
    #... 

class Route(models.Model): 

    #... 

    stops = models.ManyToManyField(Stop, through='RouteStop', blank=True, related_name="routes", verbose_name="Stops") 


class RouteStop(models.Model): 
    stop = models.ForeignKey(Stop) 
    route = models.ForeignKey(Route) 
    position = models.PositiveSmallIntegerField() 

    class Meta: 
     unique_together = (("stop", "route"),) 

Wenn Sie jetzt Routes bekommen Sie route.stops von RouteStop.position bestellen, so etwas wie:

Route.objects.all().prefetch_related(
    Prefetch('stops', queryset=Stop.objects.all().order_by('routestop__position')) 
) 
+0

Sollte Ihre 'route = models.ForeignKey (Stop)' Zeile 'route = models.ForeignKey (Route)' lauten? Oder vielleicht bin ich falsch und der Code ist gültig? –

+0

Es wird auch ausgelöst, wenn ich versuche zu migrieren: 'ValueError: Kann Feld izmir.Route.stops nicht in izmir.Route.stops ändern - sie sind nicht kompatible Typen (Sie können nicht zu oder von M2M-Feldern ändern oder hinzufügen oder entfernen durch = on M2M-Felder) ' –

+0

Ja, es sollte" Route "(ein Tippfehler klar) sein. Über die Migration wird es nicht automatisch passieren, Sie müssen eine [Datenmigration] machen (http://stackoverflow.com/questions/33257530/how-to-add-through-option-to-existing-manytomanyfield- mit-Migrationen-und-Daten-i) – Todor