I would like to build my personal web pages in Pelican, but I am missing one functionality. I would love to have an introductory page for some/all categories on the pages.
For example - I would like to build a page for my grant project, where posts are related to activities and/or published papers, but I would also like a single page saying something about the grant project and keep this page as the title page of this category.
Is this possible (easily) in Pelican framework? If not, can you suggest better static pages framework that works in combination Markdown+Python?
This is actually very easy with pelican. The plugin Auto Pages defines three extra content folders: One for authors, one for categories and one for tags.
Say you, John Smith, wanted to have extra information about your person when clicking on your name. Then, you would add a file called authors/john-smith{.rst|.md} with this extra information. No HTML, but only the contents you want to provide about your person. These contents are then read in, transformed and presented to the template engine as author.page.
Now it is about your templates to also use this variable.
In my theme, I simply modified theme/templates/author.html to not show the combination of "featured article" and "other articles" related to my author, but to show author.page.content and "all articles" related to my author instead.
Short extract of my theme/templates/author.html:
<aside id="featured" class="body">
<article>
<h1 class="entry-title">{{ author }}</h1>
{{ author.page.content }}
</article>
</aside>
<section id="content" class="body">
<!-- removed the apostrophe for SO highlighting reasons-->
<h1>Authors articles</h1>
<hr/>
<ol id="posts-list" class="hfeed" start="{{ articles_paginator.per_page - 1}}">
{% for article in articles_page.object_list %}
<li><article class="hentry">
<header>
<h1><a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark"
title="Permalink to {{ article.title|striptags }}">{{ article.title }}</a></h1>
</header>
{% include 'article_infos.html' %}
{{ article.summary }}
<a class="readmore" href="{{ SITEURL }}/{{ article.url }}">read more</a>
{% include 'comments.html' %}
</article></li>
{% endfor %}
</ol>
{% if articles_page.has_other_pages() %}
{% include 'pagination.html' %}
{% endif %}
</section>
You can do the exact same thing for categories and tags using the procedure described above. For the template, just use the existing index.html and adapt it to your needs.
Related
I have a flask html page that retrieve applicants information from the database sqlalchemy, I want to click on a name of applicant from the first page and another page open with specific information for this applicant.
I sent a query for the first page and it works like I want, but I struggled in the second page, I did not know how to send that one record
this is the code of the first page, applicant-report page is the second page
{% for report in reports %}
<div class="rec_box">
<a class="text" href="/applicant-report">
{% for a in applicant %}
{% if a.phone == report.applicant_phone %}
{{a.name}}
{% endif %}
{% endfor %}
</a>
<p class="rec_small">O: {{(report.op*100)}}%</p>
<p class="rec_small">C: {{report.co*100}}%</p>
<p class="rec_small">E: {{report.ex*100}}%</p>
<p class="rec_small">A: {{report.ag*100}}%</p>
<p class="rec_small">N: {{report.ne*100}}%</p>
</div>
{% endfor %}
Pass parameters between pages is usually using the URL, since this method is showed to the end user, I suggest not include any passwords or something like that
In the link you will redirect the user ends in something like
<a class="text" href="/applicant-report?phone={{a.phone}}">
Where the a.phone is the value of your variable. To read this url in the other page, you use something like
applicant_phone = request.args.get('phone')
applicant = session.query(Applicant).filter_by(phone=applicant_phone).first()
If you want to add another parameter to the url you concat using & between them, like
<a class="text" href="/applicant-report?phone={{a.phone}}&{{a.contact}}">
And so on.
Hope you find this usefull
I am trying to build a blog using lektor CMS, for that.. i needed a tags system, after searching i found a lektor plugin on lektor docs called lektor-tags
I followed every step on the docs, struggled a lot and even visited the github repo to see if is there anything else not included in the docs.
My problem is when i try to visit localhost:5000/{the_tag_name} say like localhost:5000/python i always get a 404 Not Found saying that
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
This is what i did so far:
Before using lektor-tags:
I changed the route for the blog posts to be /posts instead of /blog.
Added slug format to models/blog.ini in [children]
[children]
model = blog-post
order_by = pub_date, title
slug_format = {{ (this.pub_date|dateformat('YYYY/M/') if this.pub_date) ~ this._id }}
Created 3 posts, everything was working properly.
At this point i wanted to use a tags system so i chosen to use lektor-tags, what i did was:
Installation
lektor plugins add lektor-tags
Created configs/tags.ini with this config:
parent = /
url_path = {{ this.parent.url_path }}{{ tag }}
tags_field = tags
ignore_missing = true
template = tags.html
Created templates/tags.html with the following content:
{% extends "layout.html" %}
{% block title %}{{ this.title }}{% endblock %}
{% block body %}
<div class="container mt-3">
<b>Tag: {{ this.tag }}</b>
<b>Items:</b>
<ul>
{% for i in this.items %}
<li>{{ i._id }}</li>
{% else %}
<li><em>No items.</em></li>
{% endfor %}
</ul>
</div>
{% endblock %}
Edited models/blog-post.ini and added:
[fields.tags]
type = strings
In templates/blog-post.html i added the following to show links to the page that contain a list of all posts with the specific tag:
{% if this.tags %}
<ul>
{% for t in this.tags -%}
<li>
<a href="{{ ('/' ~ t.lower())|url }}">
All posts tagged {{ t }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
Finally i updated a post to contain some tags from the admin and made sure it's there in content.lr for that post. so i stopped the lektor dev server and run it again lektor servor with no errors to be present.
The links were there in the post for the tags but when i click and follow a link say for example for the python tag localhost:5000/python i get 404 Not Found. i am new to lektor. i'm wondering what i did wrong and how can i get this to work properly?
NB: Other plugins i used are lektor-minify, lektor-disqus-comments the docs for these plugins were straightforward and i didn't got confused, but when it comes to this specific plugin i were confused, struggling: the docs were not that great and explaining, i felt completely lost!
Update
I created a github repo containing the code and what i have done so far so you can easily replicate this.
Update 2
I managed to get this to work properly see my answer below, however now i'm wondering how to set the root as the parent in other words how to edit this expression :
<a href="{{ ('/posts#tag/' ~ t.lower())|url }}">
to generate a source path for each of the blog post's tags but using root as the parent.
As you can see i tried this :
<a href="{{ ('/' ~ t.lower())|url }}">
but this doesn't work properly.
It's worth mentioning that lektor uses jinja2 templating language.
So Basically it was me doing this wrong because i wanted to use the root as the parent in tags.ini like so :
parent = /
I ended up changing the expression '/blog#tag/' ~ t.lower() in blog-post.html to something like :
<a href="{{ ('/' ~ t.lower())|url }}">
making it not able to generate a source path for each of the blog post's tags
What i changed and worked was :
I chosen posts to be the parent, updated the configs/tags.ini to :
parent = /posts
url_path = {{ this.parent.url_path }}{{ tag }}
tags_field = tags
ignore_missing = true
template = tags.html
Updated templates/blog-post.html :
{% if this.tags %}
<ul>
{% for t in this.tags -%}
<li>
# '/posts#tag/' ~ t.lower() because i changed the route of blog to posts
<a href="{{ ('/posts#tag/' ~ t.lower())|url }}">
All posts tagged {{ t }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
After running lektor clean --yes then lekor server everything was working properly including the tags system.
So I have been tinkering for a while with jinja2 and google app engine. I am just writing a small toy app on my spare time; the app has a webpage that displays the ten most recent posts along with its comments.
All of the blog posts print fine onto the page by using the following within the google data store, after the Post object is created and stored in the database of course. I use the following query to get the ten posts to be displayed.
recent_blog_posts = ndb.gql("SELECT * FROM Posts ORDER BY created_at
DESC LIMIT 10;")
The blogpage.html code below:
{% block content %}
{% for post in recent_blog_posts %}
<div>
<h3>{{post.title}}</h3>
<pre>
<p style="max-width: 100%;">{{post.post}}</p>
</pre>
<p>By: {{post.by_user}}</p>
<!-- this is where I want the comments to go (explained below)-->
<h4>Leave A Comment:</h4>
<form method="post">
<textarea name="comment" value="{{comment}}" style="height: 50px; width: 200px;"></textarea>
<input type="hidden" name="post_key" value="{{post.key}}">
<br>
<button>Comment</button>
</form>
</div>
<hr>
{% endfor %}
{% endblock %}
I just iterated over the ten objects in the query above to print all of the blog posts. However, this is where it gets tricky for me.
I create a new Comment instance with the following:
new_comment = Comments(comment = comment,
user = user.name, parent = ndb.Key(Posts, int(post_key)))
new_comment_key = new_comment.put()
When I print the new Comment instances onto the screen, just to see, they all print out correctly with the right parent and their own ids.
Now this is where I am not sure on how to take each Comment instance and print it with its corresponding post. How can I accomplish that?
I have searched everywhere, and even added this to the html template above. (In place of the comment from the html template above)
{% for comment in comment_query %}
{{comment.comment}}
{% endfor %}
With the query below:
recent_comments = Comments.query(ancestor=ndb.Key(Posts, int(new_string))).order(-Comments.created_at).fetch(limit=3)
This obviously just prints out all of the Comments instances for all of the Posts instances on the page.
Thanks In Advance
Just form the output list in the backend itself.
recent_blog_posts = ndb.gql("SELECT * FROM Posts ORDER BY created_at
DESC LIMIT 10;")
posts_with_comments = []
for post in recent_blog_posts:
recent_comments = Comments.query(ancestor=post.key).order(-Comments.created_at).fetch(limit=3)
posts_with_comments.append([post, recent_commmnets])
Then iterate over posts_with_comments in the template like
{% for post,comments in posts_with_comments %}
<div>
<h3>{{post.title}}</h3>
<pre>
<p style="max-width: 100%;">{{post.post}}</p>
</pre>
<p>By: {{post.by_user}}</p>
<p> Comments: </p>
{% for commnet in comments %}
{{ comment }}
{% endfor %}
{% endfor %}
When I blog, I like to separate each blog-post into its own .html file (is that ok?)
This prevents the file getting too big, and makes it easy to go back and edit a previously written blog post if need be.
Occasionally the blog post will contain css/js/ajax/template variables.
But on my website, I like all the blog posts on one page (so I can scroll through them all, instead of going to a separate page for each post)
Here is an html file that contains two blog posts:
{% extends "base.html" %}
{% block blog_posts %}
<!-- links/targest for the side menu to jump to a post -->
<li>Post2 - April 2012</li>
<li>Post1 - Feb 2012</li>
{% endblock %}
{% block content %}
<div id="post1">
spam1 blah blah
</div>
<div id="post2">
spam2
</div>
{% endblock %}
and in base.html I have something like:
<div id="content-container">
<div id="section-navigation">
<ul>
{% block blog_posts %}
{% endblock %}
</ul>
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</div>
What is the best way for me to split these blog posts out into separate files using webapp2 and jinja2?
e.g. blog1.html might look like:
{% block blog_posts %}
<!-- links/targest for the side menu to jump to a post -->
<li>Post1 - Feb 2012</li>
{% endblock %}
{% block content %}
<div id="post1">
spam1 blah blah
</div>
{% endblock %}
(And I would want the links and the blogposts to be displayed in the right order on the website)
I could think of a way of doing it where post2 extends post1.html, post3 extends post2.html etc, but I would prefer to fan out more
"Henry and Kafura introduced Software Structure Metrics Based on Information Flow in 1981[2] which measures complexity as a function of fan in and fan out."
Thanks
#robert king, your design has data embedded directly in the template. Templates should only contain the blueprint to a view, and they should be rendered with new data generated from your main code every time. I simulate this process here (Edited to illustrate the use of a loop to extract post titles, and the display of a single post.):
import jinja2
# NOTE: in this template there is no data relating to specific posts.
# There are only references to data structures passed in from your main code
page_template = jinja2.Template('''
<!-- this is a navigation block that should probably be in base.html -->
{% block blog_posts %}
<!-- links/targets for the side menu to jump to a post -->
{% for post in posts %}
<li><a href="{{ post.url }}">{{ post.title }}
- {{ post.date }}</a></li>
{% endfor %}
{% endblock %}
<!-- this is a content block that should probably be in page.html -->
{% block content %}
<div id="post">
<h1>{{ current.title }}</h1>
<h2>{{ current.date }}</h2>
<p>{{ current.content }}</p>
</div>
{% endblock %}
''')
# NOTE your main code would create a data structure such as this
# list of dictionaries ready to pass in to your template
list_of_posts = [
{ 'url' : '#post1',
'title' : 'My first post',
'date' : 'Feb 2012',
'content' : 'My first post is about Hello World.'},
{ 'url' : '#post2',
'title' : 'My second post',
'date' : 'Apr 2012',
'content' : 'My second post is about Foo Bar.'}
]
# Pass in a full list of posts and a variable containing the last
# post in the list, assumed to be the most recent.
print page_template.render(posts = list_of_posts,
current = list_of_posts[-1])
Hope this helps.
EDIT See also my answer to a question on "Site fragments - composite views"
I just found another option in the jinja2 tutorial. I think it makes more sense for my handler to pass my template a list of filenames of blog posts, and then to include the blog posts.
include - returns the rendered contents of that file into the current namespace:
{% include 'header.html' %}
<div ...
{% include 'footer.html' %}
Included templates have access to the variables of the active context by default. For more details about context behavior of imports and includes see Import Context Behavior.
From Jinja 2.2 onwards you can mark an include with ignore missing in which case Jinja will ignore the statement if the template to be ignored does not exist. When combined with with or without context it has to be placed before the context visibility statement. Here some valid examples:
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
New in version 2.2.
You can also provide a list of templates that are checked for existence before inclusion. The first template that exists will be included. If ignore missing is given, it will fall back to rendering nothing if none of the templates exist, otherwise it will raise an exception. Example:
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
When I read the raw html file (file.read()) and passed the data to my template, it escaped all the html.
instead of {{data}} i had to use {{data|safe}} which allowed raw html.
something like:
class HomeHandler(BaseHandler):
def get(self):
file_names = sorted(os.listdir('blog_posts'))
html = [open('blog_posts/%s' % fn).read() for fn in file_names]
templates = {'html': enumerate(html)}
self.render_template('home.html', **templates)
{% block content %}
{% for num,data in html %}
<div id="post{{num}}">
{{data|safe}}
</div>
<br />
<img src="http://www.sadmuffin.net/screamcute/graphics/graphics-page-divider/page-divider-007.gif" border=0>
<br />
{% endfor %}
{% endblock %}
(make sure the directory isn't a static directory)
i have problem with results in django-cms and haystack search. I'm using django-cms-search plugin, haystack as backend. Haystack returns correct results. But i want to show "teaser" in search results.
I can access absolute URL and title of page via template this way:
{% for result in page.object_list %}
<div class="searchResults">
<h2>{{ result.object.get_title }}</h2>
{{ result.object.placeholders.all }}
<p>{% blocktrans %} Read more {% endblocktrans %}</p>
Problematic part is {{ result.object.placeholders.all }}. I have on every page content in placeholder with name content.
{{ result.object.placeholders.all }} returns only name of the placeholders.
Search results should look like this:
PAGE TITLE
PAGE TEASER
READ MORE LINK
In teaser there should be first 50 words from search-matched page.
Is this possible to access placeholder content from template?
Thank you for your tips.
Haystack has templatetag higlight which creates "teaser" as i requested.
Template code can look like this:
{{ result.object.get_title }}
{% highlight result.text with request.GET.q max_lenght 40 %}
{{ result.object.get_absolute_url }}
Thanks to guys from #haystack IRC channel.