Django HTML Email Message Automatically pick receiver's email from form - django

Please can anyone help me with this issue. I am trying to allow the users of my website to send out review request to customers by filling out a form on their profile page. They only have to provide the email address of the recipient then the backend would use this to configure a HTML message then send to the recipient. Currently, the whole system works just fine if I hard code the recipient email address. But once I try to get the email from request.POST['receiver'] it seems not to be passing the argument to the function.
Here is the view function:
def request_review_api(request):
receiver_email = request.POST['receiver']
print(receiver_email)
request_review(request, receiver_email)
return redirect('profile_company')
#login_required(login_url='loginpage_company')
#allowed_users_company(allowed_roles=['company'])
def request_review(request, receiver_email):
company = get_object_or_404(Company, user=request.user)
company_id = company.pk
print(company)
html_tpl_path = 'companyusers/request_review.html'
context_data = {'company': company, 'company_id': company_id,}
email_html_template = get_template(html_tpl_path).render(context_data)
receiver = receiver_email
email_msg = EmailMessage('Review Request',
email_html_template,
settings.EMAIL_HOST_USER,
[receiver],
reply_to=['no-reply#bbb.com'],
)
# this part allows the message to be send as html instead of plain text
email_msg.content_subtype = 'html'
email_msg.send(fail_silently=False)
This is what I have in my Template:
<p class="tm-request-review-display card-text">
<form class="tm-request-review-display" action="{%url
'request_review' %}" method="POST"> {% csrf_token %}
<div class="form-group">
<div class="col-md">
<input type="email" class="form-control" name="receiver"
id="receiver" placeholder="Enter Reviewer's Email">
</div>
</div>
<div class="form-group">
<div class="col-md">
<input class="btn btn-primary btn-sm" type="submit"
value="Send Request">
</div>
</div>
</form>
</p>
The email gets sent successfully once I hard code the recipient email like this:
def request_review_api(request):
request_review(request)
return redirect('profile_company')
#login_required(login_url='loginpage_company')
#allowed_users_company(allowed_roles=['company'])
def request_review(request):
company = get_object_or_404(Company, user=request.user)
company_id = company.pk
print(company)
html_tpl_path = 'companyusers/request_review.html'
context_data = {'company': company, 'company_id': company_id,}
email_html_template = get_template(html_tpl_path).render(context_data)
receiver_email = 'sndnd#yahoo.com'
email_msg = EmailMessage(' Review Request',
email_html_template,
settings.EMAIL_HOST_USER,
[receiver_email],
reply_to=['no-reply#yahoo.ng'],
)
# this part allows the message to be send as html instead of plain text
email_msg.content_subtype = 'html'
email_msg.send(fail_silently=False)

The code is perfect. The mistake was that the email request.post was getting was an invalid email.
Thanks guys for helping. It works perfectly now.

Related

Getting a django.utils.datastructures.MultiValueDictKeyError using ajax

I am trying to use the ajax post function to post data from my contact form in one of my templates. However, I am getting a 'django.utils.datastructures.MultiValueDictKeyError' when I make the request.
The error is a server error and it is displayed as shown
django.utils.datastructures.MultiValueDictKeyError: 'name'
It is being triggered in the view.py folder on the line with the code
name = request.POST['name']
Here is my model for the message:
class Message(models.Model):
name = models.CharField(max_length=255)
email = models.CharField(max_length=255)
content = models.TextField(max_length=10000)
created_at = models.DateTimeField(auto_now_add=True)
This is my view.py:
def save_message(request):
if request.method=='POST':
name = request.POST['name']
email = request.POST['email']
content = request.POST['content']
Message.objects.create(
content = content,
name = name,
email = email
)
messages.success(request, f'Your message has been sent. Expect a response soon!')
return JsonResponse({'bool':True})
This is the form in the index template
{% csrf_token %}
<form class="contactForm" id="contactForm">
<div class="form-floating">
<input class="form-control" class="message-name" id="name" type="text" placeholder="Enter your name..." />
</div>
<div class="form-floating">
<input class="form-control" class="message-email" id="email" type="email" placeholder="Enter your email..." />
</div>
<div class="form-floating">
<textarea class="form-control" id="message" class="message-text" placeholder="Enter your message here..."></textarea>
</div>
<br />
<button class="btn btn-primary text-uppercase save-message" id="submitButton" type="submit">Send</button>
</form>
And this is my ajax:
{% block script %}
<script>
$(document).ready(function(){
// This is for the post messages for non-logged in users
$(".save-message").on('click',function(){
var _content=$(".message-text").val();
var _messageName=$(".message-name").val();
var _messageEmail=$(".message-email").val();
// Ajax
$.ajax({
url:"/save-message",
type:"POST",
data:{
content:_content,
name:_messageName,
email:_messageEmail,
csrfmiddlewaretoken:"{{csrf_token}}"
},
dataType:'json',
beforeSend:function(){
$(".save-message").addClass('disabled').text('Saving...');
},
success:function(res){
if(res.bool==true){
$(".message-text").val('');
}
$(".save-message").removeClass('disabled').text('submit');
}
});
});
});
</script>
{% endblock %}
Using request.POST[] is for data sent with regular HTML forms, but not when sending data using AJAX (even if it is sent via POST). To access that you need the raw, request.body, and to parse that you need json, which also means you need to import json:
import json
def save_message(request):
if request.method=='POST':
data = json.loads(request.body)
name = data['name']
email = data['email']
content = data['content']
Message.objects.create(
content = content,
name = name,
email = email
)
messages.success(request, f'Your message has been sent. Expect a response soon!')
return JsonResponse({'bool':True})
The error would have occurred with email = request.POST['email'] or content = request.POST['content'] because request.POST is empty, so the keys, name, email, content, or any other key would have raised the MultiValueDictKeyError:.
Source: Django Docs:
HttpRequest.body
The raw HTTP request body as a bytestring. This is
useful for processing data in different ways than conventional HTML
forms: binary images, XML payload etc. For processing conventional
form data, use HttpRequest.POST.

I am trying to get POST request but django response with GET request

I am trying to get the post request and i have tried everything it is still getting me get requests.
Please Help.
I have tried using that i saw in other problems displayed here. but it is not working for me.
{% csrf_token%}
Item name
{{form.item_name}}
Quantity
{{form.quantity}}
<div class="form-group">
<label for="address">Address</label>
{{form.address}}
</div>
<div class="modal-footer d-flex justify-content-center">
<button type="submit" id="submit" class="btn btn-success" data-dismiss="modal" >Donate</button>
</div>
</form>
This is my view file
#this is my view
#login_required(login_url='loginPage')
def home(request):
form = DonateForm()
print(request.user.id)
get_user = user_info.objects.get(id=request.user.id)
print('Inside Home View')
print(get_user)
print(request)
if request.method == 'POST':
form = DonateForm(request.POST)
print('Inside Home Page')
if form.is_valid():
print('Form is valid!!')
user = form.save()
Donate.objects.create(user_name = user,item_name=form.cleaned_data['item'],quantity=form.cleaned_data['itemquantity'])
else:
messages.add_message(request,messages.INFO,'Your details are Incorrect!!')
else:
print('No Post Request!!')
return render(request,'donate/home.html',{'form':form,'get_user':get_user})
Here is my Models.py
class Donate(models.Model):
user_name = models.ForeignKey(user_info,on_delete=models.CASCADE)
item_name = models.CharField(max_length=30,null=False , blank=False, default ="None")
quantity = models.IntegerField(null=False,blank=False,default=0)
address = models.CharField(max_length=100 , null=False , blank= False, default="None")
def __str__(self):
return f"{self.user_name.user.username} donated {self.item_name}"
Please try to add the method in the <form>, like this:
<form method="post" action="#">
{% csrf_token %}
......
<button type="submit" id="submit" class="btn btn-success" data-dismiss="modal" >Donate</button>
</form>

Python/Django - radiobutton with submit button instead of buttons

I have a Django application where I want to have a setting: if the email is sent automatically or manually. What I have works, but not in the style that I want it.
At the moment I have 2 buttons where you can click them and the setting is set to what you want. But what I would want is radio buttons, that are also already checked or unchecked, depending on the setting.
What I have now is:
model.py
class AutoSendMail(models.Model):
auto = models.BooleanField(default=False)
manual = models.BooleanField(default=True)
send_type = (
('manual', 'MANUAL'),
('auto', 'AUTO')
)
type = models.CharField(max_length=6, choices=send_type, default="manual")
forms.py
CHOICES = [('manual', 'MANUAL'),
('auto', 'AUTO')]
class SendMailSetting(ModelForm):
class Meta:
model = AutoSendMail
fields = ['auto', 'manual', 'type']
widgets = {
"manual": forms.RadioSelect(attrs={'class': 'form-control'}),
"auto": forms.RadioSelect(attrs={'class': 'form-control'}),
'type': forms.ChoiceField(choices=CHOICES, widget=forms.RadioSelect)
}
views.py
class AutoSendView(generic.TemplateView):
template_name = 'core/mailbox/autoSendMail.html'
context_object_name = 'autosend'
extra_context = {"mailbox_page": "active"}
form_class = SendMailSetting
def post(self, request, *args, **kwargs):
if request.POST.get('manual'):
logger.info("Set to: manual email send")
AutoSendMail.objects.filter(pk=1).update(auto=True,
manual=False,
type="manual")
elif request.POST.get('auto'):
logger.info("Set to auto email send")
AutoSendMail.objects.filter(pk=1).update(auto=True,
manual=False,
type="auto")
return HttpResponseRedirect(self.request.path_info)
autoSendMail.html
<form class="card" action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="card-body">
<h3 class="card-title">Update Mail Settings</h3>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="form-label">Send E-mail</label>
<button type="radio" name="manual" value="manual" class="btn btn-primary">Manual</button>
<button type="radio" name="auto" value="auto" class="btn btn-primary">Automated</button>
</div>
</div>
</div>
</div>
</form>
Currently it looks like this:
And I would like it to look more like this:
At the moment I'm only using a POST request, and I guess, to inform the user I also need to use a GET request, but I can't get it to work. Also I'm now not using the form, I tried to use it in different ways but I can't get the result I want..
Can someone help me?
You had created a modelForm but you are not using it here. Anyway for basic method you can try below method
<input type="radio" name="update_type" value="manual">Manual</input>
<input type="radio" name="update_type" value="auto">Automated</input>
<button type="submit" class="btn btn-primary">Submit</button>
views.py
def post(self, request, *args, **kwargs):
update_type = request.POST.get('update_type'):
if update_type == 'manual':
"update db with manual to true"
else:
"update the db with auto to true"

Create a basic contact form that send a mail

I have a template for a form already designed (using bootstrap-studio).
I just need to get the data from it and send it as a mail to my email id.
It would also be great if the page could get redirected to a new one after pressing submit.
I have already set up the settings.py and am able to send the 'message' part of the form.
if request.method == 'POST':
message = request.POST['message']
send_mail(
'Contact Form',
message,
settings.EMAIL_HOST_USER,
['abcd#gmail.com'],
fail_silently=False
)
return render(request, 'contact.html')
What I need is to be able to send an email with 'message', 'name', 'email',
included in it.
I tried writing
message = request.POST['message','name','email']
Didn't get expected results.
contact.html:
<form method="post">
{% csrf_token %}
<h2 class="text-center">Contact us</h2>
<div class="form-group"><input class="form-control" type="text" name="name" placeholder="Name"></div>
<div class="form-group"><input class="form-control " type="email" name="email" placeholder="Email"></div>
<div class="form-group"><textarea class="form-control" name="message" placeholder="Message" rows="14"></textarea></div>
<div class="form-group"><button class="btn btn-primary" type="submit">send </button></div>
</form>
</div>
To fetch data from form you have to do it invidually.
message = request.POST["message"]
name = request.POST["name"]
email = request.POST["email"]
Then you can use this data to pass into send_mail() function as arguments.
To redirect to another page after submitting the form, use this logic:
from django.shortcuts import redirect
if request.method == 'POST':
message = request.POST['message']
name = request.POST["name"]
email = request.POST["email"]
send_mail(
'Contact Form',
message,
settings.EMAIL_HOST_USER,
[email,],
fail_silently=False
)
return redirect("/home/")
return render(request, 'contact.html')

how to integrate API with HTML in django template?

I am using both POST and GET method through python requests to fetch datas and submit data in an API.
class ApiLoginView(TemplateView):
template_name = 'index.html'
def post(self,request):
email = request.POST.get('email')
print(email)
password = request.POST.get('password')
print(password)
API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxx'
API_URL = 'http://dev.com/rest/storeLogin'
parameter = {
'authToken':API_KEY,
'email':email,
'password':password,
}
r = session.post(url = API_URL, params=parameter)
print(r.json()['code'])
return render(request,'index.html')
With this above views.py class method i'm trying to post data.and I have an readymade HTML form for login ready.
<form class="my-login-form" action="/login" method="post">
{% csrf_token %}
<div class="field-wrap">
<input type="email" name="email" required autocomplete="off" placeholder="Email Id"/>
</div>
<div class="field-wrap">
<input type="password" name="password" required autocomplete="off" placeholder="Password">
</div>
<button class="button button-block"/>Login</button>
<div class="forgot"><a class="user-form-toggle" href="#forgot">Forgot Password?</a></div>
</form>
So my dilemma is how to map both class based view and html form. Right now it seems html form is stand alone!
You should check djangorestframework. It's a good framework for defining REST APIs with multiple formats, filters, etc, by doing mostly configuration instead of code.