使用Django Rest框架创建对象时将数据更新到序列化器

时间:2019-01-25 11:21:51

标签: python django django-rest-framework

我的models.py看起来像这样:

class Activity(models.Model):
    name = models.CharField(max_length=50, unique=True)
    description = model.TextField(max_length=500)

class Jira(models.Model):
    jira_id = models.CharField(max_length=50, unique=True)
    activity = model.ForeignKey(Activity, null=True on_delete=models.SET_NULL)

一个活动可以关联多个Jira票证。因此,我使用外键表示一对多关系。

我创建新活动的序列化器如下:

class ActivityCreateSerializer(serializers.ModelSerializer):
    name = serializers.CharField(max_length=50)
    description = serializers.CharField(max_length=50)
    jira_ticket = serializers.ReadOnlyField()

我的看法如下:

class ActivtyViewSet(viewsets.ViewSet):
    def create(self, request):
        serializer = ActiityCreateSerializer(data=request.data)
        if serializer.is_valid():
           #jira_ticket = make call to jira and get a valid ticket number
           serializer.save()
           return Response(serializer.data, status=status.HTTP_201_CREATED)

很明显,在创建新的Activity时,需要向Jira票务系统发送外部API调用以创建新的jira_ticket。这成功发生,我得到了jira_ticket号。 我的问题有两个:

  1. 我如何将Jira票证保存在数据库中,因为它不属于序列化程序,并且仅在从外部API调用发出请求后才能获得?
  2. 由于serializer.data是不可变的,并且我无法将jira_ticket附加到响应字典上,因此如何将jira票号添加到序列化器输出中?

2 个答案:

答案 0 :(得分:0)

在调用serializer.save()后的视图中,调用jira票证的api,并使用该API存储jira票证对象以及从serializer.save()方法返回的活动对象。您还需要更新响应以包括jira票证数据,由于该视图将更新响应数据,因此不需要只读字段。希望这会有所帮助

答案 1 :(得分:0)

您可以覆盖drf的预保存钩子perform_create(),类似这样。

class ActivtyViewSet(viewsets.ViewSet):
    def perform_create(self, serializer):
        serializer(jira_number=get_jira_ticket_number(serializer.data))
        serializer.save()

参考:https://www.django-rest-framework.org/api-guide/generic-views/(搜索perform_create

但是我想,在您的请求-响应周期中调用第三方api不是一个好习惯。如果出了问题会从jira提取ticket_number怎么办?

我将返回我们拥有的所有数据,并触发一个后台任务,以从jira提取ticket_number并用其更新保存的对象。客户应继续轮询jira ticket_number。或类似的东西。