Django send an email on post_save with templates - html

I'm attempting to send an email our admin when new data is submitted to our website from the users. We are using a Django for the backend and Vue for the front end, even though that probably doesn't matter. Here is the code:
#receiver(post_save)
def send_update(sender, created, **kwargs):
if created:
data=kwargs['instance']
try:
if data.admin_approved == False:
print("point 1 reached")
name = data.submitted_by_name
body = data.body
content_type = str(sender).split(".")[2][:-2]
print("point 2 reached")
link = "https://link_to_website.com" + content_type.lower()
subject = "New " + content_type + " submitted"
print("point 3 reached")
from_email = "NoReply#web_site.com"
to_email = "my_email#address.com"
print("pre-html point reached")
html_message = get_template('./email/template.html')
text_message = get_template('./email/textplate.txt')
data = {
'user_name': name,
'submission': data.body,
'type': content_type,
'link': link,
'body': body
}
content_text = text_message.render(data)
content_html = html_message.render(data)
print("ready to send email!")
msg = EmailMultiAlternatives(subject, content_text, from_email, [to_email])
msg.attach_alternative(content_html, "text/html")
msg.send()
except:
print("Data was not submitted by an non-admin user.")
The try/except is included so that data that is submitted directly through the django admin page does not trigger the email function.
the function works up until "pre-html point reached", I'm guessing the issue is somewhere within the msg and msg.send() but I am not receiving any error functions.
Thanks for the help!

Related

django admin send email to user

\admin.py
#admin.register(ParentsProfile)
class ParentsProfile(admin.ModelAdmin):
list_display = ('Father_Email','Fathers_Firstname' , 'Fathers_Middle_Initial', 'Fathers_Lastname', 'Request')
ordering = ('Request',)
search_fields = ('Request',)
actions = ['Send_Email','Send_Email_Disapproved']
def Send_Email(self, request, queryset):
html_content = "Your Registration has been approved.\n\nPlease use this %s as your username and %s as your password. \nYou may now start enrolling your student using this link https://...../Plogin_form/ \n\n\n REGISTRAR "
for profile in queryset:
send_mail(subject="Invite", message=html_content %(profile.Father_Email,profile.Parent_Password), from_email=settings.EMAIL_HOST_USER,
recipient_list=[profile.Father_Email]) # use your email function here
def Send_Email_Disapproved(self, request, queryset):
# the below can be modified according to your application.
# queryset will hold the instances of your model
for profile in queryset:
send_mail(subject="Invite", message="Our Apology,\n\n Your Registration has been Disapproved " + profile.Father_Email + "\n\n\n REGISTRAR" + "", from_email=settings.EMAIL_HOST_USER,
recipient_list=[profile.Father_Email])
i have this code to send an email to user, how do i convert my html_content into HTML? so that i can design my message to user?
it send to user gmail like this,
You can render it with django.template.loader.render_to_string
You first need to store your template in your template folder, for example:
<!-- your_app/templates/my_template.html -->
<h1>hello, {{ user.first_name }}</h1>
Then in your code, change the html_content to
html_content = render_to_string('my_template.html', {
'user': User.objects.get(username="some_username")
})
Doc: https://docs.djangoproject.com/en/2.2/topics/templates/#django.template.loader.render_to_string

Flask Oauth2 get Google+ profile-picture-url from the profile-picture-json

