I have one python script which I want to execute as a daily cron job to send emails to all users. Currently I have hard-coded the html inside the script and it looks dirty. I have read the docs, but I haven't figured out how can I render the template within my script.
Is there any way that I can have the separate html file with placeholders which I can use python to populate and then send as the email's body?
I want something like this:
mydict = {}
template = '/templates/email.j2'
fillTemplate(mydict)
html = getHtml(filledTemplate)
I am going to expand on #Mauro's answer. You would move all of the email HTML and/or text into a template file(s). Then use the Jinja API to read the template in from the file; finally, you would render the template by providing the variables that are in the template.
# copied directly from the docs
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
template = env.get_template('mytemplate.html')
print template.render(the='variables', go='here')
This is a link to an example of using the API with the template.
I was looking to do the same thing using Jinja within the Flask framework. Here's an example borrowed from Miguel Grinberg's Flask tutorial:
from flask import render_template
from flask.ext.mail import Message
from app import mail
subject = 'Test Email'
sender = 'alice#example.com'
recipients = ['bob#example.com']
msg = Message(subject, sender=sender, recipients=recipients)
msg.body = render_template('emails/test.txt', name='Bob')
msg.html = render_template('emails/test.html', name='Bob')
mail.send(msg)
It assumes something like the following templates:
templates/emails/test.txt
Hi {{ name }},
This is just a test.
templates/emails/test.html
<p>Hi {{ name }},</p>
<p>This is just a test.</p>
You can use Jinja2, a template language for Python. It has template inheritance feature. Look at this example from official docs.
Related
this is the exercise(you can use only two html templates (the index and the movie). When the user navigates to a movie specific page the description and title must be read from a file called {movie_id}.txt within the project dir and then passed to movie template.)
i tried this ===>>
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/index")
def index():
return render_template("index.html")
#app.route("/marvel")
def marvel():
with open("marvel.txt") as file:
return render_template("movie.html", text=file.read())
however it only printed the html codes inside the text file and didnt use it as html codes.
If I understand you correctly, the text file contains html tags, which are automatically escaped within the template. Use the Jinja2 filter safe within the template to suppress this behavior.
{{ text | safe }}
An alternative to declare content outside of the template as safe is the following. You can find the documentation here.
from flask import Markup
#app.route("/marvel")
def marvel():
with open("marvel.txt") as file:
html = Markup(file.read())
return render_template("movie.html", text=html)
Note that the default behavior has been implemented for security reasons and you are aware of what the contents of the text file can do within your page.
Perhaps your task allows you to reconsider your data structure and application design so that you can format the html entirely within the template and not within a plain text file.
i am unable to set the environment variables from jinja2
<body>
<h1>hi {{session['user']}}<h1>
{{session['user']='Mad'}}
</body>
<body>
<h1>
hi {{session['user']}}
<h1>
{{session['user']='Mad'}}
</body>
I have already declared session['user'] in python code in flask but i am unable to set it in jinja2 that is the with the following html code
As described above, you need to define your variables within your backend and pass them to your template. For example:
run.py
from flask import Flask, render_template, session
app = Flask(__name__)
app.secret_key = 'your-secret-key'
#app.route("/<user>")
def user_page(user):
session['user'] = user
return render_template("user_page.html", user=session['user'])
if __name__ == '__main__':
app.run()
user_page.html
<body>
<h1>hi {{ user }}<h1>
</body>
Doing this doesn't make sense. Jinja2 is an HTML templating system, used server-side to render a page; it is not meant to update global variable. The logic should be implemented in your python code, before calling the template. The repsonsibility is thus:
python method: does server-side logic and prepare the variables needed by Jinja2 to render the response page;
jinja2 template: simply render the page using the variables prepared in 1.
Hence, editing session content should never appear in Jinja2 (it wouldn't make any sense anyway), so move your line to the python code. If you need two different names, simply save the old session value to a new variable that you pass to jinja2 alongside the updated session.
I am familiar with flask, and trying hands on bottle module. I wanted to have a single base.tpl file which can have an editable body and the other tpl files could extend this base file and edit in its body to change the content. Like in flask, using jinja, we could use {% block bodyContent %}{% endblock %} and insert the html body content later when needed. How can we achieve the same with bottle module?
Bottle comes with jinja2 support, out of the box. Here's a toy example, just to illustrate. Note that you may prefer to use Bottle's jinja2_view rather than return a template directly.
from bottle import jinja2_template
app = Bottle()
home_template = '''
{{greeting}} - Thanks for stopping by.
'''
app.route('/')
def home():
return jinja2_template(home_template, greeting='Hello!')
You can find examples of more advanced usage here.
Actually bottle comes with this solution built into it's own template engine.
https://bottlepy.org/docs/dev/stpl.html#template-functions
include(sub_template, **variables)
Render a sub-template with the specified variables and insert the resulting text into the current template. The function returns a dictionary containing the local variables passed to or defined within the sub-template:
% include('header.tpl', title='Page Title')
Page Content
% include('footer.tpl')
rebase(name, **variables)
Mark the current template to be later included into a different template. After the current template is rendered, its resulting text is stored in a variable named base and passed to the base-template, which is then rendered. This can be used to wrap a template with surrounding text, or simulate the inheritance feature found in other template engines:
% rebase('base.tpl', title='Page Title')
<p>Page Content ...</p>
This can be combined with the following base.tpl:
<html>
<head>
<title>{{title or 'No title'}}</title>
</head>
<body>
{{!base}}
</body>
</html>
I am running a Django website and I want to be able to upload a file through my admin panel and then have visitors to the main site be able to download it. I am running my site using Django-nonrel, Django FileTransfers and Google App Engine. I believe the upload functionality is working correctly as I am able to see the file in my App Engine Blob Storage. What I can't seem to figure out is how to present a download link to the specified file on the public website. I have pasted the relevant classes below:
I have an app called Calendar, that has the following model:
class CalendarEvent (models.Model):
start = models.DateTimeField(auto_now=False, auto_now_add=False)
end = models.DateTimeField(auto_now=False, auto_now_add=False)
title = models.CharField(max_length=500)
description = models.TextField()
file = models.FileField(upload_to='uploads/%Y/%m/%d/%H/%M/%S/')
Here is the view:
def calendar(request):
events = CalendarEvent.objects.exclude(start__lt=datetime.datetime.now()).order_by('start')
return render_to_response('home/calendar.html',{'events': events},context_instance=RequestContext(request))
def download_handler(request, pk):
upload = get_object_or_404(CalendarEvent, pk=pk)
return serve_file(request, upload.file, save_as=True)
Here is my admin:
class calendarAdmin(admin.ModelAdmin):
list_display = ('title','start','end')
admin.site.register(CalendarEvent, calendarAdmin)
Finally, here is the relevant part of my template:
{% for e in events %}
{% url Calendar.views.download_handler pk=e.pk as fallback_url %}
Download
{% endfor %}
{% firstof e.file|public_download_url fallback_url %} is just returning blank, i'm not sure where I am going wrong.
The GAE blob store does not support public download according to the documentation here, so if you use the default backend for public download urls, it returns None. So my guess is that e.file|public_download_url always return None. You could verify that.
Then I think your template is wrong. You're trying to access e.views.download_handler where it should be Calendar.views.download_handler if your app is named Calendar.
I think the sample on the django-filetransfers page is error prone because the variable used in the template loop has the same name as the sample app: "upload".
If this doesn't fix it, could you post your urls.py from Calendar app. It could be that the template's url method is not able to resolve the url for Calendar.views.download_handler if there is no mapping in urlpatterns.
You should have something like
urlpatterns = patterns('Calendar.views',
...
(r'^download/(?P<pk>.+)$', 'download_handler'),
...
)
in this file.
I don't see anything special, eg
Download File
should work, or just use e.file.url directly?
I haven't deployed on Google App Engine myself, but this appears to be what django-filetransfers was designed for:
http://www.allbuttonspressed.com/projects/django-filetransfers#handling-downloads
edit: I believe I've answered this in the other question you posted, then: Trouble downlaoding file using Django FileTransfers
I think easiest way is to write a view since this file blob cannot be retrieved directly to write a function which is such:
def file_transfer(req, calendar_event_id):
try:
ce = CalendarEvent.objects.get(calendar_event_id)
except CalendarEvent.DoesNotExist:
raise Http404()
file = ce.file (Write Google appengine specfic routine to pull file)
return HttpResponse(file, media_type='file content type')
Hook it up on urls.py
I have an HTML file that has a web page design with a single form, for a user to enter his name. I want to create an six entry array for every submission (to later be filled with information on another page)
Is Django the proper utility to use for this? I would like to have the html design file and the python back end processing as separate files. If so, can anyone point me towards a good place to read about integrating HTML and underlying python codes that process HTML submission forms?
Django may be overkill for this. If all you want is a way to link a form to some backend Python code, a micro framework like Flask might be a better choice.
Here is how you do a simple form with Flask:
Create a directory project and inside it, a directory templates
Your template is simple:
{% if name %}
Hello {{ name }}
{% endif %}
<form method="POST">
<input type="text" name="name" value="Enter your name">
<input type="submit">
</form>
Save that as index.html in the templates subdirectory.
Create a file called go.py in the project directory, and in it copy and paste this:
from flask import Flask
from flask import render_template
from flask import request
app = Flask(__name__)
#app.route('/',methods=['POST','GET'])
def process_form():
if request.method == 'POST':
form_input = request.form['name']
return render_template('index.html',name=form_input)
else:
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
Finally from the project directory, type:
python go.py
Open your browser and go to http://localhost:5000/
You can create html form in Django, though you may have to convert the form to a template.
In case this you first time to use django, you may go though the official Django book
Django provides a template system (in which the presentation files are separate from the business logic and the entire system is highly decoupled). The template language is simple (but very powerful) text substitution on top of an existing text file. You can use the Django templates in HTML (full or partial), text, XML, JSON, or nearly any other text-based format.
Django also allows you to hook into another template system, but I don't know a lot about how that works.
Look at the Django template documentation for more information.