Reputation: 99
How can I define a function that stays active in the background?
For example, I want to press a button in the admin panel and then, Django starts updating all of the movies in the database using IMDB information.
If there are too many movies in the database, It can take too long for Django to update them. So I want the process of updating to stay active in the background and don't stop if I close the web browser.
1) How is this possible?
2) Can I add a progress bar to see how many movies are updated so far?
Upvotes: 0
Views: 236
Reputation: 2093
First Way:- You can start a thread on the click of button
import threading
# define your function to start updating the data through thread
def update_data(data):
....
....
# On the click of button, start thread
try:
your_thread = threading.Thread(
target=update_data,
args=(data)
)
your_thread.start()
except Exception as ex:
print("The exception is {}".format(ex))
Second Way:- You can configure celery and start celery task on the click of button
1. Install Celery
pip install Celery
2. Installing RabbitMQ
apt-get install -y erlang
apt-get install rabbitmq-server
3. Enable and start the RabbitMQ service
systemctl enable rabbitmq-server
systemctl start rabbitmq-server
4. Check the status of rabbitmq server
systemctl status rabbitmq-server
5. Add the CELERY_BROKER_URL configuration to the settings.py file
settings.py
CELERY_BROKER_URL = 'amqp://localhost'
6. Alongside with the settings.py and urls.py files, Create a new file named celery.py
celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'projectname,.settings')
app = Celery('projectname')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
7. Edit the __init__.py file in the project root
__init__.py
from .celery import app as celery_app
__all__ = ['celery_app']
8. create tasks.py inside any django app
tasks.py
import string
from django.contrib.auth.models import User
from django.utils.crypto import get_random_string
from celery import shared_task
@shared_task
def create_random_user_accounts(total):
for i in range(total):
username = 'user_{}'.format(get_random_string(10, string.ascii_letters))
email = '{}@abc.com'.format(username)
password = get_random_string(50)
User.objects.create_user(username=username, email=email, password=password)
return '{} random users created with success!'.format(total)
9. create forms.py inside that app
forms.py
from django import forms
from django.core.validators import MinValueValidator, MaxValueValidator
class GenerateRandomUserForm(forms.Form):
total = forms.IntegerField(
validators=[
MinValueValidator(50),
MaxValueValidator(500)
]
)
10. Views in the same app
views.py
from django.contrib.auth.models import User
from django.contrib import messages
from django.views.generic.edit import FormView
from django.shortcuts import redirect
from .forms import GenerateRandomUserForm
from .tasks import create_random_user_accounts
class GenerateRandomUserView(FormView):
template_name = 'generate_random_users.html'
form_class = GenerateRandomUserForm
def form_valid(self, form):
total = form.cleaned_data.get('total')
create_random_user_accounts.delay(total)
messages.success(self.request, 'We are generating your random users! Wait a moment and refresh this page.')
return redirect('users_list')
11. now in the template
generate_random_users.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type=submit value="Submit" />
</form>
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}
12. start the work process
celery -A projectname worker -l info
Upvotes: 3