【问题标题】:Limit choices to foreignkey in django rest framework在 django rest 框架中将选择限制为外键
【发布时间】:2014-03-04 13:35:21
【问题描述】:

如何限制 request.user 的图像与节点链接。我希望我能做这样的事情:

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

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

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)

序列化器.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')

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    您可以创建一个自定义外键字段并在其中定义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】:
      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()
      

      【讨论】:

        【解决方案3】:

        我将通过覆盖 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
        

        【讨论】:

        • 非常感谢您的回答和出色的工作。
        • 这仍然是最好的方法吗?好像有点乱宁愿将我的序列化程序放在全局范围内,可以在其中导入和测试它们
        • serializers.Field 的构造函数似乎没有choices 参数了
        【解决方案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:
            (...)
        

        【讨论】:

          【解决方案5】:

          因为我确信这个逻辑将在整个 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)
          

          序列化器.py

          class SomeModelSerializersWithABunchOfOwners(serializers.ModelSerializer):
          
              photo = YourPrimaryKeyRelatedField(model=Photo)
              categories = YourPrimaryKeyRelatedField(model=Category,
                                                      many=True)
              # ...
          
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-03-27
            • 2021-12-09
            • 1970-01-01
            • 2021-06-07
            • 2010-09-18
            • 2014-09-11
            • 1970-01-01
            相关资源
            最近更新 更多