Python Django/DRF-RESTAPI端点,带有查询多个端点的查询参数
嘿,伙计们,我在设计这个端点如何工作时遇到了一些麻烦。目前,我希望这个端点Python Django/DRF-RESTAPI端点,带有查询多个端点的查询参数,python,django,rest,django-rest-framework,endpoint,Python,Django,Rest,Django Rest Framework,Endpoint,嘿,伙计们,我在设计这个端点如何工作时遇到了一些麻烦。目前,我希望这个端点“/nba/players?date=01012016”通过两个不同的端点来获得结果 目前,我的GameDates端点返回类似于 {id: 1, home_team_id: 1, away_team_id: 2, date: "1/1/2016"}, {id: 4, home_team_id: 2, away_team_id: 3, date: "1/2/2016"} 我想获取GameDate_id或它的主键(在本例中为
“/nba/players?date=01012016”
通过两个不同的端点来获得结果
目前,我的GameDates端点返回类似于
{id: 1, home_team_id: 1, away_team_id: 2, date: "1/1/2016"},
{id: 4, home_team_id: 2, away_team_id: 3, date: "1/2/2016"}
我想获取GameDate_id或它的主键(在本例中为id:1),然后将其传递到另一个PlayerStatistic端点,该端点将返回如下内容-
{id: 1, game_id: 1, player_id: 1, team_id: 1, points: 20, assists: 10, rebounds: 2},
{id: 2, game_id: 1, player_id: 2, team_id: 1, points: 15, assists: 2, rebounds: 2},
{id: 3, game_id: 1, player_id: 3, team_id: 2, points: 10, assists: 2, rebounds: 20},
{id: 4, game_id: 1, player_id: 4, team_id: 2, points: 5, assists: 1, rebounds: 2}
我的带有日期查询的初始端点将返回这四个JSON,因为玩家在该日期(game_id=1)从GameDate端点有一个游戏,然后该game_id用于查询
PlayerStatistic端点和返回
我知道覆盖get_queryset函数的正确方法,比如-
def get_queryset(self):
date = self.request.query_params.get('date')
queryset = self.queryset
if date:
# the rest here?
获取参数,但我不确定如何从那里开始
编辑-在下面添加了我的模型-
class Player(models.Model):
# class for Player model
name = models.CharField(max_length=100)
team_id = models.ForeignKey(Team, on_delete=models.CASCADE)
class GameDate(models.Model):
# class for GameDate model
home_team_id = models.ForeignKey(Team, related_name='home_games',
on_delete=models.CASCADE)
away_team_id = models.ForeignKey(Team, related_name='away_games',
on_delete=models.CASCADE)
date = models.DateField()
class PlayerStatistic(models.Model):
# class for individual player statistics
game_id = models.ForeignKey(GameDate, on_delete=models.CASCADE)
player_id = models.ForeignKey(Player, on_delete=models.CASCADE)
team_id = models.ForeignKey(Team, on_delete=models.CASCADE)
points = models.IntegerField()
assists = models.IntegerField()
rebounds = models.IntegerField()
请从所有
外键
字段中删除\u id
,这会造成非常混乱的代码:如果你有玩家
实例,那么玩家。团队id
是一个团队
实例(不是团队id),而玩家。团队id
是id。看看有多混乱
因此,假设您已删除所有\u id
,下面介绍如何获取特定日期的所有玩家统计信息:
PlayerStatistics.objects.filter(game__date=date)
# or inside `get_queryset(self)`:
super().get_queryset().filter(game__date=date)
您可以按游戏进一步排序(如果同一日期有多个游戏),然后是团队和最高分数:
PlayerStatistics.objects.filter(game__date=date).order_by('game', 'team', '-points')
date
需要是一个datetime.date
对象,因此如果您的输入是一个字符串,请确保首先将其转换为正确的日期对象
如果您实际列出了某个特定日期的Player
实例(并希望嵌套每个玩家的相关统计数据):
在这里,我更改了主队
和客队
字段中的相关
名称,因为它们用于反向关系,正如您在这里看到的(从一个队到另一个比赛),因此它们应该包含比赛
而不是球队
如果您只想要已记录统计数据的播放器,请尝试以下操作:
from django.db.models import Exists, OuterRef
player_stats = PlayerStatistics.objects.filter(game__date=date, player=OuterRef('pk'))
Player.objects.filter(
Q(team__home_games__date=date)
| Q(team__away_games__date=date))\
.annotate(has_stats=Exists(player_stats))
.filter(has_stats=True)
.prefetch_related('playerstatistics'
你想错了。您不能从另一个端点调用端点,至少没有必要这样做。您只需调用playerstats端点,并根据日期正确筛选玩家查询集。向我们展示您的游戏和玩家模型(或玩家统计)。@DirkRoten我已经用我的模型更新了我的帖子。如果没有日期,您希望url/players从PlayerViewset返回结果,这有点奇怪,但是如果有日期作为查询参数,它将返回一个完全不同的资源,即PlayerStatisticsViewset。它应该返回相同的列表,但以某种方式使用日期进行过滤。您可能希望将/players和/player stats分离为不同的URL。在设计API时,仔细考虑各种URL是很重要的。资源
游戏
的良好REST API是:获取/games/返回游戏
列表,可以添加过滤器(/games/?date=xxx)。发布/游戏/创建新游戏。GET/games/id获取特定游戏,POST/games/id更新现有游戏。删除有点棘手(应该是Delete/games/id,但浏览器不执行删除),所以我通常会执行POST/games/id/Delete。这在我看来很好,“返回在特定日期玩过的所有玩家”将是Player.objects.filter(Q(team\u home\u games\u date=date)| Q(team\u away\u games\u date=date))
然后在序列化程序中,如果你想添加统计数据,只需为玩家嵌套PlayerStatistics
。但这一切都在PlayerViewSet
中,没错。提到
from django.db.models import Exists, OuterRef
player_stats = PlayerStatistics.objects.filter(game__date=date, player=OuterRef('pk'))
Player.objects.filter(
Q(team__home_games__date=date)
| Q(team__away_games__date=date))\
.annotate(has_stats=Exists(player_stats))
.filter(has_stats=True)
.prefetch_related('playerstatistics'