簡體   English   中英

Django REST Framework:在一次交易中保存/更新/刪除具有相關性的對象。 如何?

[英]Django REST Framework: save/update/delete object with related in one transaction. How to?

我想問你,如何使用DRF處理帶有許多內聯對象(例如Django Admin + FormSet中)的添加/編輯/刪除對象。 例如:

Publication:
  - title
  - description
  + Notofications (1 and more)
    - first_name
    - email
  + Images (1 and more)
    - title
    - url
  + Attributes (1 and more)
    - name
    - value

JSON輸入:

{
     "title": "..", 
     "description": "..", 
     "notifications": [{"first_name": "", "email": ""}, ...]
     "images": [{"title": "", "url": ""}, ...]
     "attributes": [{"name": "", "value": ""}, ...]
}

因此,我認為“添加”這樣的結構非常簡單,但是“更新”(或“修補”)和“刪除”(例如圖像之一)又如何呢? 整個請求應在事務中完成,例如:如果我們對出版物的標題和圖像的url進行了一些編輯,並且url的格式錯誤,則我們既不應保存發布對象,也不應保存圖像對象。

REST API中有一個好的模式嗎?

謝謝。

我建議使用嵌套的序列化程序來實現:

class NestedNotificationSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Notification
        fields = ('id', 'first_name', 'email')

    def to_internal_value(self, data):
        """ Return exist notification as internal value if id is provided """
        if 'id' in data:
            try:
                return models.Notification.objects.get(id=data['id'])
            except models.Notification.DoesNotExists:
                raise serializers.ValidationError('Notification with id %s does not exist' % data['id'])
        else:
            internal_data = super(NestedNotificationSerializer, self).to_internal_value(data)
            return models.Notification(**internal_data)


class PublicationSerializer(serializers.ModelSerializer):

    notifications = NestedNotificationSerializer(many=True)
    ...

    def create(self, validated_data):
        notifications = validated_data.pop('notifications', [])
        # create publication and its notifications in one transaction
        with transaction.atomic():
            publication = super(PublicationSerializer, self).create(validated_data)
            for notification in notifications:
                publication.notifications.add(notification)

        return publication

    def update(self, instance, validated_data):
        notifications = validated_data.pop('notifications', [])
        new_notifications = [notification for notification in notifications if notification.id is None]
        existed_notifications = set([notification for notification in notifications if notification.id is not None])

        # update publication and its notifications in one transaction:
        with transaction.atomic():
            publication = super(PublicationSerializer, self).update(instance, validated_data)
            old_notifications = set(publication.notifications.all())

            removed_notifications = old_notifications - existed_notifications
            for notification in removed_notifications:
                notification.delete()

            for notification in new_notifications:
                publication.notifications.add(notification)

        return publication

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM