Reputation: 140
I'm playing with DRF and made a simple blog where anonymous people can comment on a blog post. I'm just using the browsable API at the moment, and everything seems to work fine until I try to post a comment. DELETE, GET, and PUT all work as expected, only POST.
The error I get is IntegrityError at /api/posts/i-had-a-blog-his-name-was-bingo/comments/: blog_comment.blogpost_id may not be NULL
I've searched thoroughly for an answer as to why this might be happening, but nothing is helping. Here's my code...
models.py
class BlogPost(models.Model):
created = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey('auth.User', related_name='posts')
title = models.CharField(max_length=100, unique=True)
content = models.TextField()
slug = models.SlugField(max_length=100, unique=True, editable=False)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(BlogPost, self).save(*args, **kwargs)
@permalink
def get_absolute_url(self):
return ('post-detail', { 'slug': self.slug })
class Meta:
ordering = ('created',)
class Comment(models.Model):
created = models.DateTimeField(auto_now_add=True)
blogpost = models.ForeignKey(BlogPost, related_name='comments')
author = models.CharField(max_length=100, blank=False)
content = models.TextField()
class Meta:
ordering = ('created', 'author', 'content')
serializers.py
class CommentSerializer(serializers.HyperlinkedModelSerializer):
post = serializers.Field(source='blogpost.title')
class Meta:
model = Comment
fields = ('id', 'author', 'content', 'post')
class BlogPostSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.Field(source='owner.username')
url = serializers.HyperlinkedIdentityField(view_name='post-detail')
comments = serializers.HyperlinkedIdentityField(view_name='comment-list')
class Meta:
model = BlogPost
fields = ('url', 'id', 'title', 'content', 'owner', 'comments')
views.py
class CommentList(generics.ListCreateAPIView):
serializer_class = CommentSerializer
def get_queryset(self):
slug = self.kwargs['slug']
return Comment.objects.filter(blogpost__slug=slug)
class CommentDetail(generics.RetrieveUpdateDestroyAPIView):
serializer_class = CommentSerializer
permission_classes = (IsAdminOrNoEdit,)
def get_queryset(self):
slug = self.kwargs['slug']
return Comment.objects.filter(blogpost__slug=slug)
urls.py
commentpatterns = patterns('',
url(r'^$', views.CommentList.as_view(), name='comment-list'),
url(r'^(?P<pk>[0-9]+)/$', views.CommentDetail.as_view(), name='comment-detail'),
)
urlpatterns = patterns('blog.views',
url(r'^$', 'api_root'),
url(r'^posts/$', views.PostList.as_view(), name='post-list'),
url(r'^posts/(?P<slug>[-\w]+)/$', views.PostDetail.as_view(), name='post-detail'),
url(r'^posts/(?P<slug>[-\w]+)/comments/', include(commentpatterns)),
url(r'^users/$', views.UserList.as_view(), name='user-list'),
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view(), name='user-detail'),
)
Any help would be greatly appreciated, this is driving me crazy.
Upvotes: 3
Views: 5067
Reputation: 6796
Your Comment
model defines a ForeignKey
, which is not allowed to be null
:
class Comment(models.Model):
...
blogpost = models.ForeignKey(BlogPost, related_name='comments')
...
which is ok, but your serializer does not include the blogpost
id, so even if your request includes it, it will be just ignored. correct your serializer to include the blogpost
field:
class CommentSerializer(serializers.HyperlinkedModelSerializer):
post = serializers.Field(source='blogpost.title')
blogpost = serializers.PrimaryKeyRelatedField()
class Meta:
model = Comment
fields = ('id', 'author', 'content', 'post', 'blogpost')
now when you create a post request, the blogpost
field should contain the id
of the blog post to which you're attaching this comment.
Upvotes: 4