django rest单线程/阻塞视图

时间:2018-07-18 16:59:51

标签: python django python-3.x django-rest-framework pyinstaller

在单个用户执行视图时,是否有可能阻止视图中的代码被所有访问该视图的用户执行?一种单线程视图。

我需要它,因为在此视图中我用pyinstaller生成了python可执行文件,并通过配置文件将用户名传递给了可执行文件。

例如:

class CliConfig(APIView):

    def get(self, request, format=None):
        try:
            config['DEFAULT']['username'] = request.user

            #make a build with pyinstaller
            bin_file = open(*generated filepath *, 'rb')
            response = Response(FileWrapper(bin_file), content_type='application/octet-stream')
            response['Content-Disposition'] = 'attachment; filename="%s"' % '*filename*'
            return response
        finally:
            config['DEFAULT']['username'] = ''

因此,基本上我想要的是在Django rest框架APIView中生成一个python可执行文件,它将具有它的设置唯一的用户名。除了通过设置文件传递用户名外,我看不到其他方法。如果有办法的话,不胜感激。

python 3.6.5djangorestframework==3.8.2pyinstaller==3.3.1

2 个答案:

答案 0 :(得分:5)

为什么要将用户名存储在配置中? 这代人不是每个用户都可以吗?

无论如何,在视图内部执行耗时的任务不是一种好习惯。
使用Celery执行长期任务,这些任务将生成可执行文件并接受任何变量而不会停止Django。在该任务结束时,Celery可以将可执行文件发送到电子邮件或其他内容。

from celery import Celery

app = Celery('hello', broker='amqp://guest@localhost//')


@app.task
def generate_executable(username):
    # make a build with pyinstaller with username

    bin_file = open(*generated filepath *, 'rb')
    response = Response(FileWrapper(bin_file), content_type='application/octet-stream')
    response['Content-Disposition'] = 'attachment; filename="%s"' % '*filename*'

    # send email and/or returns as task result

    return response


class CliConfig(APIView):

    def get(self, request, format=None):
        task = generate_executable(request.user)
        task.delay()

        return Response({"status": "started", "task_id": task.task_id})

答案 1 :(得分:2)

看看Django-channels项目。通道将抽象提供给开发人员并支持许多协议,包括HTTP。您可以将关键页面重写为渠道使用方。因此,您将能够使用async/await构造以块的方式编写异步代码。 https://channels.readthedocs.io/en/latest/topics/consumers.html#asynchttpconsumer

您还可以通过Javascript显示锁定状态并使用Redis锁定机制:https://redis.io/topics/distlock

# <settings_dir>/settings.py
ASGI_APPLICATION = "my_app.routing.application"


# my_app/routing.py
from channels.routing import ProtocolTypeRouter

from .consumers import LockConsumer


application = ProtocolTypeRouter({
    "websocket": AuthMiddlewareStack(
        URLRouter([
            url("^ws/lock$", LockConsumer),
        ])
    ),
})


# my_app/consumers.py
class LockConsumer(JsonWebsocketConsumer):

    def connect(self):
        if self.scope['user'].is_authenticated:
            self.accept()
        else:
            self.close(code='unauthorized')
        pass

    def receive_json(self, content, **kwargs):
       # process lock procedures
       # try to lock by REDIS API
       # if locked -> show alarm to user by javascript 


# template, see fuul doc here http://channels.readthedocs.io/en/latest/javascript.html
...
<script src="{% static "websocketbridge.js" %}"></script>
....
相关问题