在Django中排队请求图片
Queuing pictures to be requested in Django
我正在建立一个系统,其中一个用户将 posting 图像发送到 Django 服务器,N 个用户将同时查看 posted 图像的一个子集。我似乎无法在 Django 中找到一个队列机制来完成这个任务。最接近的是将 latest 与 filter() 一起使用,但这只会一遍又一遍地发送最新图像,直到出现新图像。任务队列没有帮助,因为这不是周期性任务,它仅在用户请求下一张图片时发生。我有一个 Viewset 用于上传图像,另一个用于获取。我考虑过使用 python 线程安全队列。卸载程序会将上传的图像 pk 排入队列,当多个用户请求新图像时,发送视图集会将图像 pk 出队并将其发送给最近请求图像的用户,然后下一个出队给第二个最近的用户和等等...
但是,我仍然觉得这里可能存在一些竞争条件。我读到 Django 是线程安全的,但该应用程序可能会变得非线程安全。此外,队列需要是全局的才能在视图集之间共享,这感觉是不好的做法。有没有更好更安全的方法来解决这个问题?
编辑
这里有更多关于我正在努力完成的事情的详细信息,并提供了一些背景信息。拍摄照片的用户 post 是连接到无人机的 Smart-phone。它将 post 以恒定的间隔从空中向 Django 服务器发送图片。因为会有很多图片进来。我希望能够让多个用户分担查看所有图片的工作量(即没有两个用户应该看到相同的图片)。因此,当用户联系 Django 服务器时,会说 "send me the next pic you have or send me the next 3 pics you have or etc..."。但是,多个用户可能会同时说这句话。所以 Django 需要对图片保持某种排序,这就是为什么我说 Queue 并弄清楚如果一次有多个用户请求时如何将它传递给用户。因此,一个 Viewset 是供智能 phone 到 post 图片的,另一个是供用户索取图片的。我正在寻找一种线程安全的方法来做到这一点。到目前为止我唯一的想法是使用 Python 的线程安全队列并使其成为视图集的全局队列。但是,我觉得这是一种不好的做法,而且我不确定它在 Django 中是否是线程安全的。
Django本身没有队列,但是你可以很容易的模拟出来。就个人而言,我可能会使用外部服务,如 rabbitMQ,但如果你愿意,也可以在纯 Django 中完成。添加一个单独的 ImageQueue 模型来保存对传入图像的引用,并使用事务管理来确保同时请求不会 return 相同的图像。也许是这样的(当然,这纯粹是概念代码的证明)。
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]
我正在建立一个系统,其中一个用户将 posting 图像发送到 Django 服务器,N 个用户将同时查看 posted 图像的一个子集。我似乎无法在 Django 中找到一个队列机制来完成这个任务。最接近的是将 latest 与 filter() 一起使用,但这只会一遍又一遍地发送最新图像,直到出现新图像。任务队列没有帮助,因为这不是周期性任务,它仅在用户请求下一张图片时发生。我有一个 Viewset 用于上传图像,另一个用于获取。我考虑过使用 python 线程安全队列。卸载程序会将上传的图像 pk 排入队列,当多个用户请求新图像时,发送视图集会将图像 pk 出队并将其发送给最近请求图像的用户,然后下一个出队给第二个最近的用户和等等...
但是,我仍然觉得这里可能存在一些竞争条件。我读到 Django 是线程安全的,但该应用程序可能会变得非线程安全。此外,队列需要是全局的才能在视图集之间共享,这感觉是不好的做法。有没有更好更安全的方法来解决这个问题?
编辑
这里有更多关于我正在努力完成的事情的详细信息,并提供了一些背景信息。拍摄照片的用户 post 是连接到无人机的 Smart-phone。它将 post 以恒定的间隔从空中向 Django 服务器发送图片。因为会有很多图片进来。我希望能够让多个用户分担查看所有图片的工作量(即没有两个用户应该看到相同的图片)。因此,当用户联系 Django 服务器时,会说 "send me the next pic you have or send me the next 3 pics you have or etc..."。但是,多个用户可能会同时说这句话。所以 Django 需要对图片保持某种排序,这就是为什么我说 Queue 并弄清楚如果一次有多个用户请求时如何将它传递给用户。因此,一个 Viewset 是供智能 phone 到 post 图片的,另一个是供用户索取图片的。我正在寻找一种线程安全的方法来做到这一点。到目前为止我唯一的想法是使用 Python 的线程安全队列并使其成为视图集的全局队列。但是,我觉得这是一种不好的做法,而且我不确定它在 Django 中是否是线程安全的。
Django本身没有队列,但是你可以很容易的模拟出来。就个人而言,我可能会使用外部服务,如 rabbitMQ,但如果你愿意,也可以在纯 Django 中完成。添加一个单独的 ImageQueue 模型来保存对传入图像的引用,并使用事务管理来确保同时请求不会 return 相同的图像。也许是这样的(当然,这纯粹是概念代码的证明)。
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]