I have a problem here in obtaining the Google+ profile-picture-url from the profile-picture-json. I'm quite a beginner and this is my first webapp so please take this into account.
My callback function:
def callback(self):
self.validate_oauth2callback()
oauth_session = self.service.get_auth_session(
data={'code': request.args['code'],
'grant_type': 'authorization_code',
'redirect_uri': self.get_callback_url()
},
decoder=jsondecoder
)
me = oauth_session.get('').json()
social_id = 'google$' + me['sub']
username = me.get('name', None) if me.get('name', None) else me['email'].split('#')[0]
email = me['email'] if me['email_verified'] == True else None
url = me.get('profile', None)
image_json = 'https://www.googleapis.com/plus/v1/people/' + me['sub'] + '?fields=image&key=AIz..yAl..juCqj..sjj9y..PuM..R..9..F8p..mo'
image = image_json['image'] # <-- THIS DOESN'T WORK
return social_id, username, email, url, image, me
My problem is that the variable image_json contains the following:
{
"image": {
"url": "https://lh6.googleusercontent.com/-f..i0..dl..Gc/AAAAAAAAAAI/AAAAAAAAABQ/iNw-IEz...o/photo.jpg?sz=50",
"isDefault": false
}
}
and I have to extract the profile-picture-url from that. A substring method doesn't work since in order to get that code I have to "run" the url saved in image_json.
What I need is something like image = image_json['image'] to retrieve the string:
"https://lh6.googleusercontent.com/-f..i0..dl..Gc/AAAAAAAAAAI/AAAAAAAAABQ/iNw-IEz...o/photo.jpg?sz=50"
and I would like to change that size in 256 instead of 50.
I have followed many posts but I didn't found a solution for this thing.
The view that will call this function is the following:
#auth.route('/callback/<provider>')
def oauth_callback(provider):
oauth = OAuthSignIn.get_provider(provider)
social_id, username, email, url, image, jsonme = oauth.callback()
if social_id is None:
flash('Authentication failed! Access to ' + provider + ' denied.')
return redirect(url_for('main.home'))
user = User.query.filter_by(email=email).first()
if not user:
user = User(social_id=social_id, username=username, email=email, social_page=url, social_image=image)
db.session.add(user)
db.session.commit()
else:
...
login_user(user, True)
return redirect(url_for('main.home'))

Login to https website with Python with request

I'd like to access some content from https://bato.to/ that requires me to login first. Their login page is: https://bato.to/forums/index.php?app=core&module=global&section=login
I've opened chrome's web developer tools to inspect the POST that's sent when I click login. The 'Form Data' inside the POST is:
auth_key:880ea6a14ea49e853634fbdc5015a024
referer:https://bato.to/forums/
ips_username:startwinkling
ips_password:password1
rememberMe:1
So I've tried to implement this with the code:
Code so far
from requests import session
import re
AUTH_KEY = re.compile(r"<input type='hidden' name='auth_key' value='(.*?)' \/>")
payload = {
'ips_username': 'startwinkling',
'ips_password': 'password1',
'rememberMe' : '1',
'referer' : 'https://bato.to/forums/'
}
with session() as c:
login_url = 'https://bato.to/forums/index.php?app=core&module=global&section=login'
page = c.get(login_url)
auth_key = AUTH_KEY.search(page.text).group(1)
payload['auth_key'] = auth_key
print("auth_key: %s" % auth_key)
page = c.post(login_url, data=payload)
page = c.get('https://bato.to/reader#4b57865eb3a9a9a6')
print(page.text)
I believe I'm grabbing and passing in the auth_key properly since the code outputs:
auth_key: 880ea6a14ea49e853634fbdc5015a024
But the HTML that's printed out indicate that I haven't been able to successfully log in. What am I missing here?
The URL you use for POST is not correct.
The correct one should be https://bato.to/forums/index.php?app=core&module=global&section=login&do=process, it's not the same as login landing page, notice the extra do=process part.
Codes:
from requests import session
import re
AUTH_KEY = re.compile(r"<input type='hidden' name='auth_key' value='(.*?)' \/>")
payload = {
'ips_username': 'startwinkling',
'ips_password': 'password1',
'rememberMe' : '1',
'referer' : 'https://bato.to/forums/'
}
with session() as c:
login_url = 'https://bato.to/forums/index.php?app=core&module=global&section=login'
page = c.get(login_url)
auth_key = AUTH_KEY.search(page.text).group(1)
payload['auth_key'] = auth_key
print("auth_key: %s" % auth_key)
page = c.post(login_url + '&do=process', data=payload)
page = c.get('https://bato.to/reader#4b57865eb3a9a9a6')
print(page.text)
P.S. I would suggest you to add some headers(not use default headers) as well, you might not want to appear as User-Agent: python-requests/1.2.3 CPython/2.7.3 Windows/7 on their analytics, also in case they set some limits on certain pages for "non-browser" visit.

