在单个用户执行视图时,是否有可能阻止视图中的代码被所有访问该视图的用户执行?一种单线程视图。
我需要它,因为在此视图中我用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.5
,djangorestframework==3.8.2
,pyinstaller==3.3.1
答案 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>
....