How to send an email after User post the form? - django

i am beginner and used steps for sending email from https://docs.djangoproject.com/en/2.0/topics/email/
but i didn't accomplished to send email.
i want to send an email automatically using django email after a user submit the form . i am having a booking form and having email field in it after user post the form i want to send a email "Thankyou for your booking / your booking is placed ".
for eg
first name : Abubakar
Last name :Afzal
email : any#gmail.com
i want to take any#gmail.com and send email to it . after user post the form .
settings.py
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'my#gmail.com'
EMAIL_HOST_PASSWORD = 'mypassword'
EMAIL_USE_TLS = True
View.py
class BookingView(FormView):
template_name = 'buggy_app/booking.html'
form_class = BookingForm
models = Booking
def form_valid(self, form):
car_id = self.request.GET.get('car', '')
car = Car.objects.get(id=car_id)
car.is_available_car = False
car.save()
form.save()
return super(BookingView, self).form_valid(form)
success_url = reverse_lazy('index')
Forms.py
class BookingForm(ModelForm):
class Meta:
model = Booking
widgets = {
times_pick': TimePickerInput(), }
fields = ('first_name','last_name','email','book_car','contact_number','times_pick',)

You can define a function called send_emails (or any name). and call taht function from within form_valid method. It will look something like this
def form_valid(self, form):
car_id = self.request.GET.get('car', '')
car = Car.objects.get(id=car_id)
car.is_available_car = False
car.save()
form.save()
form.cleaned_data.get('username')
first_name = form.cleaned_data.get('first_name')
last_name = form.cleaned_data.get('last_name')
to_email = form.cleaned_data.get('email')
#your function here
send_emails(first_name, last_name, to_email)
and then define function something like this.
def send_emails(first_name, last_name, to_email):
#get template
htmly = get_template('email_templates/welcome.html')
#create a context
d = {'first_name':first_name, 'last_name':last_name}
subject, from_email, to = 'Subject line', settings.EMAIL_HOST_USER, to_email
#pass the context to html template
html_content = htmly.render(d)
msg = EmailMultiAlternatives(subject, html_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()

class BookingView(FormView):
template_name = 'buggy_app/booking.html'
form_class = BookingForm
models = Booking
def form_valid(self, form):
car_id = self.request.GET.get('car', '')
car = Car.objects.get(id=car_id)
car.is_available_car = False
car.save()
form.save()
subject = 'Thankyou for your booking / your booking is placed'
message = 'Thankyou for your booking / your booking is placed'
email_from = settings.EMAIL_HOST_USER
recipient_list = [any#gmail.com]
send_mail( subject, message, email_from, recipient_list )
return super(BookingView, self).form_valid(form)
success_url = reverse_lazy('index')

Related

Django - MultiValueKeyError in form when running test

I have a CustomUser model, using django's auth for authentication, and a custom signup view. In the signup form I have some validation to check that the email_suffix (domain of the email) matches with the district that they select in the form. I also check that the email is unique.
When running a test on this, I get an error on the form:
raise MultiValueDictKeyError(key)
django.utils.datastructures.MultiValueDictKeyError: 'district'
Model
class CustomUser(AbstractUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
is_student = models.BooleanField('student status', default=False)
is_teacher = models.BooleanField('teacher status', default=False)
SD23 = 'SD23'
SD39 = 'SD39'
SD67 = 'SD67'
SDISTRICT = [
(SD23, 'Kelowna SD23'),
(SD39, 'Vancouver SD39'),
(SD67, 'Summerland SD67'),
]
district = models.CharField(
max_length=4, choices=SDISTRICT, blank=True, default='SD39')
paper = models.BooleanField(default=False)
def __str__(self):
return self.username
View
def signup(request):
if request.method == 'POST':
form = CustomUserCreationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
to_email = form.cleaned_data.get('email')
# make the username the same as the email
user.username = str(to_email)
user.is_teacher = True
user.is_staff = True
user.is_active = False
user.save()
group = Group.objects.get(name='teacher')
user.groups.add(group)
current_site = get_current_site(request)
print(urlsafe_base64_encode(force_bytes(user.pk)))
sendgrid_client = SendGridAPIClient(
api_key=os.environ.get('SENDGRID_API_KEY'))
from_email = From("doug#smartmark.ca")
to_email = To(to_email)
subject = "Activate your SmartMark Account"
active_link = render_to_string('account/acc_active_email_link.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
html_text = f'Hello {user}<br/><p>Please click on the link below to confirm</p>{active_link}'
html_content = HtmlContent(html_text)
mail = Mail(from_email, to_email, subject,
html_content)
response = sendgrid_client.send(message=mail)
return redirect(reverse('accounts:account_activation_sent'))
else:
form = CustomUserCreationForm()
return render(request, 'account/signup.html', {'form': form})
Form
class CustomUserCreationForm(UserCreationForm):
""" form from class based view """
paper = forms.BooleanField(
label='I agree that keeping a backup paper gradebook is best practice')
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
class Meta:
model = get_user_model()
fields = ('email', 'first_name', 'last_name', 'district', 'paper')
def signup(self, request, user):
user.district = self.cleaned_data['district']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.paper = self.cleaned_data['paper']
user.email = self.cleaned_data['email']
def check_suffix(self, e, d):
email_domain = e.split("#", 2)[1]
t_suffix = email_creation(d)[0] # method which takes the 'district' and creates an email suffix
print(email_domain)
print(t_suffix)
if email_domain == t_suffix:
return True
else:
return False
def clean_email(self):
value = self.cleaned_data["email"]
value_district = self.data["district"]
if not value:
raise forms.ValidationError('An Email address is required.')
check_users = CustomUser.objects.filter(email__iexact=value)
if check_users:
raise forms.ValidationError('This email is already in use.')
if value and not check_users:
if not self.check_suffix(value, value_district):
self.add_error(
"email", "Your email address does not match your school district.")
return value
email_creation method
def email_creation(school_district):
if school_district == "SD23":
teacher_suffix = "sd23.bc.ca"
student_suffix = "learn.sd23.bc.ca"
email_prefix = True
elif school_district == "SD39":
teacher_suffix = "vsb.bc.ca"
student_suffix = "learn.vsb.bc.ca"
email_prefix = True
elif school_district == "SD67":
teacher_suffix = "sd67.bc.ca"
student_suffix = teacher_suffix
email_prefix = True
return(teacher_suffix, student_suffix, email_prefix)
Test
def test_signup_endpoint(self):
email = "foo#vsb.bc.ca"
result = self.client.post('/accounts/signup/', {'email': email})
self.assertEqual(result.status_code, 200)
created_user = get_user_model().objects.get(email=email)
self.assertTrue(created_user.is_active ==
False, created_user.to_dict())
The check_suffix might seem a bit convoluted but the MultiValueDictKeyError is happening before this method is called. The problem seems to be the `self.data['district'], it doesn't like the choice? Do I need to set/define this choice/field in my test? I tried that by adding the following in the test, but it didn't change the error.
email = "foo#vsb.bc.ca"
district = "SD39"

Need to search user based on email and then deactivate his profile

I am trying to create a search form, Where admin can search users and then deactivate their profiles, if it is the right account.
tried function based views and then class based views. It shows the profile in function based views but doesn't update it. and in class based view it wouldn't even show the profile.
models.py
class User(AbstractBaseUser):
objects = UserManager()
email = models.EmailField(verbose_name='email address', max_length=255, unique=True,)
type = models.CharField(max_length = 50, choices = type_choices)
name = models.CharField(max_length = 100)
department = models.CharField(max_length = 100, null = True, blank = True, choices = department_choices)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a superuser
admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['type']
forms.py
class SearchForm(forms.Form):
email = forms.EmailField(required=True)
views.py
#method_decorator(login_required, name='dispatch')
class adminDeleteProfileView(LoginRequiredMixin, View):
def render(self, request):
return render(request, 'admin/view_account.html', {'form': self.form})
def form_valid(self, form):
self.form = SearchForm(request.POST)
print('im here', form.cleaned_data.get('email'))
User.objects.filter(email = form.cleaned_data.get('email')).update(active = False)
#print('Donot come here')
def get(self, request):
self.form = SearchForm()
return self.render(request)
#login_required
def admin_deactivate_profile_view(request):
error_text = ''
if request.method == 'POST':
print('here')
user_email = request.POST.get('email')
try:
print('Deactivating',user_email, 'Account.')
profile = User.objects.filter(email = user_email).first()
if request.POST.get('delete'):
User.objects.filter(email = user_email).update(active = False)
messages.success(self.request, 'Profile Updated!')
except Exception as e:
print(e)
messages.success(self.request, 'There was an error!')
return render(request, "admin/delete_profile.html", {'profile':profile})
simple query .
user=User.objects.get(email="user#email.com")
user.activate=false
user.save()

Pass Variable from View to Form Django

Basically i am sending email to user with password and username. I can get the username using self.cleaned_data.get('email'). But the problem is that i dont know how to get password from view which i am setting random password in views. So please help me to get that random password from views.py to forms.py in def send_email
Forms.py
class UserRegisterForm(forms.ModelForm):
email = forms.EmailField()
first_name = forms.CharField()
last_name = forms.CharField()
class Meta:
model = User
fields = ['first_name','last_name', 'email']
def send_email(self):
name = self.cleaned_data.get('first_name')
username = self.cleaned_data.get('email')
to_email = self.cleaned_data.get('email')
password1 = # Get Password from view
Views.py
def register(request):
if request.method == 'POST':
ur_form = UserRegisterForm(request.POST)
pr_form = UserProfileForm(request.POST, request.FILES)
user_role = 0
if ur_form.is_valid() and pr_form.is_valid():
new_user = ur_form.save(commit=False)
new_user.username = new_user.email
password = User.objects.make_random_password() # Pass This to Form send_email
new_user.set_password(password)
new_user.save()
Pass the random password to the form at the time of form initialization and handle that in your UserRegisterForm form by overriding the __init__() method
Try this
# form.py
class UserRegisterForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self._pwd = kwargs.pop('pwd', None)
super().__init__(*args, **kwargs)
email = forms.EmailField()
first_name = forms.CharField()
last_name = forms.CharField()
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
def send_email(self):
name = self.cleaned_data.get('first_name')
username = self.cleaned_data.get('email')
to_email = self.cleaned_data.get('email')
password1 = self._pwd # access your password from view
# views.py
def register(request):
if request.method == 'POST':
random_password = generate_your_random_password() # generate password here
ur_form = UserRegisterForm(request.POST, pwd=random_password)
pr_form = UserProfileForm(request.POST, request.FILES)
user_role = 0
if ur_form.is_valid() and pr_form.is_valid():
new_user = ur_form.save(commit=False)
new_user.username = new_user.email
new_user.set_password(random_password) # set the random password here
new_user.save()
# your code ....

Error : Using django email i am sending an email after sending email got an error ? smtplib.SMTPServerDisconnected:[WinError 10054]

I am beginner and use the django documentation for sending an email.
I am facing a problem when submitting the form. I got this error:
SMTPServerDisconnected at /buggy_app/booking/
and in my terminal I got:
smtplib.SMTPServerDisconnected: Connection unexpectedly closed: [WinError 10054]
Views.py
from django.template.loader import get_template
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
class BookingView(FormView):
template_name = 'buggy_app/booking.html'
form_class = BookingForm
models = Booking
def form_valid(self, form):
car_id = self.request.GET.get('car', '')
car = Car.objects.get(id=car_id)
car.is_available_car = False
car.save()
form.save()
form.cleaned_data.get('username')
first_name = form.cleaned_data.get('first_name')
last_name = form.cleaned_data.get('last_name')
to_email = form.cleaned_data.get('email')
send_emails(first_name, last_name, to_email)
return super(BookingView, self).form_valid(form)
def send_emails(first_name, last_name, to_email):
htmly = get_template('buggy_app/welcome.html')
d = {'first_name':first_name, 'last_name':last_name}
subject, from_email, to = 'Subject line', settings.EMAIL_HOST_USER, to_email
html_content = htmly.render(d)
msg = EmailMultiAlternatives(subject, html_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()

sending email using django

In my project,an email id field is available.
I am collecting the authors email id and while updating the details in database,an email should send to that particular email id,saying that book name is updated.
My views.py is
def addbook(request):
log.debug("test....")
form = BookForm
if request.POST:
form = BookForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(cd['book_name'],cd['author_name'],cd.get(''),['to#example.com'],)
form.save()
return redirect('/index/')
return render_to_response('addbook.html',{ 'form':form },context_instance=RequestContext(request))
I am using this send_mail() method to perform that but it is not working as i expected.
models.py is
class Book(models.Model):
book_id=models.AutoField(primary_key=True,unique=True)
book_name=models.CharField(max_length=30)
author_name=models.CharField(max_length=30)
publisher_name=models.CharField(max_length=40)
email = models.EmailField()
bookref = models.CharField(max_length=10)
class Meta:
db_table = u'Book'
def __unicode__(self):
return "%d %s %s %s %s" % (self.book_id,self.book_name, self.author_name,self.publisher_name,self.email,self.bookref)
forms.py
class BookForm(ModelForm):
log.debug("test....")
class Meta:
model = Book
fields=['book_id','book_name','author_name','publisher_name','email','bookref']
An mail should send to the email id mentioned in the email field.
Thanks
settings.py
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'user'
EMAIL_HOST_PASSWORD = 'password'
DEFAULT_FROM_EMAIL = 'your email'
views.py
if request.POST:
form = BookForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
email_to = cd['email']
subject = "{0} Update".format(
cd['book_name'])
message = "Author: {0}\n\n Your book name is updated".format(
cd['author_name'])
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL,[email_to,])
form.save()
return redirect('/index/')