处理应在django_rest_framework中替换的唯一约束

时间:2015-04-26 21:36:11

标签: django-rest-framework

tl; dr:我如何忽略(关闭)django_rest_framework中的唯一约束使用ListCreateAPIView创建调用,因为我将在perform_create方法中手动处理它?<​​/ p>

我正在使用第三方库django-push-notifications。它有一个很好的APNSDevice模型(苹果推送通知服务设备),它对registration_id字段有一个独特的约束。

我的问题是,有时我想手动删除表中具有注册ID的旧值,以便我可以插入新值。我想使用这个序列化器:

class APNSDeviceSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = APNSDevice
        fields = ('name', 'active', 'device_id', 'registration_id')

以及PUT的此代码

class MyAppleDevices(generics.ListCreateAPIView): 
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = APNSDeviceSerializer
    model = APNSDevice

    def get_queryset(self):
        return APNSDevice.objects.filter(user = self.request.user)

    def perform_create(self, serializer):
        print "Looking for old devices with registration id "+str(self.request.registration_id)
        oldDevices = APNSDevice.objects.filter(registration_id = self.request.registration_id)
        for oldDevice in oldDevices:
             oldDevice.delete()
        apnsDevice = serializer.save(user=self.request.user)

换句话说,我正在尝试手动删除在此特定PUT中具有唯一约束的其他条目,以便我可以在不违反唯一约束的情况下插入新条目。问题是验证器在调用perform_create方法之前运行,我无法弄清楚如何关闭验证器的唯一约束。我尝试将其添加到Serializer

    def get_validation_exclusions(self, instance = None):
        exclusions = super(APNSDeviceSerializer, self).get_validation_exclusions(instance)
        return exclusions + ['registration_id']

但它没有帮助,所以显然我不知道即使我已经倾注了文档和Stack Overflow帖子。任何帮助表示感谢,谢谢。我想作为最后的手段,我可​​以从模型中删除唯一约束,但它是一个有效的约束,所以我宁愿把它留在。

1 个答案:

答案 0 :(得分:-2)

我发现了这个问题,因为我对这个确切的库有这个确切的问题。您可以通过子类化序列化程序并手动覆盖字段定义来解决它:

class APNSDeviceSerializerWithNonUniqueRegistrationId(APNSDeviceSerializer):
    registration_id = serializers.CharField(min_length=64, max_length=64)

    class Meta(APNSDeviceSerializer.Meta):
        fields = ("name", "registration_id", "device_id", "active", "date_created")

然后,如果您正在使用django-push-notifications,您还需要覆盖使用该序列化程序的ViewSet:

class APNSDeviceAuthorizedViewSetWithNonUniqueRegistrationId(AuthorizedMixin, APNSDeviceViewSet):
    """
    The out of the box viewset/serializer combo require the registration ID to be unique and won't
    allow setting a registration ID to a new user (which is useful if we have potentially more than
    one account on a device.)
    """
    serializer_class = APNSDeviceSerializerWithNonUniqueRegistrationId

    def perform_create(self, serializer):
        if self.request.user.is_authenticated():
            try:
                existing_registration = APNSDevice.objects.get(
                    registration_id=serializer.validated_data['registration_id'])
                existing_registration.delete()
            except APNSDevice.DoesNotExist:
                pass
            serializer.save(user=self.request.user)
        return super(DeviceViewSetMixin, self).perform_create(serializer)