Django Rest Framework:读写相关字段中的筛选



我有Users和Groups,其中Groups是Users上的PrimaryKeyRelatedField。在编写User时,我只想将其分配给当前用户所在的Groups。在检索User时,我仅想显示它与当前用户共有的Groups。

例如,假设user_1属于group_1user_2属于group_2。如果user_1ping到我想要的LIST USERS端点:

[{'groups': [1], 'username': 'user_1'}, {'groups': [], 'username': 'user_2'}]

注意,虽然group_2存在,但它没有列在user_2的组下,因为user_1不在其中

迄今为止的想法:

  • 重载to_representation似乎只会改变组在组列表中的显示方式,而根本不会改变它是否显示
  • 这里有一些关于如何筛选可写group选项的指南,这意味着user_1不能将自己添加到group_2
  • 有一些关于如何筛选只读字段的指南
  • 我可以把上面两个结合起来,做一个只读字段和一个只写字段,就像这里针对另一个问题所建议的那样,但我宁愿不这样做

我没有看到任何关于如何由当前用户过滤单个读/写RelatedField的指南有什么想法吗


我的代码:

# serializers.py, vanilla
from django.contrib.auth.models import User, Group
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'groups')

# views.py
from django.contrib.auth.models import User
from rest_framework.authentication import BasicAuthentication
from rest_framework import viewsets
from app import serializers
class UserViewSet(viewsets.ModelViewSet):
serializer_class = serializers.UserSerializer
queryset = User.objects.all()
authentication_classes = (BasicAuthentication,)
# serializers.py, with write-choice filter modification
class FilteredRelatedField(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
user = self.context['request'].user
user_groups = user.groups.values_list('id', flat=True)
queryset = Group.objects.filter(id__in=user_groups)
return queryset
class UserSerializer(serializers.ModelSerializer):
groups = FilteredRelatedField(many=True)
class Meta:
model = User
fields = ('username', 'groups')

# serializers.py, with read-only filtering
class UserSerializer(serializers.ModelSerializer):
groups = serializers.SerializerMethodField()
class Meta:
model = User
fields = ('username', 'groups')
def get_groups(self, instance):
instance_user_groups = instance.groups.values_list('id', flat=True)
current_user_groups = self.context['request'].user.groups.values_list('id', flat=True)
return [x for x in instance_user_groups if x in current_user_groups]

以下是我最终所做的。我认为它运行得很好,但如果有人有其他想法,请加入。

阻碍我前进的是对to_representation如何工作的错误假设。我想要的是更改一个对象的表示形式(在本例中,通过过滤列表),我知道我想以某种形式显示该对象。如果我根本不想显示该对象,最好在视图中处理。

to_representation设置任何单个对象的表示。我想过滤一个列表属性,所以我重载了to_representation

def to_representation(self, instance):
representation = super().to_representation(instance)
representation['groups'] = [x for x in representation['groups'] if x in [some_arbitrary_list_to_filter_against]]
return representation

这会过滤掉以供阅读。要使过滤器适用于读/写,请确保多对多字段是RelatedField的自定义子类,如本文所述。

最新更新