简体   繁体   中英

How can I sort a django queryset by a value from a different table?

I have these models:

class NHLTeam(models.Model):
    team_name = models.CharField(max_length=50)
    team_id = models.IntegerField()  # The NHL API gives each team an id. Probably useful to save it.
    city = models.CharField(max_length=50)

class NHLGame(models.Model):
    home_team = models.ForeignKey(NHLTeam, on_delete=models.CASCADE, related_name="home_team")
    away_team = models.ForeignKey(NHLTeam, on_delete=models.CASCADE, related_name="away_team")
    date = models.DateField()

class Distance(models.Model):
    destination = models.ForeignKey(NHLTeam, on_delete=models.CASCADE)
    starting_country = models.CharField(max_length=2,
                                        choices=COUNTRY_CHOICES)
    starting_province = models.CharField(max_length=50)
    starting_city = models.CharField(max_length=50)
    distance = models.DecimalField(decimal_places=1, max_digits=6)

So basically NHLTeam just contains the 31 teams currently in the NHL. NHLGame represents an actual game which contains a home_team, away_team and a date. Distance contains the distance from the city the user lives in to the team. If I get a list of the NHLGames with NHLGame.objects.all() I get this:

<QuerySet [<NHLGame: 2021-02-05: Boston Bruins @ Philadelphia Flyers>, <NHLGame: 2021-02-05: Detroit Red Wings @ Tampa Bay Lightning>, <NHLGame: 2021-02-05: Nashville Predators @ Florida Panthers>, <NHLGame: 2021-02-05: Los Angeles Kings @ Vegas Golden Knights>, <NHLGame: 2021-02-05: San Jose Sharks @ Anaheim Ducks>, ....]>

If I want to sort this by the Home team name i can do games.order_by('home_team__team_name') which gives me:

<QuerySet [<NHLGame: 2021-02-05: San Jose Sharks @ Anaheim Ducks>, <NHLGame: 2021-02-06: San Jose Sharks @ Anaheim Ducks>, <NHLGame: 2021-02-18: Minnesota Wild @ Anaheim Ducks>, <NHLGame: 2021-02-20: Minnesota Wild @ Anaheim Ducks>, <NHLGame: 2021-02-27: Vegas Golden Knights @ Anaheim Ducks>, <NHLGame: 2021-02-12: St. Louis Blues @ Arizona Coyotes>, <NHLGame: 2021-02-13: St. Louis Blues @ Arizona Coyotes>, ....]>

but how can I sort my games by the distance they are from a certain city? Is this possible? One thing I did was:

all_teams = NHLTeam.objects.all()
distances = {}
for team in all_teams:
    distance_object = Distance.objects.filter(starting_country=country, starting_province=province, starting_city=city, destination=team)
    distance = distance_object[0].distance
    distances[team.team_name] = float(distance)
sorted_list_of_games = sorted(games, key=lambda game: distances[game.home_team.team_name])

After this sorted_list_of_games is the list of games sorted by distance however it returns a list whereas I need a queryset sorted in that order. Is this possible?

my_filter = Min('home_team__distance__distance',
                filter=(Q(home_team__distance__starting_country=country) &
                        Q(home_team__distance__starting_province=province) &
                        Q(home_team__distance__starting_city=city)))
sorted_queryset = queryset.annotate(distances=my_filter).order_by(
    "distances" if not is_descending else "-distances")

I ended up solving it with this. The Min should be fine since it should be impossible for it to have more than one distance from a city to a team.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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