Django-Rest-Framework 实现URL携带关联字段ID的接口端点配置
实现方案
你现有代码存在缩进错误、路由参数不匹配、路由注册逻辑错误几个问题,按以下步骤修改即可。
现有基础信息
你定义的MarketHistoryListing模型如下:
class MarketHistoryListing(auto_prefetch.Model): player_profile = auto_prefetch.ForeignKey(PlayerProfile, on_delete=models.SET_NULL, null=True) sales_minute = models.DecimalField( max_digits=1000, decimal_places=2, null=True)
需求目标:实现路径为 /api/market-history/<player_profile._id> 的接口,返回指定player_profile关联的所有MarketHistoryListing记录。
第一步:修正视图代码
你原来写的get_queryset方法缩进错误,被定义在了ViewSet类外部,根本不会被调用,同时类顶层写死全量queryset有数据越权风险,修正后代码:
from rest_framework import viewsets class MarketHistoryListingView(viewsets.ModelViewSet): serializer_class = MarketHistoryListingSerializer pagination_class = LargeResultsSetPagination def get_queryset(self): # 取路由中传递的玩家ID,参数名和后续路由配置保持一致 player_id = self.kwargs["player_pk"] # 直接用外键字段_id过滤,减少一次数据库查询 return MarketHistoryListing.objects.filter(player_profile_id=player_id)
第二步:配置URL路由
你之前的路由代码存在拼写错误(market-hitory少写了s),且错误地将动态参数占位符传给了router的register方法——router.register第一个参数是资源名,不是路径参数段。根据你要的路径格式,推荐直接用基础路由配置,不需要嵌套路由:
from django.urls import path from rest_framework.routers import DefaultRouter from . import views router = DefaultRouter() urlpatterns = [ # 直接匹配目标路径格式,绑定list动作 path( "api/market-history/<int:player_pk>/", views.MarketHistoryListingView.as_view({"get": "list"}), name="market-history-list" ), # 如果需要单条记录的详情、编辑、删除接口,补充对应路径即可 ] urlpatterns += router.urls
如果你的PlayerProfile主键是UUID类型,把路径参数<int:player_pk>替换为<uuid:player_pk>即可。
可选:嵌套路由写法
如果你是要把市场历史接口挂在玩家资源路径下(生成路径格式为/api/player-profile/<player_pk>/market-history/),再用NestedSimpleRouter,配置如下:
from rest_framework_nested import routers from . import views # 主路由注册玩家资源 router = routers.DefaultRouter() router.register(r"player-profile", views.PlayerProfileView, basename="player-profile") # 配置嵌套子路由 market_history_router = routers.NestedSimpleRouter( router, r"player-profile", # 父级资源名 lookup="player" # 自动生成的路径参数名为 player_pk,和视图中取的kwarg对应 ) # 注册子资源,第一个参数传子资源名,不要传动态占位符 market_history_router.register( r"market-history", views.MarketHistoryListingView, basename="player-market-history" ) urlpatterns = [] urlpatterns += router.urls + market_history_router.urls
验证方式
- 安装
django-extensions后执行python manage.py show_urls,可以查看所有生成的路由路径、参数名、绑定的视图方法,确认匹配预期 - 测试接口时传入不同玩家ID,确认返回结果仅对应当前传入ID的关联数据,没有出现全量数据泄露。
内容的提问来源于stack exchange,提问作者JeremyE
相关产品推荐
相关产品推荐

