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

Django REST Framework列表按用户筛选及权限控制实现问询

Django REST Framework Listing 权限与筛选实现方案

先补全基础模型(假设你的模型结构如下,若有差异可调整)

from django.db import models
from django.contrib.auth import get_user_model

User = get_user_model()

class Listing(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='listings')
    title = models.CharField(max_length=255)
    description = models.TextField()
    is_listed = models.BooleanField(default=True)  # 默认上架
    created_at = models.DateTimeField(auto_now_add=True)

1. 核心:修复可见性问题 + 实现多维度筛选

重写视图的get_queryset方法,精准控制不同用户能看到的内容,同时处理user_id和status筛选参数:

from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from .models import Listing
from .serializers import ListingSerializer
from .permissions import IsOwnerOrReadOnly

class ListingViewSet(viewsets.ModelViewSet):
    serializer_class = ListingSerializer
    permission_classes = [IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]

    def get_queryset(self):
        queryset = Listing.objects.all()
        
        # 处理user_id筛选:有参数则过滤,无则返回全部基础数据集
        user_id = self.request.query_params.get('user_id')
        if user_id:
            queryset = queryset.filter(user_id=user_id)
        
        # 可见性规则:自己的Listing全可见,他人仅可见上架的
        if self.request.user.is_authenticated:
            own_listings = queryset.filter(user=self.request.user)
            other_listings = queryset.filter(user__ne=self.request.user, is_listed=True)
            queryset = own_listings | other_listings
        else:
            # 未登录用户只能看所有上架Listing
            queryset = queryset.filter(is_listed=True)
        
        # 处理status筛选:listed(上架)/unlisted(下架)/all(全部)
        status = self.request.query_params.get('status')
        if status == 'listed':
            queryset = queryset.filter(is_listed=True)
        elif status == 'unlisted':
            # 仅所有者能查看自己的下架内容
            if self.request.user.is_authenticated:
                queryset = queryset.filter(user=self.request.user, is_listed=False)
            else:
                queryset = Listing.objects.none()
        
        return queryset.distinct()

2. 自定义权限:仅所有者可编辑/删除

新建permissions.py文件,添加权限类:

from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        # GET/HEAD/OPTIONS 请求允许所有用户访问
        if request.method in permissions.SAFE_METHODS:
            return True
        # 写操作仅允许Listing所有者执行
        return obj.user == request.user

3. 序列化器:自动关联用户 + 控制字段权限

from rest_framework import serializers
from .models import Listing

class ListingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Listing
        fields = ['id', 'user', 'title', 'description', 'is_listed', 'created_at']
        read_only_fields = ['user']  # 禁止前端修改用户字段,由后端自动填充
    
    def create(self, validated_data):
        # 创建时自动绑定当前登录用户
        validated_data['user'] = self.context['request'].user
        return super().create(validated_data)

关键逻辑说明

  • 未登录用户:仅能查看所有公开上架的Listing,无法创建/修改
  • 登录用户:
    • 查看自己的所有Listing(上架/下架)
    • 查看其他用户仅上架的Listing
    • 仅能创建、编辑、删除自己的Listing
    • 通过user_id参数筛选特定用户的公开Listing
    • 通过status参数筛选自己的上架/下架/全部内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 11:07:29