【问题标题】:Getting Django REST Framework's HyperlinkedModelSerializer to recognize non-default routes让 Django REST Framework HyperlinkedModelSerializer 识别非默认路由
【发布时间】:2014-06-01 23:41:26
【问题描述】:

我正处于使用 Django、Django REST Framework 和 SQL 的项目的早期阶段。 我对 DRF 很陌生。

我有一个模型可以跟踪游戏服务的用户信息,该游戏服务在世界各地(例如北美、欧盟等)运行不同的服务器。用户 ID 仅在每个区域中是唯一的,但用户都使用相同的模型(表)存储。我在模型的 Meta 类中使用 unique_together = ('user_id', 'region') 以确保没有重复。 请注意,数据库中的 PK 与用户 ID 无关。

默认情况下,DRF 将使用数据库的用户 PK 创建端点,但我已将其更改为使用像 /users/na/123 这样的系统来获取 user_id = 123region = 'na'(北美)的对象。来自 urls.py 的 sn-p 如下:

url(r'^users/(?P<region>.+)/$', UserList.as_view()),
url(r'^users/(?P<region>.+)/(?P<user_id>.+$)', UserDetail.as_view()),

恭敬地,这些是通用视图(generics.ListAPIView 和 generics.RetrieveAPIView)。

目前,我的其余视图都是 ViewSets。

我建模的其中一件事是历史比赛数据,其中用户通过游戏模型相关联,以跟踪谁参加了比赛,如下所示:

class Game(models.Model):
    player_1 = models.ForeignKey(User)
    player_2 = models.ForeignKey(User)

我计划像我对用户所做的那样为游戏实施路线(同样,game_id 仅在每个区域中是唯一的)所以我可以做到/game/&lt;region&gt;/&lt;game_id&gt;

我的问题是:

如何使用我在 API 上的游戏列表/详细信息视图中建立的 /user/&lt;region&gt;/&lt;user_id&gt; 路由获取指向用户的超链接?

目前,我的 GameSerializer 定义如下:

class GameSerializer(serializers.ModelSerializer):
    class Meta:
        model = Game
        exclude = ('id',)

当我将其更改为 HyperlinkedModelSerializer 时,我在访问游戏端点时收到以下错误:

无法使用视图名称解析超链接关系的 URL “用户详细信息”。您可能未能将相关模型包含在 您的 API,或者错误地配置了 lookup_field 属性 这个字段。

我认为这是因为我的用户端点的实现方式与预期不同(它不知道我已经放弃了默认的 PK 索引方法并选择了自定义路由,例如 /users/&lt;region&gt;/&lt;user_id&gt; 而不是 /users/&lt;pk&gt;,对?)

我该如何解决这个问题?我愿意接受与 DRF 无关的建议,比如重组我的 DB/Django 模型,如果我想要的方向看起来很疯狂(不想使用 PK)。

【问题讨论】:

标签: python django django-rest-framework


【解决方案1】:

经过几天的阅读和不同的思考,Meta.unique_together 有点像用 SQL 表达复合键。这导致我找到了这个解决方案:

https://groups.google.com/forum/#!topic/django-rest-framework/tHmEAzSNgG4

例如而不是使用这样的 URL 来识别员工:

api/1.3/employee/5/

我使用这样的网址:

api/1.3/company/23/employee/5/

我使用 HyperlinkedModelSerializer 序列化此模型。我 找不到将 HyperlinkedIdentityField 配置为的方法 处理复合键(只能指定单个lookup_field) 所以我改用 SerializerMethodField 覆盖 url,如下所示:

class EmployeeSerializer(serializers.HyperlinkedModelSerializer):
   url = serializers.SerializerMethodField('get_employee_detail_url')


   def get_employee_detail_url(self, obj):
       # generate the URL for the composite key
       ...
       return composite_key_url

仍在探索我的选择,但这看起来很干净。

【讨论】:

    【解决方案2】:

    我今天刚遇到同样的问题。在浏览了关于通用视图的 Django-Rest-Framework 文档后,我遇到了:

    lookup_field - 用于执行单个模型实例的对象查找的模型字段。默认为“pk”。请注意,在使用超链接 API 时,如果您需要使用自定义值,则需要确保 API 视图和序列化程序类都设置了查找字段。

    http://www.django-rest-framework.org/api-guide/generic-views

    在我的例子中,我在我的 models.py 中这样做了

    class UserDetailView(generics.RetrieveAPIView):
        model = User
        serializer_class = UserSerializer
        lookup_field = "username"
    

    ...现在工作得很好。希望对您有所帮助。

    【讨论】:

    • 谢谢,但这仅与查找单个字段的情况有关。我需要根据实际上是“复合键”的内容进行检索,也就是说,我的模型的 2 个字段加在一起对于表来说是唯一的(区域和用户 ID)。
    • 哦,是的,对不起,我应该正确阅读您的问题。我喜欢您在下面发布的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2018-03-01
    • 1970-01-01
    • 2015-09-26
    • 2013-02-17
    • 1970-01-01
    • 2017-02-01
    • 2014-03-24
    • 2019-02-27
    相关资源
    最近更新 更多