You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework ModelViewSet显式允许后POST方法仍未生效

问题场景

刚接触Django Rest Framework,以超级用户身份操作Item接口时,POST表单不显示且提示"POST方法不允许"。当前使用Django Guardian的BigGroup/BigUser权限框架,尝试多种配置方案后仍未解决,相关代码及尝试如下:

Model代码(model.py)

class Category(models.Model):
    category = models.CharField('category', 
        max_length=100, null=False, blank=False, default="NA")
    def __str__(self) -> str:
        return self.category
    class Meta:
        verbose_name_plural = "categories"

class Item(models.Model):
    name = models.CharField('name', max_length=64)
    slug = models.SlugField(max_length=64, null=True, blank=True)
    icon = models.ImageField(blank=True, upload_to ='uploads/')
    category = models.ForeignKey(
        Category, on_delete=models.CASCADE, default='Uncategorized')
    subcategory = models.CharField(
        max_length=255, null=True, blank=True)
    quantity = models.DecimalField(
        max_digits=9, decimal_places=2)
    suggested_value = models.DecimalField(
        max_digits=6, decimal_places=2, null=False)
    retail_value = models.DecimalField(max_digits=6, decimal_places=2,max_length=30)
    description = models.TextField('description', max_length=255, blank=True)
    created_at = models.DateTimeField(auto_now_add=True, db_index=True)
    tenant = models.TextField('tenant', default='shared')
    exclude = ('tenant')
    
    class Meta:
        # db_table = "storeItems_item"
        default_permissions = ('view','add', 'change', 'delete')
        ordering = ['name']
        get_latest_by = 'created_at'
    
    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse(
            'storeItems_item_detail', args=(), kwargs={'slug': self.slug})
    
    def save(self, *args, **kwargs):
        # assign permission to item
        group = Group.objects.get(name=self.tenant)
        super(Item, self).save(*args, **kwargs)
        for perm in ['view_item', 'add_item','change_item']:
            assign_perm(perm, group, self)
        # Default retail value
        if not self.retail_value:
            self.retail_value = self.suggested_value()
        super().save(*args, **kwargs)

尝试过的ViewSet权限配置

class StoreItemsViewSet(
    viewsets.ModelViewSet, PermissionListMixin,   
    # viewsets.GenericViewSet, mixins.ListModelMixin, 
    # mixins.CreateModelMixin, mixins.UpdateModelMixin,
    ):
    queryset = Item.objects.all()
    serializer_class = StoreItemsSerializer
    # permission_classes = (
    #     BigGroupObjectPermission, BigUserObjectPermission)
    permission_classes = [ItemPermission]

    # @action(detail=True, methods=['post', 'delete'])
    # def perform_create(self, serializer):
    #     serializer.save(owner=self.request.user)

    # def create(self, request, *args, **kwargs):
    #     instance = super().create(request, *args, **kwargs)
    #     assign_perm("change_item", request.user, instance)
    #     assign_perm("change_item", request.user, instance)
    #     return instance

    # def post(self, request):
    #     return Response()

自定义全权限类尝试

class FullPermission(BasePermission):
    # def has_permission(self, request, view):
    #     return request.method in SAFE_METHODS
    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj):
        return True

排查方向

  • 验证权限类逻辑:先临时将permission_classes替换为IsAdminUser或FullPermission,如果POST恢复正常,说明ItemPermission的has_permission方法对POST请求返回了False,需要检查该类的权限判断逻辑。
  • 修复Model的save方法:当前Item的save方法存在两处错误:调用两次super().save(),且self.suggested_value()是错误的调用方式(suggested_value是字段而非方法)。修复后的save方法如下:
    def save(self, *args, **kwargs):
        # 先处理默认值
        if not self.retail_value:
            self.retail_value = self.suggested_value
        # 保存实例
        super(Item, self).save(*args, **kwargs)
        # 分配权限
        group = Group.objects.get(name=self.tenant)
        for perm in ['view_item', 'add_item','change_item']:
            assign_perm(perm, group, self)
    
  • 检查路由配置:确认使用DefaultRouter正确注册ViewSet,没有自定义路由覆盖默认的POST路由。
  • 确认Guardian权限注册:检查Django admin的权限列表,确保add_item权限存在,且超级用户或其所属组拥有该权限。

内容的提问来源于stack exchange,提问作者momo668

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 09:07:14