Django view not sending context data to ReactJS/Axios application - django

It appears I have come across very strange behavior. I am building a ReactJS+Django 3.0 application. Here is the problem...
I have a <form onSubmit={handleSubmit}> that wraps the form on the frontend.
const handleSubmit = (e) => {
e.preventDefault();
axios.post(paths.login, qs.stringify({
email: emailVal,
password: passwordVal
}));
}
This works perfectly fine in sending data to the Django view! But when I try to then pass context variable through the Django view, it just fails completely. Meaning,
def login(request):
data = {}
'''
Handle Logging in
'''
if request.method == 'POST':
login_form = forms.LoginForm(request.POST)
if login_form.is_valid():
user = login_form.authenticate_user()
#login(request, user)
return redirect('home')
else:
data['errorMessage'] = ''
for field, errors in login_form.errors.items():
for error in errors:
data['errorMessage'] += error
print(data)
return render(request, 'index.html', context=data)
Given this, the data dictionary will be empty at first, but even when the print(data) shows that the data dictionary is populated, the context data that is sent to the index.html file is still empty.
WHY MIGHT THIS BE? I've been stuck on this forever.
I can work around this if I just use form submission instead of axios like this: <form method='POST'> However, I need to use axios. SOS

You can also use the Django messages framework for this, which might be a better option (assuming you are re-rendering the page after POST):
from django.contrib import messages
def login(request):
data = {}
'''
Handle Logging in
'''
if request.method == 'POST':
login_form = forms.LoginForm(request.POST)
if login_form.is_valid():
user = login_form.authenticate_user()
#login(request, user)
return redirect('home')
else:
error_message = ''
for field, errors in login_form.errors.items():
for error in errors:
error_message += error
messages.add_message(request, messages.ERROR, error_message)
return render(request, 'index.html')
Then in your template (this is an example using Bootstrap, but you can modify it to fit your needs):
{% if messages %}
{% for message in messages %}
{% if message.tags == 'error' %}
<div class="alert alert-danger alert-with-icon alert-dismissible fade show" role="alert">
{% else %}
<div class="alert alert-{{ message.tags }} alert-with-icon alert-dismissible fade show" role="alert">
{% endif %}
{{ message|safe }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endfor %}
{% endif %}
If you are sending data back as an AJAX JSON response instead:
from django.http import JsonResponse
def login(request):
data = {}
'''
Handle Logging in
'''
if request.method == 'POST':
login_form = forms.LoginForm(request.POST)
if login_form.is_valid():
user = login_form.authenticate_user()
#login(request, user)
return redirect('home')
else:
error_message = ''
for field, errors in login_form.errors.items():
for error in errors:
error_message += error
data['error_message'] = error_message
return JsonResponse(data)
else:
return render(request, 'index.html')
In your Axios code:
const handleSubmit = (e) => {
e.preventDefault();
axios.post(paths.login, qs.stringify({
email: emailVal,
password: passwordVal
}).then((response) => {
//do something with JSON response
}, (error) => {
//do something with JSON response
});
});

Related

Flask-Mail not sending email

I want to receive an email when users fill out a contact form and submit it but instead of sending the email it just displays the email as part of the URL. I have tried several methods but it's not working at all and even in the code, it does not show any errors.
This is my code for the function
from app import app, mail
from flask import render_template, request
from flask_mail import Message
def send_mail(contactform):
msg = Message('Porfolio Contact Applicant',
recipients=['rynato#kellychibale-researchgroup-uct.com'],
sender='Portfolio-Maxwell#portfoliomaxwell.co.ke')
msg.body = '''
Hello there,
You have just received contact details form from your portfolio
Name: {}
Email: {}
Message: {}
'''.format(contactform['name'], contactform['email'], contactform['message'] )
mail.send(msg)
#app.route('/')
def index():
if request.method == 'POST':
contactform = request.form
contactform = {}
contactform['name'] = request.form['name']
contactform['email ']= request.form['email'].repalces(' ','').lower()
contactform['message ']= request.form['message']
send_mail(contactform)
return render_template('index.html', **locals())
else:
return render_template('index.html', **locals())
#app.route('/privacy')
def privacy():
return render_template('privacy.html')
so does anyone have a clue as what do or go about it?
The answer(s) might depend on the type of email you want to sent, and how you have to connect to your preferred service provider.
Here's one example.
In Forms.py
class SendEmailForm(FlaskForm):
confirmed = BooleanField('confirmed')
to = StringField("to", validators=[DataRequired("Please enter the email address you want to send to")])
subject = StringField("subject", [validators.DataRequired(), validators.Length(min=1, max=80)])
message_text = TextAreaField('message_text', [validators.DataRequired()] , render_kw={"rows": 10, "cols": 60} )
submit = SubmitField("submit")
In Models.py
import smtplib, ssl
from email.message import EmailMessage
def SendEmailMessage(to, subject, messagetext, messagehtml, cc):
context = ssl.create_default_context()
msg = EmailMessage()
sender = app.config['MAIL_ADMIN_NAME']
msg['From'] = sender
msg['To'] = to
msg['Subject'] = subject
msg.set_content(messagetext)
# Try to log in to server and send email
try:
server = smtplib.SMTP(app.config['MAIL_SERVER'],app.config['MAIL_PORT'])
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
server.login(app.config['MAIL_ADMIN_NAME'], app.config['MAIL_ADMIN_PSSWRD'])
server.send_message(msg)
except Exception as e:
# Print any error messages to stdout
print(e)
finally:
server.quit()
In Views:
#app.route('/send_email', methods=['GET', 'POST'])
def send_email():
form = SendEmailForm()
sender = app.config['MAIL_ADMIN_NAME']
if form.validate_on_submit():
flash('email requested to {}, confirmed={}'.format(
form.to.data, form.confirmed.data))
to = form.to.data
subject = form.subject.data
message_text = form.message_text.data
confirmed = form.confirmed.data
if confirmed == True:
cc = ""
SendEmailMessage(to, subject, message_text, message_text, cc)
flash('Please check your email inbox.')
else:
print("Not validated")
return render_template("send_email.html",
title='Send an email',
sender=sender,
form=form,
footer_text=footer_text)
In send_email.html
<p>
Hello "{{ sender }}".
</p>
<div>
<form action="" method="post">
{{ form.hidden_tag() }}
<p>
Please tick the checkbox if you would to send your email.
</p>
<p>Confirmed :
<input type="checkbox" name="confirmed"/>
</p>
<p>
Send to: <br>
{{ form.to }}<br>
{% for error in form.to.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>Subject of email: <br>
<input type="textbox" name="subject"/><br>
{% for error in form.subject.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>Email message<br>
<textarea cols="70" id="message_text" name="message_text" required rows="10" size="2400"></textarea><br>
{% for error in form.message_text.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
<input type="submit" value="Continue">
</p>
</form>
</div>

Rendering not working even through command is visible in CMD log

I am new to django, trying to use AJAX to move data from html to views.py via AJAX, something weird is happening, data is moving but the page is not changing, new page is not getting rendered.
HTML CODE
<div class="bodyclass">
{% csrf_token %}
{% for account in accounts %}
<div class="">
<div class="accountname">
<button onclick="submitform('{{ account}}')" class="btn btn-info accbtn " id="{{ account }}">{{account}}</button>
</div>
</div>
{% endfor %}
</div
JS Code
<script>
function submitform(accname){
alert(accname);
var csrf = document.getElementsByName('csrfmiddlewaretoken');
$.ajax({
type : 'POST',
url : 'accounts',
data:{
csrfmiddlewaretoken : csrf[0].value,
'accname': accname,
},
});
alert('bye');
}
</script>
views.py
def accounts(request):
if request.user.is_authenticated:
if request.method == 'GET':
if request.user.is_superuser:
account = AccountDescription.objects.all()
else:
account = UserAccount.objects.filter(user=request.user)
return render(request, 'accounts.html',{'accounts':account})
elif request.method == "POST":
print(request.POST)
print(request.POST.get('accname'))
return HttpResponseRedirect('/clientinfo')
else:
return HttpResponseRedirect('/login')
also the cmd screenshot
Kindly let me what wrong I am doing. also let me know if any more input is required.
Thanks in advance.
Read ajax return output on JS File
JS Code
$.ajax(
{
type:"POST",
url: "/checkonline",
data:{
//Pass CSRF & Data
},
success: function(data)
{
//Read Response Here
//redirect user to here using javascript
alert(data);
}
})
views.py
//Example for Return Response in JSON Format
from django.http import JsonResponse
def accounts(request):
return JsonResponse(list({"redirect_user"}) , safe=False)

django + ajax send form

and at page i'm not see csrdI try after receiving one form to get another
views.py
def get_name(request):
if request.method == 'POST':
user_code = generate_code(8)
subject = 'ver code'
message = user_code
phone = request.POST['phone']
form = NameForm(request.POST)
if form.is_valid():
Registration.objects.create(fio=request.POST['fio'],mail=request.POST['mail'])
send_mail(subject, message,settings.EMAIL_HOST_USER,[mail],fail_silently=False)
return JsonResponse({ 'form1': render_to_string( 'registers/endreg.html', {'form': NameForm1() } ) })
else:
form = NameForm()
return render(request, 'registers/detail.html', {'form': form})
def endreg(request):
if request.method == 'POST':
form = NameForm1(request.POST)
if form.is_valid():
code_use = form.cleaned_data.get("key")
try:
user = Registration.objects.get(code=code_use)
user.verification = True
user.save()
messages.warning(request, u'thanks.')
except:
messages.warning(request, u'error.')
else:
form = NameForm1()
return render(request, 'registers/endreg.html', {'form': form})
and ajax
$(document).ready(function()
{ $("#my_form").submit(function(event)
{ event.preventDefault();
$this = $(this);
$.ajax({
type: "POST",
data: $this.serialize(),
success: function(data)
{ console.log(data);
$this.html(data.form1);
},
error: function(data)
{ console.log(data);
}
});
});
});
I am facing a CSRF token missing or incorrect problem. Because it is not transferred to form 2. how can I transfer this token to a new form
detatil.html it's html first page
{% extends 'base.html' %}
{% load i18n %}
{% block content%}
<div class="main-form">
<form action="" method="post" autocomplete="off" id="my_form">
{% csrf_token %}
<div class="contact-form" >
<h1>{%trans 'Регистрация' %}</h1>
<div class="txtb">{{form.fio.label}} {{form.fio}}{{form.fio.help_text}}</div>
<div class="txtb"> {{form.purpose.label}}{{form.purpose}}</div>
<div class="container" id="none">{{form.tso.label}}{{form.tso}}</div>
<div class="txtb">{{form.phone.label}} {{form.phone}}{{form.phone.help_text}}{{form.phone.errors}}</div>
<div class="txtb"> {{form.number_car.label}}{{form.number_car}}</div>
<div class="txtb"> {{form.date_visit.label}}{{form.date_visit}}</div>
<div class="txtb"> {{form.captcha.label}}<br>{{form.captcha}}{{form.captcha.errors}}</div>
<input type="submit" value="{%trans 'send' %}" class="btn" id="btn">
</div>
</form>
</div>
{% endblock %}
it's html secon page endreg.html
{% load i18n %}
{% block content%}
<form action="" method="post" autocomplete="off" >
{% csrf_token %}
<div class="verification" >
<div class="ver">
{{form}}
</div>
<input type="submit" value="{%trans 'send' %}" class="btn1" >
</div>
</form>
{%endblock%}
csrf token is on two pages, but when I look at the code in the browser, it does not appear when I add 2 forms using ajax
since you are using render_to_string, you need to pass request object to render_to_string. You can acheive it by:
def get_name(request):
if request.method == 'POST':
user_code = generate_code(8)
subject = 'ver code'
message = user_code
phone = request.POST['phone']
form = NameForm(request.POST)
if form.is_valid():
Registration.objects.create(fio=request.POST['fio'],mail=request.POST['mail'])
send_mail(subject, message,settings.EMAIL_HOST_USER,[mail],fail_silently=False)
return JsonResponse({ 'form1': render_to_string('registers/endreg.html', {'form': NameForm1()}, request=request) })
else:
form = NameForm()
return render(request, 'registers/detail.html', {'form': form})

How to disable button when required field is empty

Hello i need your help i need to disable this button send when the required field are empty. I am a beginner using django and i don't know how to resolve it. Please i need your help .. i lost my time trying to find a solution.
Views.py:
def contact(request):
form = FeedbackForm(request.POST or None)
if form.is_valid():
recaptcha_response = request.POST.get('g-recaptcha-response')
url = 'https://www.google.com/recaptcha/api/siteverify'
values = {
'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
'response': recaptcha_response
}
data = urllib.urlencode(values).encode()
req = urllib2.Request(url, data=data)
response = urllib2.urlopen(req)
result = json.loads(response.read().decode())
''' End reCAPTCHA validation '''
if result['success']:
form.save()
message = u'You have feedback\nName: %s\nEmail: %s\nPhone: %s\nCountry: %s\nFeedback:\n%s' % (
form.cleaned_data['name'],
form.cleaned_data['email'],
form.cleaned_data['phone'],
form.cleaned_data['country'],
form.cleaned_data['feedback'])
try:
send_mail('NEW FEEDBACK', message, '', settings.DEFAULT_FROM_EMAIL) # to admin
send_mail('THANK YOU for contacting us', 'We will be back to you promptly.', '', [form.cleaned_data['email'],]) # to user
messages.info(request, 'SUCCESS! Your message has been sent!')
form = FeedbackForm()
except:
messages.info(request, 'Sorry, can\'t send feedback right now.')
else:
messages.error(request, 'Invalid reCAPTCHA. Please try again.')
return render(request, 'contact.html', {'active_page':'contact','form': form,})
Contact.html:
<html>
<div class="col-md-6">
<form role="form" class="form" method="post">
{% csrf_token %}
{% for field in form %}
<label for="{{ field.label }}">{{ field.label_tag }}
{% if field.field.required %}<span class="red">*</span>{% endif %}</label>{{ field.errors }}{{ field }}
{% endfor %}
<p><span class="redText">*</span> Indicates a required field</p>
<script src='https://www.google.com/recaptcha/api.js'></script>
<div class="g-recaptcha" data-sitekey=""></div>
<input type="submit" value="Send" class="btn btn-lg">
</form>
The best way to do this would be to use JavaScript and jQuery.
In this example, when you click your button you can make sure the form is valid before it submits.
$(".validate").on("click", function () {
if (!valid()) {
alert("You are missing required fields.");
return false;
}
else {
return confirm("This will submit the form. Are you sure?");
}
});
function valid() {
return false;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="submit" class="validate" value="Send" class="btn btn-lg">
This code adds a class to your button. The jQuery listens for the click, then makes a JavaScript function that would check if it is valid. If it is not, it displays an alert. If it is, it displays a confirm message.
There are many other ways to do this with JS though.

request not going through

im creating a login page the code im posting doesnt give any errors if request.method == 'POST' and formLogin.validate():
if formLogin.username_signin == 'admin' and formLogin.password_signin == 'admin':
return redirect(url_for('home'))
this piece of code gets skipped even when i put admin in box boxes(wtforms) here is the code im using:
app = Flask(__name__)
app.secret_key = 'jjjjjjj'
#app.route('/')
def home():
return render_template('home.html')
#app.route('/login/', methods=['GET', 'POST'])
def login():
formLogin = LoginForm(request.form)
error = None
if request.method == 'POST' and formLogin.validate():
if formLogin.username_signin == 'admin' and formLogin.password_signin == 'admin':
return redirect(url_for('home'))
else:
error = 'Please enter right credentials.'
return render_template('login.html', error=error, formLogin=formLogin)
return render_template('login.html', error=error, formLogin=formLogin)
if __name__ == '__main__':
app.debug = True
app.run()
my login.html:
{% extends 'base.html' %}
{% block head %}
<div class='container'>
<div class='row'>
<form method= post action='/login/'>
{{ formLogin.username_signin(class='form-control', placeholder='Username') }}
{{ formLogin.password_signin(class='form-control', placeholder='Password') }}
{{ formLogin.submit_signin(class='btn btn-primary') }}
</form>
<p><strong>Error:</strong>{{ error }}</p>
</div>
</div>
{% endblock %}
Form.py
from wtforms import Form,StringField, PasswordField, TextField, BooleanField, SubmitField, validators
class LoginForm(Form):
username_signin = StringField('SigninU', [validators.Required('please enter name')])
password_signin = PasswordField('signinP', [validators.Required('need password')])
submit_signin = SubmitField('Signin')
Like i said everything renders ok and im not getting a error loading my problem is that when i put 'admin' in both boxes instead of redirect me to the home() function it just skips straight to the else statement.
You have to use .data to access the get_data.
if request.method == 'POST' and formLogin.validate():
if formLogin.username_signin.data == 'admin' and formLogin.password_signin.data == 'admin':
return redirect(url_for('home'))