I am trying a timesheet project. I am using Django rest-framework and using Postgres as my database. My client requested me this (If a user already existed in the database or a new user is creating their account an email should be triggered when the post option was submitted in rest API).
models.py
from django.http import HttpResponse, HttpResponseRedirect, response
from django.db import models
from django.db.models.deletion import CASCADE
from django.utils import timezone
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.conf import settings
from django.core.mail import send_mail
from django.db.models import signals
import datetime
from django.core.mail import EmailMessage
class User(models.Model):
CHOICES= (
('manager','Manager'),
('hr', 'HR'),
('hr manager','HR Manager'),
('trainee','Trainee')
)
firstname = models.CharField(max_length=210)
lastname = models.CharField(max_length=210)
dob=models.DateField(max_length=8)
email=models.EmailField(max_length=254,default=None)
password=models.CharField(max_length=100,default=None)
joiningDate=models.DateTimeField(max_length=8)
userrole=models.CharField(max_length=20,choices=CHOICES,null=True)
def __str__(self):
return self.firstname
class Project(models.Model):
name = models.CharField(max_length=20)
description=models.TextField()
type=models.TextField()
startDate = models.DateTimeField(max_length=10)
endDate=models.DateTimeField(max_length=10)
user=models.ManyToManyField(User)
def __str__(self):
return self.name
class Timesheet(models.Model):
project=models.ManyToManyField(Project)
Submitted_by=models.ForeignKey(default=None,related_name="SubmittedBy",to='User',on_delete=models.CASCADE)
status=models.CharField(max_length=200)
ApprovedBy=models.ForeignKey(default=None,related_name="ApprovedBy",to='User',on_delete=models.CASCADE)
Date=models.DateField()
Hours=models.TimeField(null=True)
def __str__(self):
return self.id
class Client(models.Model):
clientname=models.CharField(max_length=20)
comapny=models.CharField(max_length=200)
location=models.CharField(max_length=200)
email=models.EmailField(max_length=25,default=None)
def __str__(self):
return self.clientname
serializers.py
from django.db.models import fields
from rest_framework import serializers
from.models import User,Project,Timesheet,Client
class UserSerializers(serializers.ModelSerializer):
class Meta:
model= User
fields ='__all__'
password = serializers.CharField(max_length=128, write_only=True, required=True)
class ProjectSerializers(serializers.ModelSerializer):
class Meta:
model= Project
fields= '__all__'
class TimesheetSerializers(serializers.ModelSerializer):
class Meta:
model= Timesheet
fields= '__all__'
class ClientSerializers(serializers.ModelSerializer):
class Meta:
model=Client
fields= '__all__'
viewset.py
from rest_framework import viewsets
from rest_framework import permissions
from.import models
from.import serializers
class UserViewset(viewsets.ModelViewSet):
permission_classes=(permissions.IsAuthenticated,)
queryset=models.User.objects.all()
serializer_class=serializers.UserSerializers
class ProjectViewSet(viewsets.ModelViewSet):
permission_classes=(permissions.IsAuthenticated,)
queryset=models.Project.objects.all()
serializer_class=serializers.ProjectSerializers
class TimesheetViewset(viewsets.ModelViewSet):
permission_classes=(permissions.IsAuthenticated,)
queryset=models.Timesheet.objects.all()
serializer_class=serializers.TimesheetSerializers
class ClientViewSet(viewsets.ModelViewSet):
permission_classes=(permissions.IsAuthenticated,)
queryset=models.Client.objects.all()
serializer_class=serializers.ClientSerializers
router.py
from App.viewsets import ClientViewSet, UserViewset,ProjectViewSet,TimesheetViewset
from rest_framework import routers
router = routers.DefaultRouter()
router.register('User',UserViewset)
router.register('Project',ProjectViewSet)
router.register('Timesheet',TimesheetViewset)
router.register('Client',ClientViewSet)
I am new to Django.
CodePudding user response:
It's really an important question. I just did work like this a few days ago. I am adding according to my work.
in your serializers.py you can do this.
from django.core.mail import send_mail
class TimesheetSerializers(serializers.ModelSerializer):
class Meta:
model= Timesheet
fields= '__all__'
def create(self, validated_data):
timesheet = Timesheet.objects.create(**validated_data)
send_mail(
'Timesheet {} has been created'.format(timesheet.pk),
'A new timesheet has been created . DATA: {}'.format(
validated_data), #mail_body
'[email protected]', #from_email
['[email protected]'], #to_email
fail_silently=False,
)
and you need to set email sending method in settings.py
#settings.py
#for sending testing emails you can use mailtrap.io as well that is almost same as smtp server
#for smtp
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'user'
EMAIL_HOST_PASSWORD = '****'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
#for sending emails to terminal
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
You can use celery for sending emails asynchronously.
but at first, you should do this to check. Here is the official documentation for sending email. it's really great.
and as I mentioned above about mailtrap so here is the link mailtrap
And you can follow this tutorial for setup email here is the link
Still, if you have any kind of confusion let me know. Thanks a lot.
CodePudding user response:
The solutions is same as Anny as suggested here
The solutions was:
from django.core.mail import send_mail
class TimesheetSerializers(serializers.ModelSerializer):
class Meta:
model= Timesheet
fields= '__all__'
def create(self, validated_data):
timesheet = Timesheet.objects.create(**validated_data)
send_mail(
'Timesheet {} has been created'.format(timesheet.pk),
'A new timesheet has been created . DATA: {}'.format(
validated_data), #mail_body
'[email protected]', #from_email
['[email protected]'], #to_email
fail_silently=False,
)
The only issue with that solution is, it will increase the loading time. Alternately you can do is use threading and divert the email sending process to a different thread
You can do it by creating new file named utils.py
:
import threading
from django.core import mail
class EmailThread(threading.Thread):
def __init__(self, subject, plain_message, from_email, to_email, html_message):
self.subject = subject
self.plain_message = plain_message
self.from_email = from_email
self.to_email = to_email
self.html_message = html_message
super(EmailThread, self).__init__()
def run(self):
mail_send = mail.send_mail(self.subject, self.plain_message, self.from_email, [self.to_email], html_message=self.html_message)
print('mail send successfully ', mail_send)
and in your serializer.py
:
from .utlis.py import *
class UserSerializers(serializers.ModelSerializer):
def create(self, validate_data):
subject = <subject_here>
plan_message = <plain_message_in_string>
from_email = <from_mail>
to_email = <email_you_want_to_send_to>
html_message = <if you want to include any html template for mail>
EmailThread(subject, plain_message, from_email, to_email, html_message).start()
return User.objects.create(**validated_data)
class Meta:
model= User
fields ='__all__'
password = serializers.CharField(max_length=128, write_only=True, required=True)
and in your settings.py add the following:
# EMAIL CONFIGURATION
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = '<email_user_here>'
EMAIL_HOST_PASSWORD = '<password_here>'
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER