42

Django REST Framework を使用して Django モデルをシリアル化しています。オブジェクトを一覧表示する ListCreateAPIView ビューと、個々のオブジェクトを取得/更新/削除する RetrieveUpdateDestroyAPIView ビューがあります。モデルには、ユーザーが自分で送信した情報が保存されます。彼らが送信する情報には、一部の個人情報と一部の公開情報が含まれています。すべてのユーザーが公開情報を一覧表示および取得できるようにしたいのですが、個人情報は所有者だけが一覧表示/取得/更新/削除できるようにしたいです。したがって、オブジェクトのアクセス許可ではなく、フィールドごとのアクセス許可が必要です。

私が見つけた最も近い提案は、リクエストの種類に基づいてシリアライザーを変更するhttps://groups.google.com/forum/#!topic/django-rest-framework/FUd27n_k3U0でした。ユーザーが所有しているかどうかを判断するためのクエリセットまたはオブジェクトをその時点で持っていないため、これは私の状況では機能しません。

もちろん、私はフロントエンドに個人情報を隠していますが、賢い人は API リクエストをスヌープして完全なオブジェクトを取得することができます。コードが必要な場合は提供できますが、私の要求はバニラの Django REST フレームワークの設計に適用されます。

4

8 に答える 8

61

ユーザーに基づいてシリアライザークラスを切り替えるのはどうですか?

ドキュメント内:

http://www.django-rest-framework.org/api-guide/generic-views/#get_serializer_classself

def get_serializer_class(self):
    if self.request.user.is_staff:
        return FullAccountSerializer
    return BasicAccountSerializer
于 2015-12-27T23:50:05.933 に答える
15

先日、同様の問題がありました。これが私のアプローチです:

これはDRF 2.4解決策です。

class PrivateField(serializers.Field):
    def field_to_native(self, obj, field_name):
        """
        Return null value if request has no access to that field
        """
        if obj.created_by == self.context.get('request').user:
            return super(PrivateField, self).field_to_native(obj, field_name)
        return None

#Usage
class UserInfoSerializer(serializers.ModelSerializer):
    private_field1 = PrivateField()
    private_field2 = PrivateField()

    class Meta:
        model = UserInfo

そして DRF 3.x ソリューション:

class PrivateField(serializers.ReadOnlyField):

    def get_attribute(self, instance):
        """
        Given the *outgoing* object instance, return the primitive value
        that should be used for this field.
        """
        if instance.created_by == self.context['request'].user:
            return super(PrivateField, self).get_attribute(instance)
        return None

今回はクラスに実装されていないReadOnlyFieldので拡張のみ。to_representationserializers.Field

于 2014-09-25T19:33:10.167 に答える
6

私はそれを行う方法を考え出しました。シリアライザーでは、オブジェクトと API 要求を行うユーザーの両方にアクセスできます。したがって、リクエスタがオブジェクトの所有者であるかどうかを確認し、個人情報を返すことができます。そうでない場合、シリアライザーは空の文字列を返します。

class UserInfoSerializer(serializers.HyperlinkedModelSerializer):
    private_field1 = serializers.SerializerMethodField('get_private_field1')

    class Meta:
        model = UserInfo
        fields = (
            'id',
            'public_field1',
            'public_field2',
            'private_field1',
        )
        read_only_fields = ('id')

    def get_private_field1(self, obj):
        # obj.created_by is the foreign key to the user model
        if obj.created_by != self.context['request'].user:
            return ""
        else:
            return obj.private_field1
于 2013-10-02T21:43:39.990 に答える
2

READ 操作のみを実行している場合は、シリアライザーの to_representation メソッドでフィールドをポップするだけです。

def to_representation(self,instance):
    ret = super(YourSerializer,self).to_representation(instance)
    fields_to_pop = ['field1','field2','field3']
    if instance.created_by != self.context['request'].user.id:
        [ret.pop(field,'') for field in fields_to_pop]
    return ret

これは、機密フィールドを非表示にするのに十分なはずです。

于 2016-12-09T11:27:18.797 に答える