Django REST Framework JSON API:使用 ResourceRelatedField 时无法解析 URL 的超链接关系

Django REST Framework JSON API: Could not resolve URL for hyperlinked relationship when using ResourceRelatedField

我正在编写一个使用 django + django REST framework + django REST framework JSON API 的 HTTP API。当我尝试执行 PATCH 请求时收到此错误,

Incorrect type. Expected URL string, received OrderedDict

更新关系时。查看问题我明白我需要使用 ResourceRelatedField.

我正在尝试按照此处的文档进行操作 Related fields。下面是我的代码的样子。

urls.py

from django.conf import settings
from django.conf.urls import include, url
from rest_framework import routers
from events import views as e_views

router = routers.DefaultRouter()
router.register(r'events', e_views.EventViewSet)
router.register(r'event-types', e_views.EventTypeViewSet)

urlpatterns = [
    url(r'^', include('events.urls')),
    url(r'^', include(router.urls)),
]

events/urls.py

from django.conf.urls import url

from .views import EventRelationshipView

urlpatterns = [
    url(
        regex=r'^events/(?P<event_pk>[^/.]+)/relationships/(?P<related_field>[^/.]+)$',
        view=EventRelationshipView.as_view(),
        name='event-relationships'
    )
]

models.py

from datetime import timedelta

from django.db import models
from django.contrib.gis.db import models as gis_models


class EventType(models.Model):
    title = models.CharField(max_length=16)

    def __str__(self):
        return str(self.title)


class Event(models.Model):
    timestamp = models.DateTimeField()
    delay = models.DurationField(default=timedelta(0))
    event_type = models.ForeignKey(EventType)
    name = models.CharField(max_length=16)
    location = models.CharField(max_length=200, blank=True)
    coordinates = gis_models.PointField(null=True, blank=True)
    depth = models.CharField(max_length=64, blank=True)
    size = models.IntegerField(null=True, blank=True)
    comments = models.TextField(blank=True)
    is_virtual = models.BooleanField(default=False)
    is_visible = models.BooleanField(default=True)

    def __str__(self):
        return str(self.name)

serializers.py

from .models import Event, EventType
from rest_framework_json_api import serializers
from rest_framework_json_api.relations import ResourceRelatedField


class EventTypeSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = EventType
        fields = ('url', 'id', 'title')


class EventSerializer(serializers.HyperlinkedModelSerializer):

    included_serializers = {'event_type': EventTypeSerializer}

    # THIS PART HERE DOESN'T WORK
    event_type = ResourceRelatedField(
        queryset=EventType.objects,
        related_link_view_name='eventtype-detail',
        related_link_url_kwarg='pk',
        self_link_view_name='event-relationships'
    )

    class Meta:
        model = Event
        fields = ('url', 'id', 'timestamp', 'delay', 'event_type', 'name', 'location',
                  'coordinates', 'depth', 'size', 'comments', 'is_virtual', 'is_visible')

    class JSONAPIMeta:
        included_resources = ['event_type']

views.py

# -*- coding: utf-8 -*-
import logging

from rest_framework import viewsets
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework_json_api.parsers import JSONParser
from rest_framework_json_api.renderers import JSONRenderer
from rest_framework_json_api.views import RelationshipView

import django_filters

from .models import Event, EventType
from .serializers import EventSerializer, EventTypeSerializer


class EventFilter(django_filters.rest_framework.FilterSet):
    start_timestamp = django_filters.DateTimeFilter(name="timestamp", lookup_expr='gte')
    end_timestamp = django_filters.DateTimeFilter(name="timestamp", lookup_expr='lte')

    class Meta:
        model = Event
        fields = ['event_type', 'start_timestamp', 'end_timestamp']


class EventViewSet(viewsets.ModelViewSet):
    queryset = Event.objects.all()
    serializer_class = EventSerializer
    parser_classes = (JSONParser,)
    renderer_classes = (JSONRenderer,)
    filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
    filter_class = EventFilter
    search_fields = ('name', 'location', 'comments')
    ordering_fields = '__all__'


class EventTypeViewSet(viewsets.ModelViewSet):
    queryset = EventType.objects.all()
    serializer_class = EventTypeSerializer
    parser_classes = (JSONParser,)
    renderer_classes = (JSONRenderer,)


class EventRelationshipView(RelationshipView):
    queryset = Event.objects

class EventTypeRelationshipView(RelationshipView):
    queryset = EventType.objects

错误

[08/Feb/2017 15:07:44] ERROR [django.request:124] Internal Server Error: /events/6/
Traceback (most recent call last):
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 217, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 215, in _get_response
    response = response.render()
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/django/template/response.py", line 109, in render
    self.content = self.rendered_content
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework/response.py", line 72, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework_json_api/renderers.py", line 480, in render
    json_api_data = self.build_json_resource_obj(fields, serializer_data, resource_instance, resource_name)
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework_json_api/renderers.py", line 390, in build_json_resource_obj
    relationships = cls.extract_relationships(fields, resource, resource_instance)
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework_json_api/renderers.py", line 129, in extract_relationships
    field_links = field.get_links(resource_instance)
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework_json_api/relations.py", line 106, in get_links
    self_link = self.get_url('self', self.self_link_view_name, self_kwargs, request)
  File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework_json_api/relations.py", line 90, in get_url
    raise ImproperlyConfigured(msg % view_name)
ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "event-relationships".

在 url 参数中将 event_pk 重命名为 pk 解决了问题。