Jimmyn Jimmyn - 1 year ago 212
Python Question

Django Restful Framework Authentication HTTP Post Error

I was following the Django restful framework tutorial and I came across a error at the "Authenticating with the API" step. I've retraced myself however can't seem to see where I went wrong. Basically when I go to post to my API i get an error see below. Ideally I would also like to setup permissions which state "access denied" unless object owner - any advice on this would be greatly appreciated.

http -a jimmynos:password POST http://127.0.0.1:8000/snippets/ code="print 789"


Some of the error:

IntegrityError at /snippets/
NOT NULL constraint failed: snippets_snippet.owner_id

Request Method: POST
Request URL: http://127.0.0.1:8000/snippets/
Django Version: 1.9.9
Python Executable: /Users/james/Documents/django/tutorialSerialization/env/bin/python
Python Version: 2.7.10
Python Path: ['/Users/james/Documents/django/tutorialSerialization/tutorial', '/Users/james/Documents/django/tutorialSerialization/env/lib/python27.zip', '/User


views.py

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth.models import User
from snippets.serializers import UserSerializer
from rest_framework import generics
from rest_framework import permissions
from snippets.permissions import IsOwnerOrReadOnly


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


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

class SnippetList(APIView):
"""
List all snippets, or create a new snippet.
"""
permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,)

def get(self, request, format=None):
#snippets = Snippet.objects.all()
snippets = Snippet.objects.filter(owner=self.request.user)
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)

def post(self, request, format=None):
serializer = SnippetSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

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


class SnippetDetail(APIView):
"""
Retrieve, update or delete a snippet instance.
"""
permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,)
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404

def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)

def put(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

def delete(self, request, pk, format=None):
snippet = self.get_object(pk)
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)


serializers.py

from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
from django.contrib.auth.models import User


class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Snippet
#owner = serializers.ReadOnlyField(source='owner.username')
fields = ('id', 'title', 'code', 'linenos', 'language', 'style', 'owner')


class UserSerializer(serializers.ModelSerializer):
snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())

class Meta:
model = User
fields = ('id', 'username', 'snippets')


permissions.py

from rest_framework import permissions


class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Custom permission to only allow owners of an object to edit it.
"""

def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True

# Write permissions are only allowed to the owner of the snippet.
return obj.owner == request.user


The error must have something to do with

owner = serializers.ReadOnlyField(source='owner.username')


or

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


models.py

from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles


LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())


class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
owner = models.ForeignKey('auth.User', related_name='snippets')
highlighted = models.TextField()

class Meta:
ordering = ('created',)


Enviroment:

Python 2.7.10 on MAC
Django==1.9.9
djangorestframework==3.4.6
Pygments==2.1.3


Django Restful Framework API

Answer Source

The error should be owner = serializers.ReadOnlyField(source='owner.username')

Your serializer need owner to create Snippet instance.

If you let owner to be readonly, then you will lack the owner field, therefore it failed to create snippet instance.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download