61

私のアプリには、次のモデルがあります。

class Zone(models.Model):
    name = models.SlugField()

class ZonePermission(models.Model):
    zone = models.ForeignKey('Zone')
    user = models.ForeignKey(User)
    is_administrator = models.BooleanField()
    is_active = models.BooleanField()

Django REST フレームワークを使用して、ゾーンの詳細と、そのゾーンに対する認証済みユーザーのアクセス許可を示すネストされたリソースを返すリソースを作成しています。出力は次のようになります。

{
    "name": "test", 
    "current_user_zone_permission": {
        "is_administrator": true, 
        "is_active": true
    }
} 

次のようなシリアライザーを作成しました。

class ZonePermissionSerializer(serializers.ModelSerializer):
    class Meta:
        model = ZonePermission
        fields = ('is_administrator', 'is_active')

class ZoneSerializer(serializers.HyperlinkedModelSerializer):
    current_user_zone_permission = ZonePermissionSerializer(source='zonepermission_set')

    class Meta:
        model = Zone
        fields = ('name', 'current_user_zone_permission')

これに関する問題は、特定のゾーンを要求すると、ネストされたリソースが、そのゾーンのアクセス許可を持つすべてのユーザーの ZonePermission レコードを返すことです。request.userネストされたリソースにフィルターを適用する方法はありますか?

ところで、これには a を使用したくありませんHyperlinkedIdentityField(http 要求を最小限に抑えるため)。

解決

これは、以下の回答に基づいて実装したソリューションです。次のコードをシリアライザ クラスに追加しました。

current_user_zone_permission = serializers.SerializerMethodField('get_user_zone_permission')

def get_user_zone_permission(self, obj):
    user = self.context['request'].user
    zone_permission = ZonePermission.objects.get(zone=obj, user=user)
    serializer = ZonePermissionSerializer(zone_permission)
    return serializer.data

解決策をどうもありがとう!

4

5 に答える 5

30

私は同じシナリオに直面しています。私が見つけた最善の解決策は、を使用し、SerializerMethodFieldそのメソッドクエリを実行して目的の値を返すことです。request.userからそのメソッドにアクセスできますself.context['request'].user

それでも、これはちょっとしたハックのようです。私はDRFにかなり慣れていないので、経験豊富な人が参加できるかもしれません.

于 2013-05-30T15:31:22.033 に答える
4

複数の場所で QuerySet / filter を使用している場合は、モデルでゲッター関数を使用してから、Serializer / Field の「ソース」kwarg を削除することもできます。DRF は、 get_attribute関数を使用しているときに関数/callable が見つかった場合、それらを自動的に呼び出します

class Zone(models.Model):
    name = models.SlugField()

    def current_user_zone_permission(self):
        return ZonePermission.objects.get(zone=self, user=user)

私がこの方法を気に入っている理由は、API と HTTP 経由の API の内部の一貫性が保たれるからです。

class ZoneSerializer(serializers.HyperlinkedModelSerializer):
    current_user_zone_permission = ZonePermissionSerializer()

    class Meta:
        model = Zone
        fields = ('name', 'current_user_zone_permission')

うまくいけば、これは何人かの人々を助けます!

注: 名前が一致する必要はありません。必要に応じてソース kwarg を使用できます。

編集:モデルの関数がユーザーまたはリクエストにアクセスできないことに気付きました。したがって、おそらくカスタム モデル フィールド / ListSerializer がこのタスクにより適しているでしょう。

于 2015-04-17T08:52:28.130 に答える