在django rest框架中限制对foreignkey的选择

时间:2014-03-04 13:35:22

标签: django django-rest-framework

如何限制request.user的图像与节点链接。我希望我能做一些像:

photo = models.ForeignKey(
    Image,
    limit_choices_to={'owner': username},
)

但是request.user而不是username,我不想使用本地线程。

models.py

class Node(models.Model):
    owner = models.ForeignKey(User)
    content = models.TextField()
    photo = models.ForeignKey(Image)

class Image(models.Model):
    owner = models.ForeignKey(User)
    file = models.ImageField(upload_to=get_upload_file_name)

serializers.py

class ImageSerializer(serializers.ModelSerializer):
    owner = serializers.Field('owner.username')

    class Meta:
        model = Image
        fields = ('file', 'owner')

class NodeSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Node
        fields = ('content', 'photo', 'owner')

5 个答案:

答案 0 :(得分:9)

我会通过覆盖get_serializer_class在运行时动态返回一个序列化程序类来处理这个问题,在那里的字段上设置choices选项:

def get_serializer_class(self, ...):
    user = self.request.user
    owner_choices = ...  # However you want to restrict the choices

    class ImageSerializer(serializers.ModelSerializer):
        owner = serializers.Field('owner.username', choices=owner_choices)

        class Meta:
            model = Image
            fields = ('file', 'owner')

    return ImageSerializer

答案 1 :(得分:7)

您可以创建自定义外键字段并在其中定义get_queryset()方法,以便仅将相关对象过滤为您的用户。可以在上下文中从请求中检索当前用户:

class UserPhotoForeignKey(serializers.PrimaryKeyRelatedField):
    def get_queryset(self):
        return Image.objects.filter(owner=self.context['request'].user)

class NodeSerializer(serializers.HyperlinkedModelSerializer):
    photo = UserPhotoForeignKey()
    class Meta:
        model = Node
        fields = ('content', 'photo', 'owner')

此示例使用Django REST Framework第3版。

答案 2 :(得分:4)

class CustomForeignKey(serializers.PrimaryKeyRelatedField):
    def get_queryset(self):
        return Table.objects.filter(is_active=True)

class Serializer(serializers.ModelSerializer):
    (...)
   table= CustomForeignKey()
   class Meta:
   (...)

更容易:

class Serializer(serializers.ModelSerializer):
    (...)
    table = serializers.PrimaryKeyRelatedField(queryset=Table.objects.filter(is_active=True)) 
    class Meta:
    (...)

答案 3 :(得分:0)

因为我确信此逻辑将在整个Django应用程序中使用,为什么不使其更通用?

class YourPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):

    def __init__(self, **kwargs):
        self.model = kwargs.pop('model')
        assert hasattr(self.model, 'owner')
        super().__init__(**kwargs)


    def get_queryset(self):
        return self.model.objects.filter(owner=self.context['request'].user)

serializers.py

class SomeModelSerializersWithABunchOfOwners(serializers.ModelSerializer):

    photo = YourPrimaryKeyRelatedField(model=Photo)
    categories = YourPrimaryKeyRelatedField(model=Category,
                                            many=True)
    # ...

答案 4 :(得分:0)

from rest_framework import serializers

class CustomForeignKey(serializers.PrimaryKeyRelatedField):
    def get_queryset(self):
        return Table.objects.filter(user=self.context['request'].user)
        # or: ...objects.filter(user=serializers.CurrentUserDefault()(self))

class Serializer(serializers.ModelSerializer):
   table = CustomForeignKey()