我正在尝试使用django rest框架为不同类型的内容创建Bookmark模型的实例,例如Book。
代码:
models.py
class Bookmark(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
api.py
from django.contrib.contenttypes.models import ContentType
from rest_framework import viewsets, mixins, serializers, permissions
from .models import Bookmark
class BookmarkSerializer(serializers.ModelSerializer):
class Meta:
model = Bookmark
fields = ('id', 'user', 'content_type', 'object_id')
class BookmarkViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
queryset = Bookmark.objects.all()
serializer_class = BookmarkSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
content_type = self.request.query_params.get('content_type')
app, model = content_type.split(".")
ct = ContentType.objects.get_by_natural_key(app, model)
object_id = self.request.query_params.get('object_id')
serializer.save(user=self.request.user, content_type=ct, object_id=object_id)
def get_queryset(self):
items = Bookmark.objects.filter(user=self.request.user)
content_type = self.request.query_params.get('content_type', None)
if content_type:
app, model = content_type.split(".")
ct = ContentType.objects.get_by_natural_key(app, model)
items = items.filter(content_type=ct)
object_id = self.request.query_params.get('object_id', None)
if object_id:
items = items.filter(object_id=object_id)
return items
get_queryset部分没问题。但是当我尝试创建一个新的书签时,perform_create失败了:
var item = new Bookmark({'content_type': 'books.book', 'object_id': self.book_id});
item.save();
回应:
{"user":["This field is required."],"content_type":["Incorrect type. Expected pk value, received unicode."]}
我不清楚我应该怎么做。我将不胜感激任何反馈。
答案 0 :(得分:0)
你也应该发布你的模型定义,但是你得到的错误是你还需要将user
参数传递给Bookmark
并且你应该传递一个pk值(又名一个整数,它是您content_type
指向的对象的id。
答案 1 :(得分:0)
我不能说有关用户的错误消息,但这是关于第二个的2美分。
您不是简单地将模型的路径作为content_type
键的字符串提供。
Apparently
,你必须使用作为模型参数传递的get_for_model
方法(模型'Book',而不是它的实例),并返回类型为ContentType
的对象。此对象的id
是您应该作为值传递的对象。
答案 2 :(得分:0)
以前的答案都指出了我正确的方向。最后,解决方案不是覆盖perform_create,而是创建函数:
def create(self, request, *args, **kwargs):
content_type = request.data['content_type']
if content_type:
app, model = content_type.split(".")
ct = ContentType.objects.get_by_natural_key(app, model)
request.data['user'] = request.user.id
request.data['content_type'] = ct.id
#object_id already passed as id in request.data
可在此处阅读进一步说明: https://github.com/encode/django-rest-framework/issues/3470