I am writing an HTTP API that uses django + django REST framework + django REST framework JSON API. When I tried to do PATCH request I received this error,
Incorrect type. Expected URL string, received OrderedDict
when updating relationship. Looking through issues I understood I need to use ResourceRelatedField.
I'm trying to follow documentation here Related fields. Below is how my code looks like.
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
Error
[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".
Renaming event_pk
to pk
in url argument solved the problem.