如何使用模型视图集和 POST 请求创建对象?

Posted

技术标签:

【中文标题】如何使用模型视图集和 POST 请求创建对象?【英文标题】:How do you create object with modelviewset and POST request? 【发布时间】:2017-07-08 17:19:58 【问题描述】:

我正在尝试向我的数据库添加评论,但收到错误 'OrderedDict' object has no attribute 'pk'

处理POST请求的react.js代码部分:

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);
    );


我的 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

我的意见.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

当发送 Post-request 时,它会正常进行。如果我删除其中一个字段,它将返回 400。现在我得到这个500 [Internal server] error

AttributeError: 'OrderedDict' 对象没有属性 'pk'

错误似乎来自:

/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

这里->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)

▶ 局部变量如下:-

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

阅读具有相同错误的其他问题。没有找到解决我问题的方法。

谢谢!

编辑:

通过将其添加到我的帖子序列化程序来解决它:

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

【问题讨论】:

什么是完整的回溯? Kinda 通过明确告诉它如何创建新帖子来解决它,因此无法获取其余的错误数据。如果您知道可能是什么原因造成的,我仍然很好奇。 【参考方案1】:

我认为这仅仅是因为您的url 是空的:

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);
    );

由于您指定了class CommentSerializer(serializers.HyperlinkedModelSerializer):,因此在document 中提到了这一点:

需要有一种方法来确定应该使用哪些视图 超链接到模型实例。

默认情况下,超链接应与视图名称相对应 匹配样式“model_name-detail”,并通过以下方式查找实例 pk 关键字参数。

所以HyperlinkedModelSerializer 试图找到一个应该用于链接到 Post 对象的视图但找不到它。高度怀疑帖子url为空id

【讨论】:

以上是关于如何使用模型视图集和 POST 请求创建对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何在路由器上注册单个视图(不是视图集)?

视图集ViewSets

视图集ViewSet

如何根据请求方式设置不同的权限?

路由Routers

drf-路由