Handling SMS messages when processing forms - django

I have a few views which handle the forms for new objects being created which seem to lag the user experience due to having to connect to the Twilio API. For example, the following form_valid method sends an SMS message to all receivers of a memo:
def form_valid(self, form):
form.instance.sender = self.request.user
form.save()
receiving_groups = form.cleaned_data['receiver']
for group in receiving_groups:
username = list(
employees.models.Employee.objects.filter(
employee_type=group))
for user in username:
form.instance.unread.add(user)
memo_url = form.instance.pk
user.send_sms('memo', memo_url)
user.send_email('memo', memo_url)
form.save()
return super(MemoCreateView, self).form_valid(form)
The issue here is that the send_sms method has to wait for a response before continuing. This really makes the site seem slow to the user.
I have started to create a request_finished signal but I would have to pass a lot of parameters to the signal so this seems like a bad option.
What other options do I have for sending the SMS messages post-success/redirect of the object being created?

Related

Handling user registrations Using only Django without the need to be redirected to other template

This is my view
class UserRegistrationView(FormView):
template_name = "register/register_form.html"
form_class = None
extra_fields_form_page_slug = ""
email_template = "register/account_activation_email.html"
def get_form(self, form_class=None):
form = super().get_form(form_class)
add_extra_fields(
form.fields, form.helper.layout.fields, self.extra_fields_form_page_slug
)
return form
def get_extra_form(self):
return FormPage.objects.filter(slug=self.extra_fields_form_page_slug).first()
def form_valid(self, form):
user = form.save(commit=False)
user.is_active = False
user.save()
email = form.cleaned_data.get("email")
email_template = "register/account_activation_email.html"
send_confirmation_email(
self, "Activate Your Account", user, email, email_template
)
return render(self.request, "register/after_submission.html")
This is working fine (registration wise) but it's not from many other sides, because I have the registration form as a pop up window in the header, so it's available throughout the whole website, my problems are:
if the user had a successful registration they will be redirected to the specified template "after_submission" what I want is to stay on the same page and display a pop up with some message
if the user had an unsuccessful registration they will be redirected to the main template "register_form.html" with the errors displayed their, what I want is to stay on the same page and to display the error messages on the pop up form if the user opened it again
is this achievable using only Django?? or I must throw some JS in there, and if JS is the answer, can you give me a quick insight into how to do it?
You can redirect to the same page in your CBV :
from django.http import HttpResponseRedirect
return HttpResponseRedirect(self.request.path_info)
As stated in the comment your solution require Ajax and JS, you can however redirect to the same page but that will make a new request and refresh the whole page which might no be ideal for you.
There is a tutorial to work with Django and Ajax Ajax / Django Tutorial

How can i create a registration form in django which sent mail also

I'm creating a registration form in Django which has first_name, last_name, email, password fields. After the registration, all the details are stored in a Database. Meantime I receive an email with all the details. I didn't understand how to execute this .
Hey you can send the mail after form.save() method.
def post(self, request, *args, **kwargs):
"""
performing post request and marking the user object as active and
sending the registration email to the user email account
"""
form = self.form(data=request.data)
if form.is_valid(raise_exception=True):
user = form.save()
## you can define your method to send the mail call after save
account_utils.send_user_registration_email(user)
return

Calling a method when the user login Django

On my Django site, I want to create an object when the user login the site. I searched it on the internet and I decided to write a method in a context_processors.py. so I wrote;
def check_online_status(request):
user_status = None
if request.user.is_authenticated():
user_status = UserStatus.objects.create(user_id=request.user.id)
user_status.status_type = "online"
user_status.save()
return {
'user_status': user_status,
}
Here it is the problem; my check_online_status() method is triggered in every request but I want to trigger my method at once, only when the user login.
Can you help me to do it?
I think what you're looking for is a signal, specifically an auth signal. These are already provided in django.
https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.signals
from django.contrib.auth.signals import user_logged_in
def set_status_online(sender, user, request, **kwargs):
user_status = UserStatus.objects.create(user_id=request.user.id)
user_status.status_type = "online"
user_status.save()
user_logged_in.connect(set_status_online)

Django signals in login

What is django signal in login function used for? The user is already added in the request session table. So what is the last line call to signal does in Django auth.login function?
#sensitive_post_parameters()
#csrf_protect
#never_cache
def login(request, user):
"""
Persist a user id and a backend in the request. This way a user doesn't
have to reauthenticate on every request. Note that data set during
the anonymous session is retained when the user logs in.
"""
session_auth_hash = ''
if user is None:
user = request.user
if hasattr(user, 'get_session_auth_hash'):
session_auth_hash = user.get_session_auth_hash()
if SESSION_KEY in request.session:
if _get_user_session_key(request) != user.pk or (
session_auth_hash and
request.session.get(HASH_SESSION_KEY) != session_auth_hash):
# To avoid reusing another user's session, create a new, empty
# session if the existing session corresponds to a different
# authenticated user.
request.session.flush()
else:
request.session.cycle_key()
request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
request.session[BACKEND_SESSION_KEY] = user.backend
request.session[HASH_SESSION_KEY] = session_auth_hash
if hasattr(request, 'user'):
request.user = user
rotate_token(request)
user_logged_in.send(sender=user.__class__, request=request, user=user)
The user_logged_in signal sent at the end of login() has been defined so that it can be used for notification when a user logs in. It also updates the last_login attribute for the currently logged-in user(as #ozgur mentioned above).
From Login and Logout Signals documentation:
The auth framework uses two signals (user_logged_in and
user_logged_out) that can be used for notification when a user logs
in or out.
The arguments sent with this signal are:
sender : The class of the user that just logged in.
request : The current HttpRequest instance.
user : The user instance that just logged in.
Using this helps in allowing decoupled applications to get notified when a user has logged in.
Lets say you want to be notified whenever a user logs in and do some actions, then you can use this signal so that your receiver gets notified on a user login. To receive a signal, you need to register a receiver function that gets called when the signal is sent by using the Signal.connect() method.
For example:
perform_some_action_on_login is a receiver function which will perform some extra actions whenever a user logs in.
from django.contrib.auth.signals import user_logged_in
def perform_some_action_on_login(sender, user, **kwargs):
"""
A signal receiver which performs some actions for
the user logging in.
"""
...
# your code here
After defining the register function, connect this receiver function with user_logged_in signal
user_logged_in.connect(perform_some_action_on_login)
Now whenever a user logs in, a user_logged_in signal is sent which is received by the receiver function perform_some_actions_on_login. It then performs those extra actions.
try to put the following code in the _ _init__.py of your app
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
#receiver(user_logged_in)
def on_login(sender, user, request, **kwargs):
print('User just logged in....')

Django - many to many with post_save gridlock

I want to send out an email when a model instance is saved. To do this I listen out for the post_save signal:
#models.py
#receiver(post_save, sender=MyModel, dispatch_uid="something")
def send_email(sender, **kwargs):
instance = kwargs['instance']
email = ModelsEmailMessage(instance)
email.send()
In my view I process the form and append subscribers to the object:
#views.py
object = form.save()
object.subscribers.add(*users)
My problem is that the form save triggers the post_save signal before the users have been added.
But if I do this:
object = form.save(commit=False)
then I can't add m2m instances to an object that has no id.
Heyulp!
Most likely you will have to write your own signal to send email.
Event though you are implemented that tries to send email when object is saved, but that is not what you want. You want to send email when object is saved and has some subscribers added after processing some view. i.e. its 2 step operation.