【问题标题】:update the same group if group name clashes如果组名冲突,则更新同一组
【发布时间】:2017-08-01 12:30:41
【问题描述】:

如果组用户的名称想要创建与已创建组匹配的组,我如何更新同一个组?如果我想更新而不是显示错误,我应该在哪里工作?它是在验证功能还是创建功能上?

这是我的序列化器

class DeviceGroupSerializer(serializers.ModelSerializer):
    id = serializers.UUIDField(source='token', format='hex', read_only=True)
    devices = DeviceIdSerializer(many=True)

    class Meta:
        model = DeviceGroup
        fields = ['id','name', 'devices',]

    def validate(self, data):
        errors = {}
        try:
            name = data['name']
            if not bool(name):
                #empty or null
                errors['name'] = 'Name cannot be empty'
        except KeyError:
            if not (self.instance and bool(self.instance.name)):
                errors['name'] = 'Name is required'

        if len(data.get('devices', [])) == 0:
            errors['devices'] = 'Device(s) should be specified.'

        if bool(errors):
            raise serializers.ValidationError(errors)
        return data

    def create(self, validated_data):
        # for create - there is always name; we have already checked that in validation
        # TODO Further check for group-name clash - if yes, update the same group
        owner = validated_data['owner']
        name = validated_data['name']
        group = DeviceGroup.objects.create(owner=owner, name=name)

        tokens = [d['token'] for d in validated_data['devices'] ]
        BaseDevice.objects.filter(token__in=tokens, owner=owner).update(group=group)
        return group

def update(self, instance, validated_data):
        # for update - there may or may not be name
        # if it does, it refers rename

        owner = validated_data['owner']
        name = validated_data.get('name', None)
        if not name is None:
            instance.update(name=name)

        tokens = [d['token'] for d in validated_data['devices'] ]
        BaseDevice.objects.filter(token__in=tokens, owner=owner).update(group=instance)
        return instance

【问题讨论】:

  • 您要更新DeviceGroup 还是BaseDevice
  • 如果我已经有一个名为重要的组,并且我再次为设备“device2”创建了一个组,那么应该将 device2 移动到同一组。

标签: python django django-rest-framework


【解决方案1】:

你想要update_or_create():

使用给定的 kwargs 更新对象的便捷方法, 如有必要,创建一个新的。默认值是一个字典 (field, value) 对用于更新对象。

根据您分享的内容,假设您想要更新DeviceGroup 上的所有者,如果具有给定nameDeviceGroup 已经存在:

    def create(self, validated_data):
        # for create - there is always name; we have already checked that in validation
        # TODO Further check for group-name clash - if yes, update the same group
        owner = validated_data['owner']
        name = validated_data['name']

        # created is a boolean telling us if a new DeviceGroup was created
        group, created = DeviceGroup.objects.update_or_create(name=name, defaults={'owner': owner})

        tokens = [d['token'] for d in validated_data['devices'] ]
        BaseDevice.objects.filter(token__in=tokens, owner=owner).update(group=group)
        return group

【讨论】:

  • 如果我有更新功能,在创建功能或更新中处理名称冲突更好吗?
  • 我有一个名为 device1, device2 的设备,其中设备 1 在重要组中,当我单击 device2 并创建一个新组重要时,设备 2 应该移动到已创建的重要组,而不是创建另一个具有相同的组名称
  • 对不起,我的代码有问题。它现在正在工作。但是,一个问题是,如果我现在创建一个重要组,那么设备将被移动到已创建的名为重要的组,而不是创建另一个重要组。但是如果我创建一个重要的组,它会创建一个新组。如何处理大写小写问题?
  • 解决这个问题的最快方法是执行group_exists = DeviceGroup.objects.filter(name__iexact=name).exists() 之类的操作或使用try:catch 块,如果@987654332,您尝试在其中获取DeviceGroup(使用name__iexact) @ 被提出,只需创建它。您也可以查看一些more options here,但它们比仅仅修改您的查询要复杂一些。
  • 我明白这一点,也感谢您提供信息丰富的解决方案。
猜你喜欢
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 2018-08-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
  • 2011-10-04
相关资源
最近更新 更多