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帖子。任何帮助表示感谢,谢谢。我想作为最后的手段,我可以从模型中删除唯一约束,但它是一个有效的约束,所以我宁愿把它留在。
答案 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)