获取最近创建的Django Rest Framework对象的ID [英] Get the id of the object recently created Django Rest Framework

查看:281
本文介绍了获取最近创建的Django Rest Framework对象的ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Django REST Framework为我的移动应用程序提供API。创建新设备时,需要发送其所有者的电子邮件作为额外的参数。

I am using Django REST Framework to provide an API for my mobile app. I need send as extra argument when I creating a new Device the email of his owner.

实际上,我发送的是与此类似的json:

Actually I send a json similar to this:

{"os_type": "AND",
 "token": "dfsdfdfsd",
 "email": "sdfdfd@sdfs.com"
}

我需要将一些数据传递给标准ModelViewSet并覆盖一小部分(提取所有者的电子邮件并将其与最近创建的设备相关联。问题是我不知道如何获取该新对象的ID。

I need pass some data to the standard ModelViewSet and overrides a little part (extract the email of the owner and associate It with the Device recently created. The problem is that I don't know how to get the id of this new object.

我的设备模型具有以下ModelViewSet:

I have this ModelViewSet for my Device model:

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

创建的对象的类型为Response,它将显示所有信息,但我想以更优雅或更正确的方式获取ID。

The "created" object is type Response, and that will render with all de info, but I would like to get the ID in a more elegant or right way.

这是我的设备模型:

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)

我宁愿不要在我的设备模型中添加字段所有者,因为我已经拥有引用设备的所有者模型:

I prefer don't add the field owner in my Device model, because I have already the Owner model that refers to Device:

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)

如何解决此问题?

推荐答案

您可以通过在您的视图中覆盖 perform_create

You can perform actions after objects are created in Django REST Framework by 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 而不是<视图中的code> create 方法,您不必担心会对 create 方法进行的任何更改在升级过程中丢失。推荐使用 perform_create 方法,因此您不必担心该中断。

By overriding perform_create instead of the create method on the view, you won't have to worry about any changes being made to the create method that you will be missing during upgrades. The perform_create method is the recommended hook, so you don't need to worry about that breaking.

我我们还对创建设备之前进行的检查做了一些更改。

I've also made a few changes to the checks that are being done before the device is created.


  1. 正在为提出 ValidationError 未随请求传递电子邮件时出现400 错误。这将产生与其他字段相同的样式错误消息,并应由默认的异常处理程序处理。

  2. try ...除外仅限于 DoesNotExist 错误,如果用户提供的无效电子邮件与数据库所有者不匹配,则会触发该错误。这将防止您压榨那些未被考虑的边缘情况,尽管<$ <$ <$ <$ c $ c> DoesNotExist 和 MultipleObjectsReturned 异常是您真正应该从 get收到的唯一异常呼叫。

  3. 未知电子邮件的错误不再包含例外通知,已经存在的消息应该没问题。

  1. A ValidationError is being raised for the 400 error when the email is not passed in with the request. This will produce the same style error messages as other fields, and should be handled by the default exception handler.
  2. The try...except has been limited to the DoesNotExist error that will be triggered if the user gives an invalid email that does not match an owner in the database. This will prevent you squashing edge cases that weren't considered, though the DoesNotExist and MultipleObjectsReturned exceptions are the only ones that you should really receive from a get call.
  3. The error for an unknown email no longer includes the exception notice, the message that is there already should be fine.

此外,如果有一种方法可以绑定当前发出请求的用户(在 request.user 中提供) )发送给正在创建的设备的所有者(在本例中为 owner ),您可能希望跳过他们提供的电子邮件。当然,这取决于API应该如何运行,因为您可能希望允许用户将设备绑定到另一个所有者的帐户。

Also, if there is a way to tie the current user making the request (provided in request.user) to the owner of the device being created (owner in this case), you might want to skip them providing the email. This depends on how the API is supposed to function of course, because you might be interested in allowing users to tie devices to another owner's account.

这篇关于获取最近创建的Django Rest Framework对象的ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