簡體   English   中英

如何在 Django REST 框架序列化程序中獲取超鏈接外鍵?

[英]How do I get a hyperlinked foreign key in Django REST Framework serializer?

我正在嘗試在我的 DRF 項目中序列化 model。 model 包含 2 個外鍵字段和一些簡單的數據類型字段。 外鍵字段之一是我的CustomUser model ,該字段在我的 API output 中顯示為超鏈接。 另一個外鍵字段指向不同的 model(如下所示)。 在過去的幾個小時里,我一直在重復同樣的幾個錯誤,因為我嘗試了其他 StackOverflow 線程中推薦的各種解決方案。

有人可以告訴我如何讓第二個外鍵作為鏈接出現在我的 API output 中嗎?

當我的代碼文件如下所示時,我在嘗試訪問localhost:8000/trade/create/localhost:8000/trader-accounts/ URL 時收到此錯誤:

django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "traderaccount-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.

當然,我在谷歌上搜索了這個錯誤消息及其部分,並嘗試了幾個 DRF 兔子洞嘗試各種事情。

交易/模型.py

class Trade(models.Model):
    trade_owner = models.ForeignKey(CustomUser, related_name='owners', on_delete=models.RESTRICT)
    trade_account = models.ForeignKey(TraderAccount, related_name='trades', on_delete=models.RESTRICT)

交易者賬戶/models.py

class TraderAccount(models.Model):

    account_owner = models.ForeignKey(
        CustomUser, on_delete=models.CASCADE,
    )
    account_name = models.CharField(
        max_length=200, blank=True, verbose_name='Account Name'
    )

api/serializers.py

class TraderAccountSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = TraderAccount
        fields = ['account_owner', 'account_name',]


class TradeSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Trade
        fields = ['trade_owner', 'trade_account', 'magic_number',]

api/views.py

class TraderAccountView(generics.ListCreateAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = TraderAccount.objects.all()
    serializer_class = TraderAccountSerializer


class TradeCreateView(generics.ListCreateAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = Trade.objects.all()
    serializer_class = TradeSerializer

api/urls.py


router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('trader-accounts/', views.TraderAccountView.as_view(), name='trader-accounts'),
    path('trade/create/', views.TradeCreateView.as_view(), name='trade-create'),

當我從api.serializers.TradeSerializer.Meta.fields中刪除'trader_account'時,我可以成功訪問localhost:8000/trade/create/端點和localhost:8000/trader-accounts/端點。

api/serializers.py

# Omit TraderAccountSerializer class for brevity in this example


class TradeSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Trade
        fields = ['trade_owner', 'magic_number',]  # Removed 'trader_account'

我一直在看這個,現在我找不到錯誤。 真的很感謝幫助!

基於這個api/views.py你有一個TraderAccountView(generics.ListCreateAPIView) 您應該將其重命名為TraderAccountList(generics.ListCreateAPIView) ,然后為詳細信息添加一個額外的視圖; TraderAccountDetail(generics.RetrieveUpdateDestroyAPIView)

api/views.py 現在是:

class TraderAccountList(generics.ListCreateAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = TraderAccount.objects.all()
    serializer_class = TraderAccountSerializer

class TraderAccountDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = TraderAccount.objects.all()
    serializer_class = TraderAccountSerializer

你的 urlpatterns 現在應該是

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('trader-accounts/', views.TraderAccountList.as_view(), name='trader-accounts'),
    path('trader-accounts/<int:pk>/', views.TraderAccountDetail.as_view()),
]

並刪除 TradeCreate。 因為您現在正在構建一個 RESTful API。 要創建交易,您可以向列表視圖發出 POST 請求以創建新交易。

在列表視圖中,您可以執行 GET 以獲取所有交易的列表,或執行 POST 以創建新交易。 在詳細視圖中,您可以執行 GET 以獲取特定交易,或執行 PUT 或 PATCH 以更新,或執行 DELETE 以刪除交易。

您是否嘗試過以與user相同的方式為account創建路由?

您包含的錯誤消息表明沒有具有預期名稱的路由。

根據https://www.django-rest-framework.org/api-guide/serializers/#how-hyperlinked-views-are-determined的文檔,為了使自動映射工作,您需要一個名為account-detail的視圖,該視圖需要 1 integer 路由參數。

正如他們所說,超鏈接的序列化程序很繁瑣,因此請密切注意文檔。 如果您更改視圖名稱,您可以在序列化程序中覆蓋它。

account = serializers.HyperlinkedRelatedField(
    view_name='account-detail', # or whatever name you give it
    ...
)

非常感謝 Gabbeh 為我指明了正確的方向。

我將TraderAccountView(generics.ListCreateAPIView)重命名為TraderAccountList(viewsets.ModelViewSet)並將此視圖添加到api/views.py

class TraderAccountDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = TraderAccount.objects.all()
    serializer_class = TraderAccountSerializer

api/urls.py文件現在是:

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
router.register(r'trader-accounts', views.TraderAccountList)

一切正常!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM