如何在Django序列化器中通过外键获取数据及权限验证问题
问题解决:通过外键验证权限并创建数据
一、序列化器create方法的错误修正
你当前的序列化器create方法存在参数错误,且获取requesterid角色的逻辑有误,修正如下:
错误点说明
create方法的正确参数是self和validated_data,instance是更新方法update的参数,不适合用在这里requesterid作为外键,在validated_data中已经被解析为userTable实例,需要通过它关联的userroleid(roleTable实例)获取角色ID,而非直接和数字比较
修正后的序列化器代码
class RequestCreateSerializer(serializers.ModelSerializer): parts = PartSerializer(many=True) class Meta: model = requestTable fields = ['rid', 'requesterid', ...] # 保留你的其他字段 def create(self, validated_data): # 从validated_data中取出请求者对应的user实例 requester = validated_data['requesterid'] # 假设roleTable的主键字段为roleid,判断是否符合权限要求 if requester.userroleid.roleid == 3: parts_data = validated_data.pop('parts') request_obj = requestTable.objects.create(**validated_data) for part_data in parts_data: partsTable.objects.create(request=request_obj, **part_data) return request_obj raise serializers.ValidationError("Sorry! Your role has no permission to create a request.")
二、验证逻辑的位置选择
序列化器 vs 视图的适用场景
- 序列化器:适合处理和数据模型强绑定的验证逻辑,比如字段格式、关联数据权限。在这里处理验证能让逻辑内聚,也方便后续复用序列化器。
- 视图:适合处理和请求上下文相关的逻辑,比如当前登录用户权限、请求方法限制等。但你这里的验证基于请求中的
requesterid,和数据本身强相关,放在序列化器更合适。
视图验证的修正版(若坚持在视图处理)
你之前的视图错误在于直接从request.data获取requesterid__userroleid——前端不会传递这个嵌套字段,需要先通过requesterid查询用户:
from django.shortcuts import get_object_or_404 class RequestListCreateView(ListCreateAPIView): queryset = requestTable.objects.all() serializer_class = RequestCreateSerializer def create(self, request, *args, **kwargs): requester_id = request.data.get('requesterid') if not requester_id: raise ValidationError("requesterid is required") # 查询对应的用户实例,不存在则返回404 requester = get_object_or_404(userTable, userid=requester_id) if requester.userroleid.roleid == 3: return super().create(request, *args, **kwargs) raise ValidationError("Sorry! Your role has no permission to create a request.")
三、推荐方案:用序列化器的validate方法提前验证
更推荐把权限验证放在序列化器的字段验证方法中,这样在数据验证阶段就能拦截非法请求,逻辑更清晰:
class RequestCreateSerializer(serializers.ModelSerializer): parts = PartSerializer(many=True) class Meta: model = requestTable fields = ['rid', 'requesterid', ...] def validate_requesterid(self, value): # value是requesterid对应的userTable实例 if value.userroleid.roleid != 3: raise serializers.ValidationError("Sorry! Your role has no permission to create a request.") return value def create(self, validated_data): parts_data = validated_data.pop('parts') request_obj = requestTable.objects.create(**validated_data) for part_data in parts_data: partsTable.objects.create(request=request_obj, **part_data) return request_obj
调用serializer.is_valid()时会自动触发validate_requesterid方法,提前完成权限验证,符合DRF的序列化器设计规范。
内容的提问来源于stack exchange,提问作者anastasia
相关产品推荐
相关产品推荐

