【问题标题】:Django REST validator. Multiple users can have records with same value, but that record is unique for each user, how to do that?Django REST 验证器。多个用户可以拥有相同值的记录,但该记录对于每个用户都是唯一的,如何做到这一点?
【发布时间】:2020-09-12 09:12:14
【问题描述】:

我正在尝试使用 Django REST 框架完成以下任务。 我有模型记录,它有字段。它具有用户的外键。每个用户可以创建多个不同编号的记录,但不能为自己创建多个相同编号的记录。但是,每个其他用户都可以为自己创建具有相同编号的记录。 例如。用户乔和吉尔。 Joe 只能创建一次编号为 123 的记录,如果他尝试使用 123 再创建一个记录,则不应允许他。然而,吉尔可以为自己创造一次 123,但不能再创造更多。

我的猜测是在序列化器中创建一个验证器,也就是

class RecordSerializer(serializers.HyperlinkedModelSerializer):
    '''Serializer for Record'''

    class Meta:
        model = Record
        fields = [
            'user', 
            'number', 
            'otherfield', 
        ]

        validators = [
            UniqueValidator(
                queryset= Record.objects.filter(user=<current user>),
            )
        ]

但是,我无法在验证器属性中获取当前用户,否则我该如何完成此操作?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    您应该在序列化程序级别和模型级别添加约束,以防在序列化程序之外创建记录。 所以假设记录有idowner 字段,在模型的Meta 类中添加unique_together 属性:

    class Meta:
        unique_together = (('id', 'owner'))
    

    然后在序列化器中,可以使用CurrentUserDefault高级字段来捕获登录用户。

    from rest_framework.validators import UniqueTogetherValidator
    
    
    class RecordSerializer(serializer.ModelSerializer):
        owner = serializers.HiddenField(
            default=serializers.CurrentUserDefault()
        )
    
        class Meta:
            validators = [
                UniqueTogetherValidator(
                    queryset=Record.objects.all(),
                    fields=['id', 'owner']
                )
            ]
    

    当然,序列化器应该用在需要认证的视图中

    【讨论】:

    • 伙计们! @Andee 和 @Ken4Sholars!非常感谢!我花了一整天的时间寻找解决方案!
    • stackoverflow.com/a/55786819/7027427 的这个答案指出 UniqueConstraints 应该优于 unique_together,并且可以弃用。我也得到 迁移时指向这些字段的错误。
    • 是的,这只是在新版本的 Django 中指定唯一约束的首选方式,所以如果你有这样的版本,请继续使用它而不是 unique_together。至于IntegrityError,您似乎违反了唯一约束。这正是它通知开发人员它被违反的方式。我怀疑您是在序列化程序之外创建记录。表示该用户已经拥有该号码的记录。此外,您可能希望将我的回答中的 id 字段重命名为您在问题中描述的数字字段
    • 我在数据库中有违反约束的记录。删除它们并修复:) 再次非常感谢。
    【解决方案2】:

    在您的模型 Meta 上,设置 unique_together https://docs.djangoproject.com/en/3.0/ref/models/options/#unique-together

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-28
      • 1970-01-01
      相关资源
      最近更新 更多