Reputation: 3149
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.
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. In the data I am scraping, Stop
objects are ordered. The thing is, there are no significant filter to sort e.g. a Stop
instance comes after another.
Django (or Django Rest Framework) returns Stop
instances of Route
instance in alphabetic order, e.g.
{
"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.
So, is there a way to order like a list
in Python? Like, there is no significant point, you just append to the end and return so.
Upvotes: 0
Views: 623
Reputation: 16030
The position
of a stop
is relative to a Route
, e.g. 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. Djagno solves this by letting you provide a Intermediate Table with two ForeignKey
and the metadata
you need for the relation.
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:
Route.objects.all().prefetch_related(
Prefetch('stops', queryset=Stop.objects.all().order_by('routestop__position'))
)
Upvotes: 1