Saturday, July 28, 2018

django rest single thread / blocking view

Leave a Comment

Is it possible to block a code in view from execution by all users accessing the view while it is being executed by a single user? Kind of single-thread view.

I need it because i generate the python executable with pyinstaller in this view and passing a username into the executable through the config file.

For example:

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'] = '' 

So, basically what i want is to generate a python executable which will have a unique username it it's settings, in django rest framwork APIView. I don't see other approach except passing the username through the settings file. If there is a way - would appreciate an advise.

python 3.6.5, djangorestframework==3.8.2, pyinstaller==3.3.1

3 Answers

Answers 1

Why do you store the username in the config? Shouldn't this generation be per user?

Anyhow it is not good practice to do time-consuming tasks inside views.
Use Celery for long-term tasks that will generate executables and will accept any variables without stopping Django. At the end of this task Celery can send executable to email or something.

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}) 

Answers 2

Take a look at Django-channels project. channels give abstraction to developer and support many protocols including HTTP. You can rewrite critical pages to channels consumers. So you will be able to write asynchronious code in block manner using async/await constructions. https://channels.readthedocs.io/en/latest/topics/consumers.html#asynchttpconsumer

Answers 3

This is not Django related question. What you would like is to lock the 'method' and not allow the other threads to access it while there is a lock on this method. This is somenthing that python can do for you.

I recommend you reading this post http://effbot.org/zone/thread-synchronization.htm#locks or refer to this answer Locking a method in Python?

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment