获取最近创建的对象的 id Django Rest Framework
Get the id of the object recently created Django Rest Framework
我正在使用 Django REST Framework 为我的移动应用程序提供 API。我需要在创建新设备时将其所有者的电子邮件作为额外参数发送。
实际上我发送了一个类似这样的json:
{"os_type": "AND",
"token": "dfsdfdfsd",
"email": "sdfdfd@sdfs.com"
}
我需要将一些数据传递给标准 ModelViewSet 并覆盖一小部分(提取所有者的电子邮件并将其与最近创建的设备相关联。问题是我不知道如何获取 id这个新对象。
我的设备型号有这个 ModelViewSet:
class DeviceViewSet(viewsets.ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
def create(self, request):
"""
Overrides the create method in order to get
extra params: the email of the device's owner.
When this is done, we pass the method to his parent.
"""
print "creating..."
created = super(DeviceViewSet, self).create(request)
print type(created).__name__
#[method for method in dir(created) if callable(getattr(created, method))]
return created
"created" 对象是 Response 类型,它将使用所有 de 信息呈现,但我想以更优雅或正确的方式获取 ID。
这是我的设备型号:
class Device(models.Model):
"""
iOS or Android device, where is installed the app
"""
ANDROID = 'AND'
IOS = 'IOS'
OS_DEVICES_CHOICES = (
(ANDROID, 'Android'),
(IOS, 'iOS'),
)
os_type = models.CharField(max_length=3, choices=OS_DEVICES_CHOICES)
token = models.CharField(max_length=1000)
active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
我不想在我的设备模型中添加字段所有者,因为我已经有引用设备的所有者模型:
class Owner(models.Model):
name = models.CharField(max_length=200, blank=True, null=True)
biography = models.TextField(max_length=1000, blank=True, null=True)
birthday = models.DateField(blank=True, null=True)
country = models.CharField(max_length=50, blank=True, null=True)
language = models.CharField(max_length=50, blank=True, null=True)
email = models.EmailField(blank=True, null=True)
devices = models.ManyToManyField(Device)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return u'[{0}] {1}'.format(self.id, self.name)
def __unicode__(self):
return u'[{0}] {1}'.format(self.id, self.name)
如何解决这个问题?
终于解决了我自己编写代码保存序列化器对象并直接获取ID的问题。
这是完整代码:
class DeviceViewSet(viewsets.ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
def create(self, request):
"""
Overrides the create method in order to get
extra params: the email of the device's owner.
When this is done, we pass the method to his parent.
"""
print "creating..."
data = request.data
email = None
if 'email' in data:
email = data['email']
else:
return Response("No owner email provided", status=status.HTTP_400_BAD_REQUEST)
try:
owner = Owner.objects.get(email=email)
except Exception as e:
print e
return Response('No owner with the email ({0}) found, error: {1}'.format(email, e),
status=status.HTTP_406_NOT_ACCEPTABLE)
serializer = DeviceSerializer(data=request.data)
if serializer.is_valid():
device = serializer.save()
print device.id
owner.devices.add(device)
#device.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
您可以在 Django REST Framework 中通过 overriding perform_create
on your view 创建对象后执行操作。
class DeviceViewSet(viewsets.ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
def perform_create(self, serializer):
from rest_framework.exceptions import ValidationError
data = self.request.data
if "email" not in data:
raise ValidationError({
"email": "No owner email provided",
})
try:
owner = Owner.objects.get(email=data["email"])
except Owner.DoesNotExist:
return Response(
'No owner with the email ({0}) found'.format(email),
status=status.HTTP_406_NOT_ACCEPTABLE
)
device = serializer.save()
owner.devices.add(device)
通过覆盖视图上的 perform_create
而不是 create
方法,您不必担心对 create
方法所做的任何更改会丢失在升级过程中。 perform_create
方法是推荐的钩子,因此您无需担心会中断。
我还对在创建设备之前进行的检查进行了一些更改。
- A
ValidationError
is being raised 当电子邮件未随请求一起传递时出现 400
错误。这将产生与其他字段相同样式的错误消息,应由默认异常处理程序处理。
try...except
仅限于 DoesNotExist
错误,如果用户提供的电子邮件与数据库中的所有者不匹配,则会触发该错误。这将防止您压缩未考虑的边缘情况,though the DoesNotExist
and MultipleObjectsReturned
exceptions 是您真正应该从 get
调用中收到的唯一情况。
- 未知邮件的错误不再包含异常通知,已经存在的邮件应该没问题。
此外,如果有办法将发出请求的当前用户(在 request.user
中提供)与正在创建的设备的所有者(在本例中为 owner
)联系起来,您可能想跳过他们提供的电子邮件。这当然取决于 API 应该如何运作,因为您可能有兴趣允许用户将设备绑定到另一个所有者的帐户。
我正在使用 Django REST Framework 为我的移动应用程序提供 API。我需要在创建新设备时将其所有者的电子邮件作为额外参数发送。
实际上我发送了一个类似这样的json:
{"os_type": "AND",
"token": "dfsdfdfsd",
"email": "sdfdfd@sdfs.com"
}
我需要将一些数据传递给标准 ModelViewSet 并覆盖一小部分(提取所有者的电子邮件并将其与最近创建的设备相关联。问题是我不知道如何获取 id这个新对象。
我的设备型号有这个 ModelViewSet:
class DeviceViewSet(viewsets.ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
def create(self, request):
"""
Overrides the create method in order to get
extra params: the email of the device's owner.
When this is done, we pass the method to his parent.
"""
print "creating..."
created = super(DeviceViewSet, self).create(request)
print type(created).__name__
#[method for method in dir(created) if callable(getattr(created, method))]
return created
"created" 对象是 Response 类型,它将使用所有 de 信息呈现,但我想以更优雅或正确的方式获取 ID。
这是我的设备型号:
class Device(models.Model):
"""
iOS or Android device, where is installed the app
"""
ANDROID = 'AND'
IOS = 'IOS'
OS_DEVICES_CHOICES = (
(ANDROID, 'Android'),
(IOS, 'iOS'),
)
os_type = models.CharField(max_length=3, choices=OS_DEVICES_CHOICES)
token = models.CharField(max_length=1000)
active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
我不想在我的设备模型中添加字段所有者,因为我已经有引用设备的所有者模型:
class Owner(models.Model):
name = models.CharField(max_length=200, blank=True, null=True)
biography = models.TextField(max_length=1000, blank=True, null=True)
birthday = models.DateField(blank=True, null=True)
country = models.CharField(max_length=50, blank=True, null=True)
language = models.CharField(max_length=50, blank=True, null=True)
email = models.EmailField(blank=True, null=True)
devices = models.ManyToManyField(Device)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return u'[{0}] {1}'.format(self.id, self.name)
def __unicode__(self):
return u'[{0}] {1}'.format(self.id, self.name)
如何解决这个问题?
终于解决了我自己编写代码保存序列化器对象并直接获取ID的问题。
这是完整代码:
class DeviceViewSet(viewsets.ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
def create(self, request):
"""
Overrides the create method in order to get
extra params: the email of the device's owner.
When this is done, we pass the method to his parent.
"""
print "creating..."
data = request.data
email = None
if 'email' in data:
email = data['email']
else:
return Response("No owner email provided", status=status.HTTP_400_BAD_REQUEST)
try:
owner = Owner.objects.get(email=email)
except Exception as e:
print e
return Response('No owner with the email ({0}) found, error: {1}'.format(email, e),
status=status.HTTP_406_NOT_ACCEPTABLE)
serializer = DeviceSerializer(data=request.data)
if serializer.is_valid():
device = serializer.save()
print device.id
owner.devices.add(device)
#device.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
您可以在 Django REST Framework 中通过 overriding perform_create
on your view 创建对象后执行操作。
class DeviceViewSet(viewsets.ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
def perform_create(self, serializer):
from rest_framework.exceptions import ValidationError
data = self.request.data
if "email" not in data:
raise ValidationError({
"email": "No owner email provided",
})
try:
owner = Owner.objects.get(email=data["email"])
except Owner.DoesNotExist:
return Response(
'No owner with the email ({0}) found'.format(email),
status=status.HTTP_406_NOT_ACCEPTABLE
)
device = serializer.save()
owner.devices.add(device)
通过覆盖视图上的 perform_create
而不是 create
方法,您不必担心对 create
方法所做的任何更改会丢失在升级过程中。 perform_create
方法是推荐的钩子,因此您无需担心会中断。
我还对在创建设备之前进行的检查进行了一些更改。
- A
ValidationError
is being raised 当电子邮件未随请求一起传递时出现400
错误。这将产生与其他字段相同样式的错误消息,应由默认异常处理程序处理。 try...except
仅限于DoesNotExist
错误,如果用户提供的电子邮件与数据库中的所有者不匹配,则会触发该错误。这将防止您压缩未考虑的边缘情况,though theDoesNotExist
andMultipleObjectsReturned
exceptions 是您真正应该从get
调用中收到的唯一情况。- 未知邮件的错误不再包含异常通知,已经存在的邮件应该没问题。
此外,如果有办法将发出请求的当前用户(在 request.user
中提供)与正在创建的设备的所有者(在本例中为 owner
)联系起来,您可能想跳过他们提供的电子邮件。这当然取决于 API 应该如何运作,因为您可能有兴趣允许用户将设备绑定到另一个所有者的帐户。