Django - 从相关 table 中抓取一个附加字段

Django - grabbing an additional field from related table

我有以下型号:

class User(AbstractBaseUser, PermissionsMixin):
    SUPERVISOR = 1
    REVIEWER = 2
    VERIFIER = 3
    READ_ONLY = 4
    USER_TYPE = [
        (SUPERVISOR, 'Supervisor'),
        (REVIEWER, 'Reviewer'),
        (VERIFIER, 'Verifier'),
        (READ_ONLY, 'Read Only'),
    ]
    email = models.EmailField(max_length=50, unique=True)
    name = models.CharField(max_length=100)
    phone = models.CharField(max_length=50, null=True)
    role = models.IntegerField(
        choices=USER_TYPE,
        default=READ_ONLY
    )
    is_active = models.BooleanField(default=True)


class Comment(models.Model):
    text = models.TextField()
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.PROTECT
    )

查看:

class CommentViewSet(BaseCertViewSet):
    queryset = Comment.objects.all()
    serializer_class = serializers.CommentSerializer

序列化器:

class CommentSerializer(serializers.ModelSerializer):
    user = serializers.SlugRelatedField(
        read_only=True,
        slug_field='name'
    )


    class Meta:
        model = Comment
        fields = ('id', 'text', 'user',)
        read_only_fields = ('id',)

我的问题:当我点击评论 API 端点时,我想 return 用户 角色 也来自用户模型。我该怎么做?

我相信你可以使用 QuerySet.annotation:

编辑:F 来自 django.db.models,因此您也必须导入它。

queryset = Comment.objects.annotate(user_role=F("user__role")) 在你的 CommentViewSet

编辑: 为了让序列化器识别您尝试添加到 QuerySet 的字段,您还必须像这样在序列化器上定义字段:

class CommentSerializer(serializers.ModelSerializer):
    user = serializers.SlugRelatedField(
        read_only=True,
        slug_field='name'
    )

    # add line below to your code
    user_role = IntegerField()

    class Meta:
        model = Comment
        # you have to add it to the list of fields as well
        fields = ('id', 'text', 'user', 'user_role')
        read_only_fields = ('id',)

对我有用的解决方案(不确定它是否是最优雅的,很乐意更改为更好的方法):

class CommentSerializer(serializers.ModelSerializer):
    """Serializer for Comment object"""

    user = serializers.SlugRelatedField(
        read_only=True,
        slug_field='name'
    )

    role = serializers.SerializerMethodField()

    def get_role(self, obj):
        user = obj.user_id
        role = User.objects.only('id').get(
            id=user).role
        return role

    class Meta:
        model = Comment
        fields = ('id', 'value', 'text', 'user', 'role',
                  'date_created', 'date_updated')
        read_only_fields = ('id',)