Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you create object with modelviewset and POST request?

Im trying to add a comment to my db, but getting error 'OrderedDict' object has no attribute 'pk'

The part of react.js code handling the POST request:

addComment() {
    let url = this.props.post_url

    axios.post('/api/comments/', {
          post: url,
          user: "http://127.0.0.1:8000/api/users/1/?format=json",
          text: document.getElementsByName(url)[0].value,
          csrfmiddlewaretoken: document.getElementsByName("csrfmiddlewaretoken")[0].value},
      )
    .then(function (response) {
       console.log(response);
    })
    .catch(function (error) {
      console.log(error);
    });

}

My serializers.py:

from django.contrib.auth.models import User
from rest_framework import serializers

from .models import Post, Comment

        
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'url')


class CommentSerializer(serializers.HyperlinkedModelSerializer):
    #user = UserSerializer(many=False, required=False)
    class Meta:
        model = Comment
        fields = ('id', "post", "user", 'text')
        read_only_fields = ('id', "user")

    def create(self):
        user = None   
        request = self.context.get("request")
        if request and hasattr(request, "user"):
            user = request.user


class PostSerializer(serializers.HyperlinkedModelSerializer):
    #user = UserSerializer(required=False)
    comments = CommentSerializer(many=True, required=False, read_only=True)
    class Meta:
        model = Post
        fields = ('id', 'title', "user", "url", "comments", 'text')
        read_only_fields = ('id', "url", "comments")

    def save(self):
        user = None
        request = self.context.get("request")
        if request and hasattr(request, "user"):
            user = request.user

My views.py

from django.contrib.auth.models import User
from api.serializers import UserSerializer
from rest_framework import viewsets

from .models import Comment, Post
from .serializers import CommentSerializer, PostSerializer


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

        
class CommentViewSet(viewsets.ModelViewSet):
    queryset = Comment.objects.all()
    serializer_class = CommentSerializer

       
class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

When sending the Post-request it goes througth normaly. If I remove one of the fields it returnes a 400. Now Im getting this 500 [Internal server] error.

AttributeError: 'OrderedDict' object has no attribute 'pk'

The error seems to be comming from:

/home/halvor1606/.virtualenvs/django-react/local/lib/python2.7/site-packages/rest_framework/relations.py in get_url

   # Unsaved objects will not yet have a valid URL.

   if hasattr(obj, 'pk') and obj.pk in (None, ''):

       return None

Here-> lookup_value = getattr(obj, self.lookup_field) ...

   kwargs = {self.lookup_url_kwarg: lookup_value}

   return self.reverse(view_name, kwargs=kwargs, request=request, format=format)

   def get_name(self, obj):

       return six.text_type(obj)

▶ Local vars are as follows:-

Variable    Value

request      <rest_framework.request.Request object at 0x7f4e59e75b90>

view_name    'post-detail'

obj           OrderedDict([(u'title', u'adskjfj|'), (u'user', <User:      halvor1606>), (u'text', u'kjkldsjf')])

self          HyperlinkedIdentityField(read_only=True, view_name='post-detail')

format        None

Read the other Questions with the same error. Didn't find one that solved my problem.

Thank you!

Edit:

Solved it by adding this to my post serializer:

def create(self, validated_data):
    tmp_post = validated_data
    user = None   

    request = self.context.get("request")
    if request and hasattr(request, "user"):
        user = request.user

    post = Post.objects.create(
        user=user,
        title=tmp_post['title'],
        text=tmp_post['text'],
    )

    return post
like image 579
H. Boe Avatar asked Feb 19 '17 12:02

H. Boe


People also ask

What is ModelViewSet in Django?

The ModelViewSet class inherits from GenericAPIView and includes implementations for various actions, by mixing in the behavior of the various mixin classes. The actions provided by the ModelViewSet class are . list() , . retrieve() , . create() , .

What is difference between APIView and Viewset?

APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.

Should either include a Serializer_class attribute or override the?

serializer_class - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the get_serializer_class() method.

What is serializer Django?

Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.


1 Answers

I think this is simply because your url here is empty:

addComment() {
    let url = this.props.post_url

    axios.post('/api/comments/', {
          post: url,
          user: "http://127.0.0.1:8000/api/users/1/?format=json",
          text: document.getElementsByName(url)[0].value,
          csrfmiddlewaretoken: document.getElementsByName("csrfmiddlewaretoken")[0].value},
      )
    .then(function (response) {
       console.log(response);
    })
    .catch(function (error) {
      console.log(error);
    });
}

Since you specified class CommentSerializer(serializers.HyperlinkedModelSerializer):, this was mentioned in the document:

There needs to be a way of determining which views should be used for hyperlinking to model instances.

By default hyperlinks are expected to correspond to a view name that matches the style '{model_name}-detail', and looks up the instance by a pk keyword argument.

So the HyperlinkedModelSerializer tries to find a view which should be used for the linking to Post object and could not find it. Highly suspected that the post url is with empty id

like image 54
Nathan Do Avatar answered Oct 17 '22 16:10

Nathan Do