I am making a website where a user registers to book an instructor for a certain period of time according to a plan he chooses. There are three plans from which a user can choose namely 7days, 14days and 21days. After registering, the user needs to accept an agreement and then based on the plan he has chooses an expiration date is set from the day the user has accepted the agreement.
Now after the user, has accepted the agreement, a copy of the agreement is sent to the user as well as the owners of the website through email. The owners want this system, where the copy of agreement is recieved by both the user and them. I am able to make this happen, and the site is working fine in the testing phase. So basically, two emails are sent after the user accepts and a Contract model is updated.
Now, I have noticed that sending two emails takes a good of time, and the page keeps on loading until both the emails are sent, and then the redirects and all happens for the user. This waiting time may trigger some users to press back interrupting the smtp connection, and then trying to accept the agreement again will raise an intigrity error and also provide a poor user experience. The below code is how making this happen.
views.py (posting only a part where the plan is 7days)
if request.method == 'POST':
agreement = Contract()
if request.user.plan == '7days':
agreement.user = request.user
agreement.contract_status = True
expiry = datetime.now() timedelta(days=7)
agreement.date_of_acceptance = datetime.now()
agreement.date_of_expiration = expiry
agreement.save()
# for the customers
template = render_to_string('contract_email.html', {'name': request.user.full_name, 'email': request.user.email, 'plan': request.user.plan,'price': 2000, 'accept': agreement.date_of_acceptance, 'expire':agreement.date_of_expiration})
email = EmailMessage(
'Copy of Contract', #subject
template, # body
settings.EMAIL_HOST_USER,
[request.user.email], # sender email
)
email.fail_silently = False
email.content_subtype = 'html' # WITHOUT THIS THE HTML WILL GET RENDERED AS PLAIN TEXT
email.send()
#for the owners
template = render_to_string('contract_email.html', {'name': request.user.full_name, 'email': request.user.email, 'plan': request.user.plan,'price': 2000, 'accept': agreement.date_of_acceptance, 'expire':agreement.date_of_expiration})
email = EmailMessage(
'Copy of Customer Contract', #subject
template, # body
settings.EMAIL_HOST_USER,
['[email protected]'], # sender email
)
email.fail_silently = False
email.content_subtype = 'html' # WITHOUT THIS THE HTML WILL GET RENDERED AS PLAIN TEXT
email.send()
return redirect('user')
The values generated above are all stored in the model and then sent through the email which is neccesary.
Since, I am begginer I want to know if there is a more efficient and faster way of doing this entire task, so that the user does not have to wait for that long for his redirections and the emails are also sent from the backend.
CodePudding user response:
There is not much you can do with synchronous code, what you need to do is setting up an asynchronous view Async with Django and create worker for your email.
The idea is to have all the tasks that could potentially slow down your server wrap in a asynchronous task, this is use in a lot of case and specifically yours where contracts and emails need to be sent but it should not block the connection or code from executing.