Python 在DRF中处理相关模型并为其获取正确的招摇过市文档

Python 在DRF中处理相关模型并为其获取正确的招摇过市文档,python,django,django-rest-framework,swagger,drf-yasg,Python,Django,Django Rest Framework,Swagger,Drf Yasg,所以我有点麻烦,因为我想做的事 基本上,我有这些模型: 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) downloade

所以我有点麻烦,因为我想做的事

基本上,我有这些模型:

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,允许对给定包包含的任何项执行get操作。该方法调用不同的序列化程序。 以下是两个序列化程序的代码:

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

我找到了正确的路线,但首先,斯威格给了我错误的post模型:

{
  "title": "string",
  "package_items": {
    "items": 0
  }
}
不确定为什么在我发布到
/api/packages
时希望输入此只读字段(这也是serializermethodfield)

类似地,这些字段显示在
/api/packages/{id}

对于嵌套的“item”路由,
POST
可以很好地工作,但是
DELETE
不能。POST路由允许我输入项目ID,并将其添加到
/api/packages/{ID}/item
路由下的给定包ID中。 但是delete不允许我输入要删除的项目ID

因此,我认为我对嵌套项的delete方法是完全错误的

我是DRF/django的新手,正在尝试验证我是否朝着正确的方向前进

如何让drf yasg为HTTP动词(例如POST)找到正确的模型? 删除嵌套项的正确方法是什么

我处理这个问题对吗?还有其他更有效的方法吗

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


提前谢谢各位

不要在
序列化程序中嵌套
序列化程序
。SerializerMethodField
直接嵌套它,就像:

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

试试这个

继续玩这个,使用不同的序列化程序执行不同的操作。对于“我的软件包”部分的作品,招摇过市的文档看起来很好,模型很好,所有内容的表示也很好