1

Я настраиваю систему, в которой один пользователь будет размещать изображения на сервере Django, и каждый пользователь N будет просматривать подмножество размещенных изображений параллельно. Кажется, я не могу найти механизм очередей в Django для выполнения этой задачи. Самое близкое - использовать последние с filter(), но это будет просто продолжать отправку последнего изображения снова и снова, пока не появится новый. Очередь задач не помогает, поскольку это не периодическая задача, она возникает только тогда, когда пользователь запрашивает следующее изображение. У меня есть один Viewset для загрузки изображений, а другой - для загрузки. Я подумал о том, чтобы использовать поточную безопасную очередь python. Разгрузочная машина будет выгружать загруженное изображение pk, а когда несколько пользователей запросят новое изображение, отправляющий декодер будет деинсталлировать изображение pk и отправить его последнему пользователю, запрашивающему изображение, а затем следующий разворачивается второму последнему пользователю и так далее ...Очередь в Django

Однако, я все еще чувствую, что здесь возможны некоторые условия гонки. Я читал, что Django является потокобезопасным, но приложение может стать безошибочным. Кроме того, Queue должна быть глобальной, чтобы быть доступной среди Viewsets, которая воспринимается как плохая практика. Есть ли лучший и безопасный способ обойти это?

Редактировать

Здесь более подробно о том, что я пытаюсь сделать, и дать ему некоторый контекст. Пользователь, отправляющий фотографии, является смартфоном, прикрепленным к Drone. Он будет размещать изображения с неба с постоянным интервалом до сервера Django. Поскольку будет много фотографий, я бы хотел, чтобы несколько пользователей разделили нагрузку на все фотографии (т. Е. Ни один пользователь не должен видеть одно и то же изображение). Поэтому, когда пользователь свяжется с сервером Django, скажем: «Отправьте мне следующий снимок, который у вас есть или отправьте мне следующие 3 фотографии, которые у вас есть и т. Д.». Тем не менее, несколько пользователей могут сказать это одновременно. Таким образом, Django должен сохранять какие-то заказы на фотографии, поэтому я сказал «Очередь» и выяснил, как передать их пользователям, если за них спрашивают более одного из них. Таким образом, один Viewset предназначен для того, чтобы смартфон опубликовал фотографии, а другой - для пользователей, чтобы попросить фото. Я ищу потокобезопасный способ сделать это. Единственная идея, которую я имею до сих пор, - использовать Python в потокобезопасной очереди и сделать ее глобальной очередью в Viewsets. Тем не менее, я чувствую, что это плохая практика, и я не уверен, что это потокобезопасно с Django.

+1

Я думаю, вам нужно расширить описание того, что вы пытаетесь сделать и почему (ожидаемое поведение). Если я читаю это правильно, вы хотите настроить «получать новые изображения с тех пор, как« i «последний раз» запрашивал запрос от каждого пользователя. например пользователи отправляют время, время последнего отправления запроса, сервер отправляет обратно все изображения, добавленные с этого времени. –

+0

@ warath-coder Спасибо, что упомянули об этом. Я добавил более подробно – dylan7

+0

Итак, вы можете изменить то, что я предложил, когда вы добавляете изображение, также добавляете запись в «просмотренных» таблицах. Затем пользователи могли запросить X-число «не просматриваемых» изображений. Вы можете заблокировать просмотренную таблицу, отметить просмотры X-изображений, разблокировать таблицу, а затем отправить фотографии. Я очень сомневаюсь, что для этого есть решение «из коробки». –

ответ

1

Django сам не имеет очереди, но вы можете легко имитировать его. Лично я, вероятно, использовал бы внешнюю службу, например rabbitMQ, но это можно сделать в чистом Django, если хотите. Добавьте отдельную модель ImageQueue для хранения ссылок на входящие изображения и используйте управление транзакциями, чтобы убедиться, что одновременные запросы не возвращают одно и то же изображение. Может быть, что-то вроде этого (это, конечно, чисто доказательство кода концепции).

 
class ImageQueue(models.Model): 
    image = models.OneToOne(Image) 
    added = models.DateTimeField(auto_now_add=True) 
    processed = models.DateTimeField(null=True, default=None) 
    processed_by = models.ForeignKey(User, null=True, default=None) 

    class Meta: 
     order_by=('added') 

... 
# in the incoming image API that drone uses 
def post_an_image(request): 
    image = Image() 
    ... whatever you do to post an image ... 
    image.save() 
    queue = ImageQueue.objects.create(image=image) 
    ... whatever else you need to do ... 

# in the API your users will use 
from django.db import transaction 

@transaction.atomic 
def request_images(request): 
    user = request.user 
    num = request.POST['num'] # number of images requested 
    queue_slice = ImageQueue.objects.filter(processed__isnull=True)[:num] 
    for q in queue_slice: 
     q.processed = datetime.datetime.now() 
     q.processed_by = user 
     q.save() 
    return [q.image for q in queue_slice]