The Goal
I'm creating a Flask website to serve as the UI for a custom bioinformatics pipeline. The way I'm trying to design it is such that the user fills in the pipeline parameters (e.g. Project Name, Data Type, Number of Samples, etc.) in a multi-page form (kind of like the checkout process in online ordering) and then I would like these parameters to be saved to the user's account page as separate "posts".
The Issue
I've been following a Flask Tutorial online (https://www.youtube.com/watch?v=QnDWIZuWYW0&list=PL-osiE80TeTs4UjLw5MM6OjgkjFeUxCYH&index=2) about how to save the "posts" (pipeline parameters) to the user's dashboard by supplying fake or sample "posts" to the dashboard's html template, but nothing shows up at all. What am I doing wrong?
The Source Code
routes.py:
posts = [
{
'username': 'claudiadast',
'date_posted': 'September 22, 2018',
'stack_name': 'wgs-test-stack',
'start_point': 'fastq',
'input_uri': 's3://pipeline-validation/smallfq/',
'build': 'GRCh38',
'ome': 'wgs',
'project_id': 'summerwater598'
},
{
'username': 'claudiadast',
'date_posted': 'September 10, 2018',
'stack_name': 'clinical-exome',
'start_point': 'fastq',
'input_uri': 's3://pipeline-validation/Clinex/',
'build': 'GRCh38',
'ome': 'wes',
'project_id': 'summerwater598'
}
]
#app.route('/')
#app.route('/home')
def home():
return render_template('home.html', posts=posts)
home.html:
{% extends "layout.html" %}
{% block content %}
{% for post in posts %}
<h1>{{ post.stack_name }}</h1>
<p>{{ post.username }} on {{ post.date_posted }}</p>
<p>Pipeline Parameters:</p>
<p>{{ post.stack_name }}</p>
<p>{{ post.start_point }}</p>
<p>{{ post.input_uri }}</p>
<p>{{ post.build }}</p>
<p>{{ post.ome }}</p>
<p>{{ post.project_id }}</p>
{% endfor %}
{% endblock content %}
layout.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Psychcore Pipeline</title>
<link rel="stylesheet" href="static/site.css"
</head>
<body>
{% include 'includes/_navbar.html' %}
<div class="container">
{% block body %}{% endblock %}
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js'></script>
</body>
</html>
In your layout.html you are defining a {% block body %}, however in your home.html you are using {% block content %}. Change one of these to match the other one and it should work.
To have jinja template read from a dict you need to change the syntax of all variables to the following in home.html:
{{ post['username'] }}
Related
I am a little confused about what {% extends base %} is extending at the start of index.html in Bokeh server application packages.
Examples of this can be seen in:
Bokeh Docs: Embedding in Templates
{% extends base %}
{% block contents %}
<div>
<p> Hello {{ user_id }}, AKA '{{ last_name }}, {{ first_name }}'! </p>
</div>
{% endblock %}
Bokeh Server Application Examples
Example code from the Gapminder package in templates/index.html
{% extends base %}
{% block title %}Bokeh Gapminder Example{% endblock %}
{% block postamble %}
<style>
{% include 'styles.css' %}
</style>
{% endblock %}
What is this "base" that is being extended?
I see that there is a "contents" block, "title" block, and "postamble" block from the above examples.
How do I know what other jinja blocks I can modify?
Thanks.
Assume I am following the Your first Wagtail site tutorial, except I want to use a Streamfield, instead of separate RichTextField or BlogPageGalleryImage. For example :
class BlogPage(Page):
date = models.DateField("Post date")
intro = models.CharField(max_length=250)
body = RichTextField(blank=True)
... becomes ...
class BlogPage(Page):
body = StreamField([
('heading', blocks.CharBlock(classname="full title")),
('intro', blocks.RichTextBlock()),
('body', blocks.RichTextBlock()),
('image', ImageChooserBlock()),
], null=True, blank=True,)
How can I (or can I) pull the first image and the beginning of intro (...as I cannot restrict length) from a Streamfield for use in the blog_index_page.html template, and avoid using separate fields and BlogPageGalleryImage Class? Therefore replacing this template :
{% for post in blogpages %}
{% with post=post.specific %}
<h2>{{ post.title }}</h2>
{% with post.main_image as main_image %}
{% if main_image %}{% image main_image fill-160x100 %}{% endif %}
{% endwith %}
<p>{{ post.intro }}<p>
{% endwith %}
{% endfor %}
With something more like this :
{% for post in blogpages %}
{% with post=post.specific %}
<h2>{{ post.title }}</h2>
{{ post.body.image.first() }}
<p>{{ post.intro.get_words(50) }}</p>
{{ post.body|richtext }}
{% endwith %}
{% endfor %}
Many thanks.
{% extends 'base.html' %}
{% block content %}
<p>Welcome to home page.</p>
<p>{% user.groups.all() %}</p>
{% endblock %}
At the moment I'm trying to figure out how I could even get all the user's groups to show on the page. This results in an error.... Invalid block tag on line 5: 'user.groups.all()', expected 'endblock'. Did you forget to register or load this tag?
I have tried to do if statements, but it seems break as soon as it meets one condition. For example if user is a part of test1 and test2 groups, I'd like for it to display test1 and test2, but it only displays test1.
{% extends 'base.html' %}
{% block content %}
<p>Welcome to home page.</p>
{% if user.groups.all.0.name == "test1" %}
<p>test1</p>
{% if user.groups.all.0.name == "test2" %}
<p>test2</p>
{% endif %}
{% endblock %}
In the first code, you should have used {{ }} instead. In order to access groups, do this:
{{ user.groups.all }}
and to check for a specific group:
{% if desired_group in user.groups.all %}
some html..
{% endif %}
if you want to output specific html for each group:
{% for group in user.groups.all %}
{% if group == desired_group %}
some html..
{% endif %}
..some more conditions..
{% endfor %}
I'm trying to get and display some theme settings which gets the site name and applies to end which i have setup in the schema but cant get it to display the settings.
In the promo_header.liquid snippet file i have:
{% capture promo_header_text_1 %} locale_promo_1_text_{{ shop.name }} {% endcapture %}
{% capture promo_header_url_1 %} locale_promo_1_url_{{ shop.name }} {% endcapture %}
{% capture promo_header_text_2 %} locale_promo_2_text_{{ shop.name }} {% endcapture %}
{% capture promo_header_url_2 %} locale_promo_2_url_{{ shop.name }} {% endcapture %}
<p>
{% if settings[promo_header_text_1] %}
{{ settings[promo_header_text_1] }}
{% endif %}
{% if settings[promo_header_text_2] %}
<span>/</span>{{ settings[promo_header_text_2] }}
{% endif %}
</p>
I have also tried to output using just for example
{{ settings.promo_header_text_1 }}
But not displaying anything either... when i debug and display for example
{{ promo_header_text_1 }}
It does return
locale_promo_1_text_website-test2
Which is correct and in the schema settings file (example based on that one above it is matching and is set in theme customisation)
{
"type": "text",
"id": "locale_promo_1_text_website-test2",
"label": "Promo 1 Text",
"default": "FREE US SHIPPING OVER $35"
}
What am I doing wrong?
For anyone else that might come across the same issue here is the solution I got working:
{% assign promo_header_text_1 = 'locale_promo_1_text_' | append:shop.name %}
and to output
{{ settings[promo_header_text_1] }}
Is there a way to get ahold of a posts markdown in an include file?
My include file has this code: {{workingPost.content}}
When I include this in a markdown file I get the HTML. I pass that to another include that expects markdown and instead this is passing HTML.
Is there a way to access the markdown instead of the HTML for the post?
As requested here are the code files. What they do is get a featured post for the right hand side of the site like this. In that link the code is static HTML. I want to update it to make it dynamic via the following code. I already have the first image grabbing code working when it receives markdown. I'd like to use that code to grab the first image from the post here too, but by the time the code gets it the markdown has been turned into HTML.
Include file timely.html
{% assign workingPost = nil %}
{% for page in site.posts %}
{% if page.title == 'We Convert All Dollars To Bitcoin' %}
{% assign workingPost = page %}
{% endif %}
{% endfor %}
<div class="panel panel-default">
<div class="panel-heading text-center">
<h3 class="panel-title">Popular</h3>
</div>
<div class="panel-body">
<a href="{{workingPost.url}}">
{% assign workingPostContent = workingPost.content %}
{% include first-post-image-src2.html param=workingPostContent %}
<img src="{% include first-post-image-src2.html param=workingPostContent %}" alt="{{workingPost.title}}">
<p>{{workingPost.excerpt}}</p>
<p class="btn btn-md btn-success" role="button">READ POST</p>
<br>
<br>
</a>
</div>
</div>
include file first-post-image-src2.html
{% capture result %}
{% assign htmlAgain= 'empty' %}
{% assign foundImageAgain = 0 %}
{% assign imagesAgain = include.param | split:"![" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains '](' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:"](" %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:")" | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{%endcapture%}{{site.url}}{{htmlAgain|strip}}
Yes translating from markdown to html is one of the first thinks made when Jekyll build. So, no way to grab the markdown in an include. The only way to bypass this limitation is to do it with a plugin. But it's not the subject.
Now back to you code. It's to complicated and fragile.
Jekyll has all the needed functionalities to do what you want to do. Don't try to do data processing with liquid. Use the tags and filters and you will not have to fear a Gem upgrade that will break your site and bring you to a really difficult debugging.
eg : somewhere in your code, you're processing a string with a | split:"/>" filter that rely on how kramdown is rendering ìmg tag. If one day they decide to remove this useless closing slash, your code will break.
The way you can go : put all the datas in your post, in the simplest form possible, and then use them with simple Jekyll tags and filter.
The idea is to use yaml Front Matter custom variables and Jekyll post or page excerpt functionalities.
In your _config.yml, define a new excerpt separator :
excerpt_separator: "<!-- excerpt end -->" # default is "\n\n" = two new lines
In all your posts :
---
excerpt_image_src: "/images/dollarsToBitcoins.jpg"
excerpt_image_alt: "Bitcoin Bulls converts dollars to bitcoins."
popular : true # I'll explain that latter
---
Bitcoin Bulls customers pay in USD but those dollars are all converted to bitcoin.
<!-- excerpt end -->
Bulls, I'm excited to announce...
In default.html
{% if page.is_post %}
<link rel="alternate" type="application/atom+xml" title="{{ site.name }} — Atom" href="{{ site.url }}/blog/feed.atom" />
<meta property="og:image" content="{{ site.url }}{{ page.excerpt_image_src | strip_newlines }}" />
<meta property="og:description" content="{{page.excerpt}}" />
{% else %}
In _includes/timely.html :
<div class="panel panel-default">
<div class="panel-heading text-center">
<h3 class="panel-title">Popular</h3>
</div>
{% for p in site.posts %}{% if p.popular == true %}
<div class="panel-body">
<a href="{{p.url}}">
<img src="{{p.excerpt_image_src}}" alt="{{excerpt_image_alt}}">
<p>{{p.excerpt}}</p>
<p class="btn btn-md btn-success" role="button">READ POST</p><br><br>
</a>
</div>
{% endif %}{% endfor %}
</div>
Note the {% if p.popular == true %} that filter posts with a front matter variable popular: true.
In _includes/blog-post.html :
<li>
<a href="{{ post.url }}">
<p>{{post.date | date: "%B %d, %Y" }}</p>
<img src="{{post.excerpt_image_src}}" alt="{{post.excerpt_image_alt}}">
<!-- No need to wrap excerpt in <p> tag, Jekyll does it.
If you want to put your own tag :
<div>{{ post.excerpt | strip_html }}</div> -->
{{ post.excerpt }}
<p class="btn btn-md btn-success" role="button">READ POST</p><br><br>
</a>
</li>
In _layouts/post.html :
<h1>{{page.title}}</h1>
<div style="color:#666;">by David Smith on {{page.date | date: "%B %d, %Y" }}</div>
{% if page.excerpt_image_src %}
<p><img src="{{page.excerpt_image_src}}" alt="{{page.excerpt_image_alt}}"></p>
{% endif %}
{{ page.content | remove: page.excerpt | markdownify }}
<br>
As you're not actually displaying post excerpt in post page, it's {{ page.content | remove: page.excerpt | markdownify }}. If you want to display excerpt it's : {{ page.content | markdownify }}
I don't know why but page.content return mardown and not html, so the filter | markdownify to transform markdown to html.
Et voila ! Long live Bitcoinbulls !
The markdown isn't available. It is rendered earlier and not available.
From this answer it sounds like the markdown isn't available.
In my case I made my first-post-image-src2.html include handle the case where it gets markdown or HTML like this:
{% capture result %}
{% assign htmlAgain= 'empty' %}
{% assign foundImageAgain = 0 %}
{% if include.param contains '![' %}
{% assign imagesAgain = include.param | split:"![" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains '](' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:"](" %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:")" | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if foundImageAgain ==0 %}
{% assign imagesAgain = include.param | split:"<img" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains 'src="' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:'src="' %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:'"' | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{%endcapture%}{{site.url}}{{htmlAgain|strip}}