我尝试将 Django Rest Framework (DRF) 与 HyperlinkedModelSerializers、ViewSets 和 Router 结合使用。
当我检查生成的路由时,Django 向我显示
vehicle-detail
,但 DRF 抱怨错误:
ImproperlyConfigured at /api/vehicles/
Could not resolve URL for hyperlinked relationship using view name "vehicle-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
如果从字段中省略
url
,下面的代码效果很好。
有人知道缺少什么吗?
from rest_framework.routers import DefaultRouter
from vehicles import viewsets
# Create a router and register our ViewSets with it.
router = DefaultRouter()
router.register(r'vehicles',
viewsets.VehicleViewSet,
basename='vehicle')
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('', include(router.urls)),
]
class VehicleViewSet(viewsets.ModelViewSet):
queryset = Vehicle.objects.all()
serializer_class = VehicleSerializer
class VehicleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Vehicle
fields = ['url', 'name', 'description']
# fields = ['name', 'description'] # Removed 'url'. Now the API works
api/ ^vehicles/$ [name='vehicle-list']
api/ ^vehicles\.(?P<format>[a-z0-9]+)/?$ [name='vehicle-list']
api/ ^vehicles/(?P<pk>[^/.]+)/$ [name='vehicle-detail']
api/ ^vehicles/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='vehicle-detail']
api/ [name='api-root']
api/ <drf_format_suffix:format> [name='api-root']
Django 5.1
djangorestframework 3.15.2
问题是 url 命名空间!
在 https://www.django-rest-framework.org/api-guide/routers/ 上指出:
如果将命名空间与超链接序列化器一起使用,您还需要确保序列化器上的任何 view_name 参数正确反映命名空间。在上面的示例中,您需要包含一个参数,例如 view_name='app_name:user-detail' 用于超链接到用户详细信息视图的序列化器字段。
urlpatterns = [
path('admin/', admin.site.urls),
path('api/auth/', include('rest_framework.urls', namespace='rest_framework')),
path('api/', include(('api.urls', 'api'), namespace='api')),
]
我在 path('api/', include(('api.urls', 'api'), namespace='api'))
中使用命名空间
api。
我还需要在序列化器中提供命名空间:
class VehicleSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='api:vehicle-detail')
class Meta:
model = Vehicle
fields = ['url', 'name', 'description']