所以我在尝试做的事情上遇到了一些麻烦。
基本上,我有这些模型:
class Package(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=255, null=False, blank=False)
contact = models.BooleanField(default=False)
downloaded = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
class Item(models.Model):
[…. all the atributes of the item model….]
class PackageItems(models.Model):
package = models.ForeignKey(Package, on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
现在我正在尝试创建一个端点,允许我的用户添加“包”并将项目模型中的预先存在的项目添加到新创建的包中。一个包裹当然可以有很多物品。
所以我写了一个包序列化程序,然后添加了一个 SerializerMethodField 允许对给定包包含的任何项目执行获取操作。该方法调用不同的序列化程序。这是两个序列化程序的代码:
class PackageItemsSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = PackageItems
fields = ('package', 'item')
class PackagesSerializer(serializers.ModelSerializer):
"""
Creation only requires a title
"""
package_items = serializers.SerializerMethodField(read_only=True)
@swagger_serializer_method(serializer_or_field=packageItemsSerializer)
def get_package_items(self, obj):
packageItems = PackageItems.objects.all().filter(package=obj.id)
return PackageItemsSerializer(packageItems, many=True, context={'request': self.context['request']}).data
def create(self, validated_data):
package = super(packagesSerializer, self).create(validated_data)
return package
class Meta:
model = packages
fields = ('id', 'user', 'title', 'contact', 'downloaded', 'created', 'package_items')
read_only_fields = [ 'user', 'contact', 'downloaded', 'package_items’]
现在就我的观点而言,我决定这样做:
class PackagesViewSet(viewsets.ModelViewSet):
queryset = Packages.objects.all()
serializer_class = PackagesSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
if getattr(self, 'swagger_fake_view', False):
return Packages.objects.none()
return Packages.objects.filter(user=self.request.user).order_by('id')
def perform_create(self, serializer):
# sending default values for user, contact and downloaded
serializer.save(user=self.request.user, contact=False, downloaded=False)
def partial_update(self, request, *args, **kwargs):
response_with_updated_instance = super(PackagesViewSet, self).partial_update(request, *args, **kwargs)
return response_with_updated_instance
@action(methods=['post', 'delete'], detail=True, serializer_class=PackageItemsSerializer)
def item(self, request, pk=None):
package = self.get_object()
serializer = self.get_serializer_class()(data=request.data)
if serializer.is_valid():
serializer.save(package=package)
return Response(serializer.data)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
if request.method == 'delete':
serializer.delete(package=package)
这就是它的工作原理:我得到了这些路线:
[获取/发布] 为/api/packages/
[所有方法]为/api/packages/{id}
[发布/删除]为/api/packages/{id}/item
我得到了正确的路线,但首先,Swagger 给了我错误的帖子模型:
{
"title": "string",
"package_items": {
"items": 0
}
}
不知道为什么当我发布到/api/packages
.
同样,这些字段显示在 PUT 下/api/packages/{id}
。
对于嵌套的“项目”路线,POST
效果很好,但效果不佳DELETE
。POST 路由允许我输入项目 ID 并将其添加到/api/packages/{id}/item
路由下的给定包裹 ID。但是删除不允许我输入要删除的项目 ID。
所以我认为我对嵌套 ITEM 的删除方法的方法是完全错误的。
我是 DRF/django 的新手,试图验证我是否朝着正确的方向前进。
如何让 drf-yasg 为我提供正确的 HTTP 动词模型,例如 POST?删除嵌套项目的正确方法是什么?
我处理这个问题对吗?还有其他方法可以更有效地做到这一点吗?
如果有人可以帮助我回答这些问题,将不胜感激:)
先谢谢各位了。