I am using this procedure to use a base template which the other templates can derive from.
How can I create multiple base templates?
Just register them both:
from pyramid.renderers import get_renderer
def add_base_template(event):
base = get_renderer('templates/base.pt').implementation()
base2 = get_renderer('templates/base2.pt').implementation()
event.update({'base': base, 'base2': base2})
And then choose which to use in your template for each page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="base">
<tal:block metal:fill-slot="content">
My awesome content.
</tal:block>
</html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="base2">
<tal:block metal:fill-slot="content">
Content on a totally different page.
</tal:block>
I believe a template doesn't have to be the whole HTML element, so you could instead expand 2 macros into the same final template
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<body>
<div metal:use-macro="section1">
<tal:block metal:fill-slot="content">
Content for template "section1".
</tal:block>
</div>
<div metal:use-macro="section2">
<tal:block metal:fill-slot="content">
Content for template "section2".
</tal:block>
</div>
</body>
Related
This is urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.login_page, name='login_page'),
]
my views.py like this
def login_page(request):
return render(request, 'mileage/login_page.html', {})
this is my html code
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" >
<meta charset="UTF-8">
<title>Test</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js">
</script>
</head>
<body bgcolor="#4599e8">
<div class="title"><span><h1>Test</h1></span></div>
<div class="home_password">
<div class="password"><input type="password" name="password" placeholder="Password"></div>
<div class="button"><button>OK</button></div>
</div>
</body>
</html>
And start server, but my localhost:8080/ shows only html text not page.
Using Chrome Developer Console, I checked element.
<html>
<head></head>
<body>
<pre style="word-wrap: break-word; white-space: pre-wrap;">
"
my html code here.
"
</pre>
</body>
</html>
I don't know how to solve it.
Who is inserting all your html code inside the pre tag is your browser because it probably receives a Content-type: text/plain header with the response and it thinks you want to see the html code instead of the rendered webpage.
Try making a test using:
render(request, 'mileage/login_page.html', {}, content_type='text/html')
If it works, set the DEFAULT_CONTENT_TYPE constant to 'text/html' in your settings.
DEFAULT_CONTENT_TYPE
Default: 'text/html'
Default content type to use for all HttpResponse objects, if a MIME
type isn’t manually specified. Used with DEFAULT_CHARSET to construct
the Content-Type header.
Probably an environment variable is messing you up with this, It's weird that it has a default 'text/plain' content type set.
I'm my django app I would like to load a static html page into a main template. This static html page is an email template. My goal is to edit this email in my main template. The email html page don't have a view in url.py. I don't use include in main template and I don't want to use iframe. The problem is that I would like to load ALL the html email tag (like
<html>
<head>
<body>
) but when I do the page's render this tag is deleted (or I don't see them in main template...). This is my code:
view.py
def my_view(request):
file_name = "/templates/path/emailtemplate.html"
htmlblock = render_to_string(file_name, {})
return render_to_response('main_template.html', {
'htmlblock': htmlblock,
},
context_instance = RequestContext(request))
main_template.html
<html>
<head>
....
<head>
<body>
<div id="content">
{{htmlblock}}
</div>
</body>
</html>
this is what I would like to have:
<html>
<head>
....
<head>
<body>
<div id="content">
<html>
<head>
....
</head>
<body>
...
</body>
</html>
</div>
</body>
</html>
Is this possible without iframe? Thanks a lot for your help.
EDIT
My goal is to have the
<html>
<head>
<body>
tag into
<div id="content">
where I load the email template.
My goal is to edit this email in my main template.
You can read the template into string by
with open('/templates/path/emailtemplate.html', 'r') as content_file:
content = content_file.read()
You can use the same as a value to an edit field and it will be visible as usual. This can be used as.
return render_to_response('main_template.html', {
'htmlblock': content,
}, context_instance = RequestContext(request))
You can further use the same in edit field as:
<textarea value={{htmlblock}}>
Or render the same normally in
<div id="content">{{htmlblock}}</div>
I am experiencing a weird issue using Django on Google App Engine. I have a file upload form defined within a django-app like this:
class ConvertForm(forms.Form):
from = forms.ChoiceField(choices=choices_from,
label='from:')
to = forms.ChoiceField(choices=choices_to,
label='to:')
class Meta:
fields = ('from','to')
And then I have in my app.views file the following:
def convert(request):
if request.POST:
form = ConvertForm(request.POST,request.FILES)
if form.is_valid():
from = form.cleaned_data['from']
to = form.cleaned_data['to']
# Redirect to a result page after post to avoid duplicates
return HttpResponseRedirect('/convert/results')
else:
form = ConvertForm()
args = {}
args.update(csrf(request))
args['form']=form
return render_to_response('convert.html',args)
The form-part of my convert.html template looks like this:
<form action="/convert/convert/" method="post" enctype="multipart/form-data">{%\
csrf_token %}
<ul>
{{ form.as_ul }}
</ul>
<input type="submit" name="submit" value="Convert">
</form>
It's supposed to be a file-upload form (hence the multipart), but I edited the form-contents for brevity.
Now, when I browse the proper url, nothing happens. I can clearly see that the correct functions are being called, since replacing the body of the convert() function with a simple
return render_to_response('convert_test.html',{'some_text':some_text})
displays the value of some_text in the browser window. Is there any additional quirks when dealing with forms within GAE that I am missing, or why isn't convert.html being rendered with the form? I should mention that all of this is on localhost, I haven't deployed it yet.
Edit: After some more fiddling around with this, it seems that maybe the source of the error is in the inheritance of templates. If I take out all django-tags {} in the convert.html, I can get the form to render correctly.
So, the question is now how do I properly set up template inheritance within GAE?
My full convert.html template looks like this:
{% extends "base.html" %}
{% block content %}
<h2>[ convert ]</h2>
<form action="/convert/convert/" method="post" enctype="multipart/form-data">{% \
csrf_token %}
<ul>
{{ form.as_ul }}
</ul>
<input type="submit" name="submit" value="Convert">
</form>
{% endblock %}
So basically redefining the content block of the base.html template. This was working perfectly before I tested it on GAE, so I can't shake the feeling that's involved somehow.
If it is relevant, my django settings.py looks like this for the templates:
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__),'..','convert','templates'),
os.path.join(os.path.dirname(__file__),'..','templates'),
)
And as I said, taking out the {}-tags from convert.html gives me the form, but rendered on its own in an otherwise completely white and empty page.
This is the contents of my base.html template
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/\
DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="Your description goes here" />
<meta name="keywords" content="your,keywords,goes,here" />
<meta name="author" content="Your Name" />
<link rel="stylesheet" type="text/css" href="/static/css/basic-minimal.css" ti\
tle="Basic Minimal" media="all" />
<title>Basic Minimal v1.2</title>
</head>
<body class="light">
<div id="wrap">
<div id="header">
<h1>[ snazzy title ]</h1>
</div>
<div id="sidebar">
<ul>
<li>[ Convert ]</li>
<li>[ Transform ]</li>
<li>[ Help ]</li>
<li>[ References ]</li>
</ul>
</div>
<div id="content">
<h2>[ more title ]</h2>
<p>Text</p>
<p>More text</p>
</div>
</div>
</body>
</html>
This works beautifully for the "title" page (even the css gets loaded), but rendering other templates as convert.html above using this as a base does not work.
I am using latest Pyramid to build a web app. Somehow we have started using Chameleon as the template engine. I have used Mako before and it was extremely simple to create a base template. Is this possible with chameleon as well?
I have tried to look through the docs but I can not seem to find an easy solution.
With Chameleon >= 2.7.0 you can use the "load" TALES expression. Example:
main.pt:
<html>
<head>
<div metal:define-slot="head"></div>
</head>
<body>
<ul id="menu">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<div metal:define-slot="content"></div>
</body>
</html>
my_view.pt:
<html metal:use-macro="load: main.pt">
<div metal:fill-slot="content">
<p>Bonjour tout le monde.</p>
</div>
</html>
Another option, which was used prior Chameleon got an ability to load templates from the filesystem, is to pass the "base" template as a parameter.
To simplify things, I often wrap such stuff into a "theme" object:
class Theme(object):
def __init__(self, context, request):
self.context = context
self.request = request
layout_fn = 'templates/layout.pt'
#property
def layout(self):
macro_template = get_template(self.layout_fn)
return macro_template
#property
def logged_in_user_id(self):
"""
Returns the ID of the current user
"""
return authenticated_userid(self.request)
which can then be used like this:
def someview(context, request):
theme = Theme(context, request)
...
return { "theme": theme }
Which then can be used in the template:
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="theme.layout.macros['master']">
<body>
<metal:header fill-slot="header">
...
</metal:header>
<metal:main fill-slot="main">
...
</metal:main>
</body>
</html>
Make a template here:
<proj>/<proj>/templates/base.pt
with contents:
<html>
<body>
<div metal:define-slot="content"></div>
</body>
</html>
Use the template here:
<proj>/<proj>/templates/about_us.pt
by inserting the contents:
<div metal:use-macro="load: base.pt">
<div metal:fill-slot="content">
<p>Hello World.</p>
</div>
</div>
I'm using webpy with a basic template
render = web.template.render(basedir + 'templates/', base='layout', globals=globals_vars_custom)
in layout.html I have something like:
$def with (content)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>PAGE TITLE</title>
<!-- Some CSS and some javascript -->
</head>
<body>
$:content
</body>
</html>
This basic template works fine for the 90% of my site, but I have a page in which I need to insert some other data inside the <head> (some meta tags).
How can I do this? How can I put the <head> inside a structure that I can easily override inside a template?
Thanks!
It was easier than I tought:
You can create a variable in a template:
in page.html you can define a variable
$var title = 'specific title'
in the base template layout.html you can call the varable:
$def with (content)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>$content.get("title","DEFAULT TITLE")</title>
<!-- Some CSS and some javascript -->
</head>
<body>
$:content
</body>
</html>
I hope this answer can be useful also for other people.