简体   繁体   English

Django以不重要的顺序对ManyToMany字段进行排序

[英]Django Sort ManyToMany Field in A Nonsignificant Order

I have two models as below: 我有以下两种模型:

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

As you can see, Route has a ManyToManyFields which takes Stop instances. 如您所见, Route具有一个使用Stop实例的ManyToManyFields

I put the instances with a script which it scraps a couple of web page, it seems I will use crontab to keep them updated. 我将实例与脚本放在一起,该脚本会抓取几个网页,看来我将使用crontab来保持实例更新。 In the data I am scraping, Stop objects are ordered. 在我要抓取的数据中,对Stop对象进行了排序。 The thing is, there are no significant filter to sort eg a Stop instance comes after another. 问题是,没有重要的过滤器可以进行排序,例如Stop实例接comes而至。

Django (or Django Rest Framework) returns Stop instances of Route instance in alphabetic order, eg Django(或Django Rest Framework)以字母顺序返回Route实例的Stop实例,例如

{
    "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 which stops[0] returns a Stop instance beginning with A and sorts like that. Stop stops[0]返回以A开头的Stop实例,并进行类似的排序。

So, is there a way to order like a list in Python? 那么,有没有一种方法可以像Python中的list一样进行订购? Like, there is no significant point, you just append to the end and return so. 就像,没有任何意义,您只需附加到末尾,然后返回即可。


Environment 环境

  • python 3.5.1 python 3.5.1
  • django 1.9.7 Django 1.9.7
  • djangorestframework 3.3.3 djangorestframework 3.3.3
  • psycopg2 2.6.2 psycopg2 2.6.2
  • postgresql 9.5 PostgreSQL 9.5

The position of a stop is relative to a Route , eg one stop can be first for route 1 , 2nd for route 2 and etc. So this is a perfect example that you need more metadata about the Route-Stop relation. position一的stop是相对于一个Route ,例如一个站可以先为route 1 ,第2的route 2等。因此,这是你需要更多的一个很好的例子metadata有关Route-Stop关系。 Djagno solves this by letting you provide a Intermediate Table with two ForeignKey and the metadata you need for the relation. Djagno通过为您提供一个包含两个ForeignKey和关系所需的metadata中间表来解决此问题。

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

Now when you get Routes you can order route.stops by RouteStop.position , something like: 现在,当你得到Routes ,您可以订购route.stops通过RouteStop.position ,是这样的:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM