Django выполняет второй запрос перед возвратом первого

#django #django-rest-framework

#django #django-rest-framework

Вопрос:

Я отправляю два запроса ИСПРАВЛЕНИЙ из моего интерфейса в Django сразу один за другим. Оба запроса достигают одной и той же конечной точки django REST framework (см. Ниже).

Моя проблема заключается в порядке, в котором все происходит. Следующий код выдает мне эту печать:

 FIRST PATCH: clearing
SECOND PATCH HAPPENING
FIRST PATCH: after adding references
 

Итак, как вы можете видеть, второй патч выполняется в середине первого. Что заставляет его возвращать экземпляр, в котором поле ссылок пустое, поскольку оно еще не было заполнено повторно.

  def partial_update(self, request, pk=None, *args, **kwargs):
    if 'height' in data or 'pos_x' in data:
        # do something             
        print("SECOND PATCH HAPPENING")
        return super(NodeViewSet, self).partial_update(request, *args, **kwargs)

    reference_ids = request.data.get('references', None)
    if reference_ids is not None:
        references = Node.objects.filter(pk__in=reference_ids)
        instance = self.get_object()

        print("FIRST PATCH: clearing")

        instance.references.clear()
        instance.references.add(*references)

        print("FIRST PATCH: after adding references")

    return super(NodeViewSet, self).partial_update(request, *args, **kwargs)
 

Почему это происходит? Как я могу гарантировать, что второй ПАТЧ не произойдет в середине первого?

Комментарии:

1. Как вы отправляете эти запросы? Если вы хотите, чтобы они всегда выполнялись последовательно, вы должны отправлять их синхронно, а не асинхронно.

2. Это запросы jquery Ajax.

Ответ №1:

Вы не можете контролировать это на стороне сервера, даже если вы отправляете запрос после отправки другого, вы не можете контролировать, какой из них будет выполняться первым. Они зависят от многих факторов, в том числе от того, какому процессу они назначены на серверном компьютере, от сетевого пути, по которому проходят пакеты, и т.д.

Если вы хотите убедиться, что запрос отправляется после завершения другого, вам необходимо убедиться в этом на стороне клиента. Что-то вроде следующего, с jquery ajax:

 $.ajax({
        url : 'url',
        type : 'PATCH',
        data : data,
        success : function(response, textStatus, jqXhr) {
            // Issue the second request here, after the first one is completed successfully
            $.ajax({
                url : 'url',
                type : 'PATCH',
                data : data,
                success: function(response, textStatus, jqXhr) {
                    // Both requests succeeded here, issued sequentially
                }
            }
        },
        error : function(jqXHR, textStatus, errorThrown) {
            ...
        }
});
 

Комментарии:

1. Честно говоря, порядок, в котором обрабатываются эти запросы, не так важен, как тот факт, что второй запрос не выполняется прямо в середине первого. Есть идеи, почему это происходит?

2. @RyanPergent это вызвано параллелизмом. Если ваше приложение django не обслуживается в одном процессе / одном потоке, что почти никогда не бывает при производственных развертываниях, запросы обрабатываются одновременно. Таким образом, в то время как ваш первый запрос ожидает чтения данных, например, из базы данных, ваш второй запрос поступает и выполняется в другом процессе или потоке. Это может быть и наоборот. Вы не должны создавать свое приложение с предположением, что вы будете обслуживать один запрос за раз