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 встретит заблокированный ряд, то он должен пропустить его, а не ждать, пока ряд станет доступным.