Why can't Django REST Framework's HyperlinkedModelSerializer form URL?

烂漫一生 提交于 2020-05-15 18:39:27

问题


New to DRF and everything works as long as I don't include 'url' in fields. Here's what I've got:

Serializer:

class TaskSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Task
        fields = ('pk', 'short_desc', 'scheduled_date')

View Set:

class TaskViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Task.objects.all().order_by('scheduled_date')
    serializer_class = TaskSerializer

URLs:

router = routers.DefaultRouter()
router.register(r'tasks', views.TaskViewSet)

urlpatterns = [

    [... bunch of non-REST URLs]

    # REST API
    url(r'^', include(router.urls)),

At runtime, printing router.urls gives me:

<RegexURLPattern api-root ^$>
<RegexURLPattern api-root ^\.(?P<format>[a-z0-9]+)/?$>
<RegexURLPattern task-list ^tasks/$>
<RegexURLPattern task-list ^tasks\.(?P<format>[a-z0-9]+)/?$>
<RegexURLPattern task-detail ^tasks/(?P<pk>[^/.]+)/$>
<RegexURLPattern task-detail ^tasks/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$>

Both [...]/tasks/ and [...]/tasks/123/ work if I type them into my browser, which leads me to believe that task-list and task-detail views do, in fact exist.

Now I introduce a problem by adding 'url' to the serializer:

class TaskSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Task
        fields = ('url', 'pk', 'short_desc', 'scheduled_date')

After adding 'url' to fields, I get the following error:

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

The DRF docs say:

There needs to be a way of determining which views should be used for hyperlinking to model instances. By default hyperlinks are expected to correspond to a view name that matches the style '{model_name}-detail', and looks up the instance by a pk keyword argument.

Since I've verified that task-detail exists and that the corresponding URL [...]/tasks/123/ works, I can't for the life of me figure out why DRF can't form the URL. Any ideas?


回答1:


Inspired by clues revealed by Kunkka's answer, I have a solution that looks like this:

class TaskSerializer(serializers.HyperlinkedModelSerializer):

    url = serializers.HyperlinkedIdentityField(view_name="task:task-detail")

    class Meta:
        model = Task
        fields = ('url', 'pk', 'short_desc', 'scheduled_date')

I.e. I've added an url = [...] line to the serializer I originally posted in my question. This solves the lookup problem which was presumably caused by DRF not knowing that 'task-detail' is actually in the 'task' namespace.

Any better solutions?




回答2:


Can you try this?

class TaskSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.SerializerMethodField()
    class Meta:
        model = Task
        fields = ('pk','url', 'short_desc', 'scheduled_date')

    def get_url(self,obj):
        request = self.context['request']
        return = {'self':reverse('task-detail',kwargs={'pk':obj.pk},request=request)}


来源:https://stackoverflow.com/questions/33201520/why-cant-django-rest-frameworks-hyperlinkedmodelserializer-form-url

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!