2

所以我在尝试做的事情上遇到了一些麻烦。

基本上,我有这些模型:

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?删除嵌套项目的正确方法是什么?

我处理这个问题对吗?还有其他方法可以更有效地做到这一点吗?

如果有人可以帮助我回答这些问题,将不胜感激:)

先谢谢各位了。

4

1 回答 1

0

与其直接嵌套serializerserializer.SerializerMethodField不如嵌套如下:

package_item = PackageItemsSerializer(source="package_set", many=True, read_only=True)

尝试这个

于 2020-04-09T11:57:34.600 回答