to_representation() must be implemented (Tutorial part 5)

3,549 views
Skip to first unread message

Matt Sencenbaugh

unread,
Dec 11, 2014, 2:26:46 AM12/11/14
to django-res...@googlegroups.com
Hey guys,

I've been following the tutorial for REST Framework 3.0 (although substituting 'snippets' with my own model 'articles' which is a representation of a news article), but I'm getting hung up on an error in part 5 when changing the serializer to a HyperlinkedModelSerializer. The exact error when I try to hit any article endpoint is:

NotImplementedError at /articles/
to_representation() must be implemented.

Relevant code..

Models.py
from django.db import models

class Article(models.Model):
    owner = models.ForeignKey('auth.User', related_name='articles')
    created = models.DateTimeField(auto_now_add=True)
    published = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=250)
    author = models.CharField(max_length=100)
    #content contains raw html that will be rendered at a special endpoint
    content = models.TextField()

    class Meta:
        ordering = ('created',)

Serializers.py
from rest_framework import serializers
from shittr_api.models import Article
from django.contrib.auth.models import User


class ArticleSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.Field(source='owner.username')
    render = serializers.HyperlinkedIdentityField(view_name='article-render', format='html')

    class Meta:
        model = Article
        fields = ('url', 'render', 'title', 'author', 'content', 'owner')


class UserSerializer(serializers.HyperlinkedModelSerializer):
    articles = serializers.HyperlinkedRelatedField(many=True, view_name='article-detail', read_only=True)

    class Meta:
        model = User
        fields = ('url', 'username', 'articles')

Views.py
from shittr_api.models import Article
from shittr_api.serializers import ArticleSerializer
from shittr_api.serializers import UserSerializer
from shittr_api.permissions import IsOwnerOrReadOnly
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework import generics
from rest_framework import permissions
from django.contrib.auth.models import User
from rest_framework import renderers
from rest_framework.response import Response


@api_view(('GET',))
def api_root(request, format=None):
    return Response({
        'users': reverse('user-list', request=request, format=format),
        'articles': reverse('article-list', request=request, format=format)
    })


class UserList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class ArticleList(generics.ListCreateAPIView):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)


class ArticleDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly)


class ArticleRender(generics.GenericAPIView):
    queryset = Article.objects.all()
    renderer_classes = (renderers.StaticHTMLRenderer,)

    def get(self, request, *args, **kwargs):
        article = self.get_object()
        return Response(article.content)

Urls.py
from django.conf.urls import patterns, url
from rest_framework.urlpatterns import format_suffix_patterns
from shittr_api import views
from django.conf.urls import include

urlpatterns = [
url(r'^$', views.api_root),
    url(r'^articles/$', views.ArticleList.as_view(),name='article-list'),
    url(r'^articles/(?P<pk>[0-9]+)$', views.ArticleDetail.as_view(),name='article-detail'),
url(r'^articles/(?P<pk>[0-9]+)/render/$', views.ArticleRender.as_view(),name='article-render'),
    url(r'^users/$', views.UserList.as_view(),name='user-list'),
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view(),name='user-detail'),
]

urlpatterns += [
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

Permissions.py
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    Custom permission to allow only owners to edit objects
    """

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True

        return obj.owner == request.user


Any idea what's going on?

Tom Christie

unread,
Dec 11, 2014, 4:43:20 AM12/11/14
to django-res...@googlegroups.com
Hi Matt,

`serializers.Field` there should have been changed to `serializers.ReadOnlyField` for 3.0.
I've gone and made that fix now.
Thanks for raising the issue!

  Tom

Matt Sencenbaugh

unread,
Dec 11, 2014, 11:00:21 AM12/11/14
to django-res...@googlegroups.com
Thanks for the quick reply, all working now!

Scot Hacker

unread,
Jan 4, 2015, 3:09:51 AM1/4/15
to django-res...@googlegroups.com


On Thursday, December 11, 2014 1:43:20 AM UTC-8, Tom Christie wrote:
Hi Matt,

`serializers.Field` there should have been changed to `serializers.ReadOnlyField` for 3.0.
I've gone and made that fix now.
Thanks for raising the issue!


Ah yes, that does fix it, thanks. This is a pretty confusing error when upgrading from 2.4.x to 3.0.x as the traceback doesn't give any clue as to where in one's codebase (which class, which field) is triggering the error.

./s


Reply all
Reply to author
Forward
0 new messages