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

如何在DRF中为Bartender模型添加获取当前用户Rating的方法

解决方法:在DRF中获取当前用户对Bartender的Rating

这个问题其实是Django/DRF分层设计里的常见误区——模型层本身是和请求上下文完全隔离的,self在模型方法里指代的是模型实例,和当前请求的用户、请求对象没有任何关联,所以没法直接在Bartender模型里写方法来拿到当前用户的Rating。

正确的做法是把这个逻辑放到序列化器或者ViewSet里,因为这两层可以直接访问到请求上下文。下面给你两种常用的实现方式:

前提假设

先明确你的模型结构(如果和这个不一致,你可以调整代码适配):

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

class Bartender(models.Model):
    name = models.CharField(max_length=100)
    # 其他自定义字段...

class Rating(models.Model):
    bartender = models.ForeignKey(Bartender, on_delete=models.CASCADE, related_name='ratings')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    score = models.IntegerField()
    # 其他评分相关字段...

方式一:在序列化器中添加自定义字段

这是最常用的方式,适合在返回Bartender详情/列表时,同时带上当前用户的评分:

from rest_framework import serializers

class RatingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Rating
        fields = ['id', 'score']

class BartenderSerializer(serializers.ModelSerializer):
    # 自定义字段,用来返回当前用户的评分
    current_user_rating = serializers.SerializerMethodField()

    class Meta:
        model = Bartender
        fields = ['id', 'name', 'current_user_rating']

    def get_current_user_rating(self, obj):
        # 从序列化器的context中获取request对象(DRF默认会传入)
        request = self.context.get('request')
        
        # 先判断用户是否登录
        if request and request.user.is_authenticated:
            # 通过related_name查询当前用户对这个Bartender的评分
            rating = obj.ratings.filter(user=request.user).first()
            if rating:
                # 用RatingSerializer序列化评分数据,或者直接返回字典
                return RatingSerializer(rating).data
        # 如果用户未登录或没有评分,返回None或空字典
        return None

然后在你的ViewSet中直接使用这个序列化器即可(DRF的ModelViewSet会自动把request传入序列化器的context):

from rest_framework import viewsets

class BartenderViewSet(viewsets.ModelViewSet):
    queryset = Bartender.objects.all()
    serializer_class = BartenderSerializer

方式二:在ViewSet中自定义Action

如果你需要单独提供一个接口来获取某个Bartender的当前用户评分,可以用DRF的自定义Action:

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status

class BartenderViewSet(viewsets.ModelViewSet):
    queryset = Bartender.objects.all()
    serializer_class = BartenderSerializer

    # 自定义一个detail=True的action,意味着需要传入Bartender的pk
    @action(detail=True, methods=['get'])
    def current_user_rating(self, request, pk=None):
        bartender = self.get_object()
        
        if not request.user.is_authenticated:
            return Response({'detail': '请先登录'}, status=status.HTTP_401_UNAUTHORIZED)
        
        rating = bartender.ratings.filter(user=request.user).first()
        if rating:
            return Response(RatingSerializer(rating).data)
        else:
            return Response({'detail': '当前用户未对该调酒师评分'}, status=status.HTTP_404_NOT_FOUND)

这个方式会生成一个类似/api/bartenders/{pk}/current_user_rating/的接口,专门返回当前用户对指定Bartender的评分。

为什么不推荐在模型里实现?

Django的MTV设计模式中,模型层负责数据逻辑(比如数据验证、数据库操作),而请求上下文属于视图层的职责。把请求相关的逻辑放到模型里会导致:

  • 模型和请求上下文耦合,难以单独测试模型
  • 违背单一职责原则,模型变得臃肿
  • 无法在非请求场景下复用这个逻辑(比如后台脚本、管理命令)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:30:48