Passing Django forms' result to a page

I have worked on this for sometime now and I have decided to seek for your help. I have an ongoing project and I am using the django framework to build the site.
I have an html page that requests for user input, I have been able to extract the given data using the form.cleaned_data['']. A
#This is my views.py;
from django.shortcuts import render_to_response
from django.template import RequestContext
from forms import CarloanForm
def index(request):
form = CarloanForm()
if request.POST:
form = CarloanForm(request.POST)
if form.is_valid():
form.save()
else:
form = CarloanForm()
return render_to_response('carloan/index.html', {'form': form},
context_instance=RequestContext(request))
#I am extracting the user inputs using;
amount_of_vehicle = form.cleaned_data['cost_of_vehicle_Naira']
tenure = form.cleaned_data['loan_repayment_tenure_Months']
interest_rate = form.cleaned_data['interest_rate_Percentage']
equity = form.cleaned_data['equity_contrib_rate_Percentage']
depreciation_rate = form.cleaned_data['depreciation_rate_Percentage']
What I need to do and don't know how to go about it are;
Carry out some operations on the data (extracted using form.cleaned_data['']) and I have written some lines of code to that effect;
class LoanCalc:
def __init__(self,amount_of_vehicle,tenure,interest_rate,equity,depreciation_rate):
self.amount_of_vehicle = float(amount_of_vehicle)
self.tenure = float(tenure)
self.interest_rate = float(interest_rate)
self.equity = float(equity)
self.depreciation_rate = float(depreciation_rate)
def interest(self):
return (self.interest_rate/100) * self.amount_of_vehicle *(self.tenure/12)
def management_fee(self):
return 0.01 * (self.amount_of_vehicle + user.interest())
def processing_fee(self):
return 0.0025 *(self.amount_of_vehicle + user.interest())
def legal_fee(self):
return 0.0075 * (self.amount_of_vehicle + user.interest())
def residual_amount(self):
return 0.01 * (self.amount_of_vehicle - ((self.depreciation_rate/100) * self.amount_of_vehicle *(self.tenure/12)))
def equity_contribution(self):
return (self.equity/100) * self.amount_of_vehicle
def LoanPaymentPlan(self):
months = 1
total_amount = self.amount_of_vehicle+user.interest()+user.management_fee()+user.processing_fee()+user.legal_fee()+user.residual_amount()
upfront_payment = user.management_fee()+user.processing_fee()+user.legal_fee()+user.equity_contribution()+user.residual_amount()
opening_balance = total_amount - upfront_payment
balance = opening_balance
while months <= self.tenure:
if balance > 0:
monthly_instalment =(opening_balance/self.tenure)
monthly_interest = (((self.interest_rate/100) * balance)/ 12)
loan_payment = monthly_instalment - monthly_interest
closing_balance = balance - monthly_instalment
print' ',months,' ',round(balance,2),' ', round(monthly_instalment,2),' ',round(monthly_interest,2) \
, ' ',' ',round(loan_payment,2),' ',round(closing_balance,2)
balance = closing_balance
months += 1
return 'Thank you for using the Loan Calculator App'
and i want to carry out the operations in the code above on the extracted data.
I am thinking of doing it in such a way like this;
Create an empty dictionary;
user = {}
user = LoanCalc(amount_of_vehicle,tenure,interest_rate,equity,depreciation_rate)
result= user.interest()
result1 = user.management_fee()
. .
. .
. .
result10 = user.LoanPaymentPlan()
Pass the result(s) obtained from (question 2) to the same template that generated the form.
Please help me out guys, i am still very new to django. Thanks
This is the full stack of the referenced error am getting:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:9000/result/
Django Version: 1.4.1
Python Version: 2.5.4
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'carloan')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "C:\Python25\Lib\site-packages\django\core\handlers\base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "C:\Users\AJIBIKE\Documents\Circuit Atlantic\calculator\carloan\views.py" in result_page
226. 'carloan': instance,
def result_page(request):
if request.POST:
form = Carloan_formForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.interest = (instance.interest_rate/100) * instance.amount_of_vehicle * (instance.tenure/12)
instance.save()
else:
form = Carloan_formForm()
return render_to_response('carloan/result.html', {'carloan': instance,'form': form},
context_instance=RequestContext(request))
Exception Type: UnboundLocalError at /result/
Exception Value: local variable 'instance' referenced before assignment
Latest
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect, HttpResponse
from forms import Carloan_formForm
def index(request):
if request.POST:
form = Carloan_formForm(request.POST)
if form.is_valid():
instance = form.save()
return HttpResponseRedirect ('/result/')
form = Carloan_formForm()
kwvars = {
'form': form,
}
return render_to_response('carloan/index.html', kwvars,
context_instance=RequestContext(request))
def result_page(request):
instance = None
if request.POST:
form = Carloan_formForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.interest = (instance.interest_rate_Percentage/100) * instance.cost_of_vehicle_Naira * (instance.loan_repayment_tenure_Months/12)
instance.management_fee = 0.01 * (instance.cost_of_vehicle_Naira + instance.interest)
instance.processing_fee = 0.0025 * (instance.cost_of_vehicle_Naira + instance.interest)
instance.legal_fee = 0.0075 * (instance.cost_of_vehicle_Naira + instance.interest)
#i get syntax error starting from this line, and when i comment it out and the lines below, there is no syntax error.
instance.residual_amount = 0.01 * ((instance.cost_of_vehicle_Naira - ((instance.depreciation_rate_Percentage/100) * instance.cost_of_vehicle_Naira * (instance.tenure/12)))
instance.equity_contribution = (instance.equity_contrib_rate_Percentage/100) * instance.cost_of_vehicle_Naira)
instance.save()
else:
form = Carloan_formForm()
return render_to_response('carloan/result.html', {'instance': instance, 'form': form},
context_instance=RequestContext(request))
forms.py
from django import forms
from django.forms import ModelForm
from models import Carloan_form
class Carloan_formForm(ModelForm):
class Meta:
model = Carloan_form
exclude = ('interest', 'management_fee', 'processing_fee', 'legal_fee', \
'residual_amount', 'equity_contribution')
1 Save the result of the operations carried out on the extracted data in the Django Administration. (N.B: I already know how to save the user input)
Create a model to save the user's entries. app/models.py
class Carloan(models.Model) :
# In addition to your model fields add the functions that are part of your LoanCalc
...
Then create a ModelForm: app/forms.py
class CarLoanForm(forms.ModelForm) :
class Meta:
model = Carloan
Use CarLoanForm the same way you normally would except: app/views.py
if request.POST:
form = CarloanForm(request.POST)
if form.is_valid():
carloan = form.save()
#pass carloan (the instance) to the template and
#call its functions(from LoanCalc) instead of
#passing all of the values separately
Lastly, register this Model so it appears in the admin section app/admin.py
from django.contrib import admin
from app.models import Carloan
admin.sites.register(Carloan)
2 I have divided the page into two(one for the form and the other for
the result) and i want to pass the result to one-half of the page to
enable the user to see it.
Using the steps above, carloan will be passed to the view. go ahead and render its values.
Additionally:
Refactor index
your index definition should be refactored slightly, or your POST bound form will never make it to the template:
def index(request):
if request.POST:
form = CarloanForm(request.POST)
if form.is_valid():
instance = form.save()
else :
form = CarloanForm()
return render_to_response('carloan/index.html', {'form': form},
context_instance=RequestContext(request))
Refactor your ModelForm
Carry out some operations on the data (extracted using form.cleaned_data['']) and I have written some lines of code to that effect; - using a ModelForm instead of a regular django form you will get an instance of the model with the user's values already filled in, you reference them with instance.field.
and i want to carry out the operations in the code above on the extracted data. - the fields that you plan to calculate values for are listed in exclude they will not factor into form validation.
class CarLoanForm(forms.ModelForm) :
class Meta:
model = Carloan
# exclude fields that are calculated from user input
# NOTE: these fields must be in your model
exclude = ('interest', 'management_fee'...)
Refactor result page
Carry out some operations on the data (extracted using form.cleaned_data['']) and I have written some lines of code to that effect;
in results_page under the form.is_valid check, ther is a line: instance = form.save(commit=False) this gets all of the values that the user submitted in a instance of the Carloan Model that has NOT been saved yet.
further down: instance.interest = (instance.interest_rate/100) * instance.amount_of_vehicle *(instance.tenure/12) in this line I am calculating one of the excluded fields values (this calculation is a copy of your code).
lastly (after all of the operations on the data have been completed) I save the instance of the model.
then pass the instance to the template for display.
code:
def result_page(request):
if request.POST:
form = CarloanForm(request.POST)
if form.is_valid():
# get an instance from the form but don't save it
instance = form.save(commit=False)
# calculate excluded field values
instance.interest = (instance.interest_rate/100) * instance.amount_of_vehicle *(instance.tenure/12)
...
# after you have calculated all of the excluded fields save the instance
instance.save()
else :
form = CarloanForm()
return render_to_response('carloan/result.html', {'carloan' : instance, 'form' : form},
context_instance=RequestContext(request))
Error:
reference before error assignment - What does it say was referenced before assignment? Paste the entire stack trace please.
One of the simpler ways would be to store the data in the session in one view, retrieve it in the next. The docs will help.1
Having said that - there are a few other ways to approach the problem. It has been discussed more than once on SO:
Django Passing data between views
How do you pass or share variables between django views?
how to pass a list between views in django

Submit form on Django page without changing url

I have a text area in a django based website that displays the content of a database field.
I'd like to be able to edit this field and submit it to a function which updates the field in the database.
I know how I can call a function in a views.py which then send back the result of the query using render_to_response to a new webpage.
So in summary, how do I adress a function in a django/python script using a html form without the need to refer to another url?
It's usually recommended to use Post/Redirect/Get pattern, for example:
def myview(request, **kwargs):
if request.POST:
# validate the post data
if valid:
# save and redirect to another url
return HttpResponseRedirect(...)
else:
# render the view with partial data/error message
if request.GET:
# render the view
return render_to_response(...)
Use AJAX:
1) Create a view to handle form submission:
def my_ajax_form_submission_view(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
# save data or whatever other action you want to take
resp = {'success': True}
else:
resp = {'success': False}
return HttpResponse(simplejson.dumps(resp), mimetype='application/json')
else:
return HttpResponseBadRequest()
Then, tie the view into your urlpatterns
2) Submit form via AJAX (uses jQuery):
$('#my-form-id').submit(function(){
var $form = $(this);
$.post('/url/to/ajax/view/', $form.serialize(), function(data, jqXHR){
if (data.success) {
alert('Form submitted!');
} else {
alert('Form not valid');
}
});
return false;
});
That's the basics. You can and should provide more detailed return responses, error handling, form validation/checking, etc.
This is the standard views code pattern that I've been using.
def payment_details(request, obj_id):
yourobj = get_object_or_404(Obj, pk=obj_id)
form = TheForm(instance=yourobj)
if request.method == 'POST':
form = TheForm(request.POST, instance=yourobj)
if form.is_valid():
yourobj = form.save()
messages.success(request, 'Yourobj is saved!')
url = reverse('SOMEURL')
return redirect(url)
template = 'SOMETEMPLATE'
template_vars = {'TEMPLATEVARS': TEMPLATEVARS}
return render(request, template, template_vars)
Having watched the Advanced Forms talk at DjangoCon, one could re-write the above view like this:
def payment_details(request, obj_id):
yourobj = get_object_or_404(Obj, pk=obj_id)
form = TheForm(request.POST or NONE, instance=yourobj)
if request.method == 'POST' and form.is_valid():
yourobj = form.save()
messages.success(request, 'Yourobj is saved!')
url = reverse('SOMEURL')
return redirect(url)
template = 'SOMETEMPLATE'
template_vars = {'TEMPLATEVARS': TEMPLATEVARS}
return render(request, template, template_vars)