简体   繁体   English

DRF:如何根据实例属性使序列化器字段不同

[英]DRF: How to make serializer fields different depending on instance attributes

I'm not overly familiar with DRF or Django, but here goes:我对 DRF 或 Django 不太熟悉,但这里有:

I'm working on a workout-API that returns a user, and the user is able to set the visibility of their profile.我正在开发一个返回用户的锻炼 API,并且用户能够设置其个人资料的可见性。 The table looks something like:该表看起来像:

id | username | email | coach_id | visibility

where visibility is one of public , coach , private . visibilitypubliccoachprivate之一。

This means that if User 1 has visibility = private , another user fetching their profile should only see the attributes id and username , but the user themselves should get all the attributes.这意味着如果User 1visibility = private ,另一个用户获取他们的个人资料应该只看到属性idusername ,但用户自己应该得到所有属性。

The user's coach should see a profile if visibility = public or visibility = coach .如果visibility = publicvisibility = coach ,用户的教练应该会看到个人资料。

I've looked into dynamically setting the serializer's fields -variable, with no luck (because the fields should be "generated" depending on the content of the object/instance).我已经研究过动态设置序列化程序的fields - 变量,但没有运气(因为字段应该根据对象/实例的内容“生成”)。

I've also looked into extra_field = serializers.SerializerMethodField() , but that resulted in all the values being shown as sub-properties of extra_field .我还研究了extra_field = serializers.SerializerMethodField() ,但这导致所有值都显示为extra_field的子属性。

What I am wondering is: What is the best way to attack this problem?我想知道的是:解决这个问题的最佳方法是什么?

I solved it!我解决了!

I used the to_representation -function in my serializer like so:我在序列化程序中使用了to_representation -函数,如下所示:

class VisibilityAwareUserSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = get_user_model()
        fields = [
            "id",
            "username",
            "visibility",
            "email",
            "coach",
        ]

    def to_representation(self, instance):
        ret = super(PermissionAwareUserSerializer, self).to_representation(instance)
        fields_to_pop = [
            "email",
            "coach",
        ]
        if not self.userCanSeeObject(self.context['request'].user, instance):
            [ret.pop(field,'') for field in fields_to_pop]
        return ret

    def userCanSeeObject(self, user, obj):
        return ((obj.visibility == "public") or (obj.visibility == "coach" and obj.coach == user or obj == user) or (obj.visibility == "private" and obj == user))

Feel free to point out weaknesses in this solution, but it seems to work well for me.随意指出此解决方案中的弱点,但它似乎对我很有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM