Django - назначить одну запись из набора запросов пользователю и обновить ее. Передача записи другому пользователю только в случае неудачи транзакции

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

Есть несколько пользователей (сборщиков заказов), которые вошли в систему одновременно и которым нужно получить продукты со склада.

Моя модель выглядит следующим образом:

class Product(models.Model):

    location = models.IntegerField(validators=[MinValueValidator(1),MaxValueValidator(5000)])
    already_picked = models.BooleanField(default=False, blank=True)
    available_for_picking = models.DateField(blank=True, null=True)

    def __str__(self):
        return str(self.id)

Продукты, которые необходимо забрать со склада в определенный день, должны соответствовать ряду условий.

Например:

  • available_for_picking = сегодня или дата в прошлом

И

  • aldready_picked = False

Что я хочу сделать:

Каждый пользователь переходит по адресу url: www.mydomain.com/get_order_location_to_pick и получает местоположение товара, который он должен забрать со склада.

Однако есть несколько продуктов, которые соответствуют критериям выбора, и есть несколько пользователей, которые используют программное обеспечение в одно и то же время. Поэтому я хочу избежать назначения одного и того же продукта (и места) более чем одному пользователю. Когда пользователь взял продукт, boolean "already_picked" должен быть изменен с False на True. Если пользователь по какой-либо причине не смог забрать назначенный ему товар со склада, товар должен быть назначен другому пользователю, когда он/она перейдет по тому же url www.mydomain.com/get_order_location_to_pick

Какой хороший способ сделать это?

В настоящее время я имею следующее:

@login_required(login_url='login')
def get_order_location(request):
    products_to_pick = Product.objects.filter(already_picked=False, available_for_picking__lte= datetime.now())
    first_product_to_pick = products_to_pick.first()
    context = {
        'first_product_to_pick' : first_product_to_pick
    }
    return render(request, 'show_the_order_to_pick.html', context)

Это не совсем работает. Он просто дает один и тот же продукт из QuerySet и присваивает его всем пользователям, которые в настоящее время посещают url www.mydomain.com/get_order_location_to_pick

Я читал что-то о функции Django select_for_update(), но не могу понять, что она делает. Могу ли я использовать ее для "блокировки" первого товара для первого пользователя, пока он занят поиском товара на складе?

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

Это не совсем работает. Он просто выдает один и тот же продукт из QuerySet и присваивает его всем пользователям, которые в данный момент посещают url

.

Это представление не изменяет атрибут already_picked продукта, который оно выбирает, поэтому оно будет показывать один и тот же продукт всем.

Я читал что-то о функции Django select_for_update(), но я не могу понять, что она делает. Могу ли я использовать ее для "блокировки" первого товара для первого пользователя, пока он занят поиском товара на складе?

.

Да, это верно. select_for_update() можно использовать для блокировки строк на короткий период времени, пока вы помечаете их как выбираемые. Также обратите внимание на параметр skip_locked этой функции, который можно использовать, чтобы сообщить базе данных, что если select встретит заблокированный ряд, то он должен пропустить его, а не ждать, пока ряд станет доступным.

Вернуться на верх