2016-01-14 5 views
0

Я создаю API с платформой Django Rest Framework для сайта, который позволяет пользователям создавать сообщения и комментировать эти сообщения. Я могу создавать сообщения от API нормально, но когда я пытаюсь создать комментарий, я получаю следующую ошибку:Django REST Framework - создать дочерний элемент вложенных отношений

NOT NULL ограничения не удалось: app_comment.post_id

моих моделей:

class Post(models.Model): 
    owner = models.ForeignKey('auth.User', related_name = 'posts') 
    post_title = models.CharField(max_length=200) 
    post_description = models.CharField(max_length=1000) 

class Comment(models.Model): 
    user = models.ForeignKey(User, related_name = 'comments') 
    post = models.ForeignKey(Post, related_name = 'comments') 
    text = models.CharField(max_length=1000) 

и мой комментарий сериализатору:

class CommentSerializer(serializers.ModelSerializer): 
    user = serializers.ReadOnlyField(source='user.username') 
    post = serializers.ReadOnlyField(source='post.id') 
    class Meta: 
     model = Comment 
     fields = ('id', 'text', 'user', 'post') 

и мой комментарий мнение:

class PostCommentList(generics.ListCreateAPIView): 
    permission_classes = (permissions.IsAuthenticated, 
          IsOwnerOrReadOnly,) 
    serializer_class = CommentSerializer 
    def get_queryset(self): 
     post = self.kwargs['post_pk'] 
     post = Post.objects.get(pk = post) 
     return post.comments.all() 
    def perform_create(self, serializer): 
     post = self.kwargs['post_pk'] 
     print("creating a comment from " + str(self.request.user) + " on post " + str(post) +" : "+ str(Post.objects.get(pk = post))) 
     serializer.save(user = self.request.user) 
     serializer.save(post = self.kwargs['post_pk']) 

При попытке создать комментарий к сообщению я вижу правильную информацию, распечатанную (т. 'создание комментария от пользователя в post 6: Post object').

Почему мои комментарии не создаются с правильным post_id?

+0

Почему вы перегрузки 'get_queryset' и' perform_create'? Думаю, он должен нормально работать, если вы этого не сделаете. Не могли бы вы проверить это, пожалуйста? –

+0

Я перегружаю get_queryset, так что будут возвращены только комментарии, прикрепленные к определенному сообщению, и я перегружаю функцию perform_create, чтобы я мог получить номер сообщения из URL-адреса и пользователя из запроса (аналогично примеру здесь : http://www.django-rest-framework.org/api-guide/generic-views/). Я попробую удалить их, но я верю, что это нарушит другие функции. – KSmith

ответ

2

В вашей функции perform_create вы получаете первичный ключ, который является целым числом, а не объектом Post. Кроме того, вы не хотите вызывать сохранение дважды - это приведет к сохранению двух моделей (при условии, что это не приведет к ошибкам проверки, которые в этом случае есть).

Лучший способ сделать это может быть:

post_pk = self.kwargs['post_pk'] 
post = Post.objects.get(pk = post_pk) 
serializer.save(user=self.request.user, post=post) 

Кроме того, вы, вероятно, захотите добавить текстовое содержимое в модель сохраняет, а также. Так что, возможно, так что вам может понадобиться добавить/изменить следующим образом:

text = self.kwargs['text'] 
serializer.save(user=self.request.user, post=post, text=text) 

Пока я думал об этом - вы можете сохранить вызов «получить» и избежать поездки в базу данных и указать внешний ключ напрямую. Вы можете сделать это, используя следующий синтаксис:

post_pk = self.kwargs['post_pk'] 
# Note - we won't call '.get' here 
serializer.save(user=self.request.user, post_id=post_pk, text=text) 
+0

Не понял, что могу добавить несколько параметров в функцию сохранения, спасибо! Мне не нужно добавлять текст, чтобы сохранить хотя, я считаю, потому что он обрабатывается моим классом сериализатора. – KSmith

0

Ну, самая очевидная ошибка в том, что вы вызываете сохранить() дважды, сначала с пользователем и с почтой. И в первом вызове он пытается создать комментарий без сообщения и заставляет базу данных выдавать ошибку с ошибкой. Заменить

 
serializer.save(user = self.request.user) 
serializer.save(post = self.kwargs['post_pk']) 

с

 
serializer.save(user=self.request.user, 
       post=int(self.kwargs['post_pk'])) 

и вы должны быть хорошо.

Тем не менее, вы, вероятно, следует удалить ReadOnlyFields и просто добавить read_only_fields к сериализатора мета

 
class CommentSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Comment 
     fields = ('id', 'text', 'user', 'post') 
     read_only_fields = ('post', 'user') 
Смежные вопросы