![](/img/trans.png)
[英]Django/Django Rest Framework - How do I allow model serializer to set model's foreign key field to null?
[英]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.