经过大量调试约4-5小时。 我放弃了试图找到导致这个问题的原因,可能是非常简单的bug。 通过Update和Patch / Put Mixins尝试了这一点,并且也没有用。 由于查询集,它是100%,但我找不到问题? 尝试使用.get()和我能想到的其他一切。
我的观点非常简单:
class RemoveModel3D(generics.DestroyAPIView):
serializer_class = Model3DSerializer
def get_queryset(self):
user_pk = self.kwargs["pk"]
return Model3D.objects.filter(owners__in=[user_pk])
P.S。该查询集与ListModelMixin完美配合。我读到List是针对集合而Retrieve / Destroy / Update是针对单个模型实例的,但是如何让queryset成为单个模型实例?我找不到任何地方
编辑:添加与问题相关的序列化程序和模型片段
序列化程序:
class Model3DSerializer(serializers.ModelSerializer):
User = get_user_model()
commits = CommitSerializer(many=True, required=False, read_only=True)
favorited_by = UserSerializer(many=True, required=False, read_only=True)
date_uploaded = serializers.DateTimeField(read_only=True)
owners = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Model3D
fields = (
'id',
'title',
'owners',
'description',
'date_uploaded',
'favorited_by',
'commits'
)
型号:
class Model3D(models.Model):
title = models.CharField(max_length=64)
# Many models many owners, seems reasonable to me
owners = models.ManyToManyField(User, related_name='owners')
description = models.TextField(null=True)
date_uploaded = models.DateTimeField(auto_now_add=True)
# Many models many people who like them.
favorited_by = models.ManyToManyField(User, related_name='favorited_by')
查看:
class ListAllModels3D(generics.ListAPIView):
serializer_class = Model3DSerializer
def get_queryset(self):
queryset = Model3D.objects.all()
model_id = self.request.query_params.get('id', None)
if model_id is not None:
queryset = queryset.filter(pk=model_id)
return queryset
class RemoveModel3D(generics.DestroyAPIView):
serializer_class = Model3DSerializer
def get_queryset(self):
queryset = Model3D.objects.all()
model_id = self.request.query_params.get('id', None)
if model_id is not None:
queryset = queryset.filter(pk=model_id)
return queryset
class Models3D( mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView,
):
serializer_class = Model3DSerializer
def get_queryset(self):
user_pk = self.kwargs["pk"]
return Model3D.objects.filter(owners__in=[user_pk])
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
def perform_create(self, serializer):
# FIXME: this is a bad way to set the value, but ...
user_id = self.kwargs["pk"]
serializer.validated_data['owners'] = [user_id]
serializer.save()
答案 0 :(得分:0)
当404提高?(在你的情况下)
假设您需要使用Model3D
编辑/删除/检索id=20
实例。在这种情况下,您的终端将为/api/v1/model3d/20/
,方法将为DELETE/PUT/PATCH/GET
。此时DRF使用Model3D
搜索id = 20
个实例。如果找到,它将执行相应的操作,否则会引发404 NotFound
错误。
如果您正在处理CRUD申请,ModelViewSet
最适合您。默认情况下,它会处理大部分内容,只需几行代码。
from rest_framework.viewsets import ModelViewSet
class Model3DAPI(ModelViewSet):
serializer_class = Model3DSerializer
queryset = Model3D.objects.all()
这会为你做CRUD。如果您希望对每个CRUD操作需要更多控制,可以按以下方式覆盖它们,
from rest_framework.viewsets import ModelViewSet
class Model3DAPI(ModelViewSet):
serializer_class = Model3DSerializer
queryset = Model3D.objects.all()
def retrieve(self, request, *args, **kwargs):
# get one instance
pass
def destroy(self, request, *args, **kwargs):
# delete instance
pass
def list(self, request, *args, **kwargs):
# list all instnace
pass
def create(self, request, *args, **kwargs):
# create instance
pass
def update(self, request, *args, **kwargs):
# Update instance
pass
答案 1 :(得分:0)
GenericApiView的默认lookup_url_kwarg
为pk
。但是您使用它来过滤User
,因此在查询所有者和Model3D时将使用相同的pk值。
结果与此伪代码类似,除非用户和model3d具有相同的pk,否则会导致404响应。
kwargs = {'pk': 20}
try:
Model3D.objects.get(owners__in=[kwarsg['pk']], pk=kwargs['pk'])
except ObjectNotFound:
raise Http404Exception('Not found')
要解决此问题,请使用支持嵌套api路由的插件。或者您可以覆盖视图集get_object
方法,这是404引发的方法。
def get_object(self):
queryset = self.get_queryset()
pk = self.request.query_params.get('id', None)
obj = get_object_or_404(queryset, pk=pk)
self.check_object_permissions(self.request, obj)
return obj
http://www.django-rest-framework.org/api-guide/generic-views/#get_objectself
get_object
(GET)retrieve()
PATCH / PUT和update()
(DELETE)使用destroy()
方法,默认使用self.kwargs['pk']
查找值。