Conditionally add data-attributes in Jekyll - if-statement

My basic YAML Front Matter for blog posts looks as:
layout: post
title: 'Crepes'
permalink: /crepes/
src: '/assets/images/crepes.jpg'
date: 2018-05-24 21:41:00
origin: http//...
ingredients:
- ingredient1: amount
- ingredient2: amount
Here is my index.html to display entries:
<ul>
{% for post in site.posts %}
<li data-title='{{ post.title }}' data-origin="{{ post.origin }}"
data-src="{{ post.src | prepend: relative_url}}"
data-content='{ "ingredients": {{ post.ingredients | jsonify }} }'>
<a href="{{ site.baseurl }}{{ post.url }}">
<img src="{{ post.src | prepend: relative_url }}" alt={{ post.title }}/>
</a>
</li>
{% endfor %}
</ul>
The problem is:
Some posts are supposed to have no origin value, like origin:. And I am looking for a way to add data-origin attribute only if it's value specified in YAML Front Matter.
Liquid give following option:
{% if condition %}
<li>....</li>
{% endif %}
Is there any way to use it inside of html tag? In my case I expect something like this:
{% for post in site.posts %}
<li
{% if post.origin has value %}
data-origin="{{ post.origin }}"
{% endif %}">
</li>
{% endfor %}

Here I see four cases :
post.origin is not present in front matter :
post.origin == null
post.origin is present in front matter, but not set (post.origin:)
=> post.origin == null`
post.origin is present in front matter, but set to empty string (post.origin: "")
=> post.origin == ""
post.origin is present in front matter, and set to valid string (post.origin: "toto")
=> post.origin == "toto"
Results are conform to Truthy and falsy Liquid documentation.
From there, using logical liquid operators, we can build a condition like :
<li
{% if post.origin and post.origin != "" %}
data-origin="{{ post.origin }}"{% endif %}>
</li>
Note that post.origin means post.origin != null.

Related

How to mix Pug/Jade with Django conditionals and html element attributes?

I want to write Django conditionals for html attributes, like
<a {% if item.link %} href="{{ item.link }}", target="_blank", rel="noopener", aria-label="{{ item }}" {% endif %}>
--- Content ---
</a>
I am using pug/jade, so I can't put jade/pug syntax inside "Content" block, the compiler breaks. I would like to know if I can handle that in any way to no repeat the "Content" block.
I tried also, withouth success:
a({% if item.link %} href="{{ item.link }}", target="_blank", rel="noopener", aria-label="{{ item }}" {% endif %})
----Content---
I finally found a way to achieve this. Incredibly the solution is very simple and I felt a little dumb when I found it:
<a {% if item.link %} href="{{ item.link }}", target="_blank", rel="noopener", aria-label="{{ item }}" {% endif %}>
--- Content ---
</a>
Just need to put the --- Content --- block in the same indentation level as the plain html content.

Unable to correctly parse URLs using Django template language

I currently am trying to link a researcher's name if they provided a link, otherwise if they provide a blank input or N/A, then I choose not to link their name. I use the information from the researcher object using Django's template language, but when I check the result it ends up linking all of them, and those without input just have href = "" which links back to the homepage.
I've tried using {{r.website_link|length}} instead, but that just creates errors and the page won't load. I'm a newbie to frontend so I'm not sure if my "if" statement is incorrect or if my HTML logic is incorrect.
<div>
{% for r in researcher %}
<div class="researcher">
{% if "{{r.website_link}}" != "N/A" and "{{r.website_link}}" != "" %}
<p><a class="researcherwebname" href="{{ r.website_link }}">{{ r.fullname|title}}</a> | {{ r.institution }} | {{r.position}} | <i>{{ r.des|capfirst }}</i></p>
{% else %}
<p> {{ r.fullname|title}} | {{ r.institution }} | {{r.position}} | <i>{{ r.des|capfirst }}</i></p>
{% endif %}
</div>
{% endfor %}
</div>
I expect it to link researchers with an actual r.website_link input, otherwise the name should be unlinked.
please try
{% if r.website_link %}
{% if r.website_link != "N/A" %}
{# display researcher #}
{% endif %}
{% endif %}

why is this django template elif not working

I can't figure out why this simple if ... else ... endif is not working. The two variables being compared in the if are equal in the page output so the if should not trigger but it does. Any help is appreciated.
{% if view.get_player_id != user.id %}
<h1>'{{ view.get_player_id }}' '{{ user.id }}' Only {{ view.get_player_name }} can edit this page</h1>
{% else %}
...
{% endif %}
And this is the page output:
'4' '4' Only Leo Messi can edit this page

combine number of database requests using ORM

I am working on a website, where a user can vote and comment on different projects in various categories. Whenever a user returns to the site, their votes will be highlighted and all the comments will be visible.
The problem is that every time the page is loaded there are many database calls due to the design of my models or due to me not finding an efficient way of retrieving the data.
My models are as follows:
class ProjectCategory:
title=models.CharField(...)
class Project:
category=models.ForeignKey(ProjectCategory)
title=models.CharField(...)
def ownedComments(self):
return Comment.objects.filter(project=self).order_by('-submissionTime')
def ownedCommentsPreview(self):
return Comment.objects.filter(project=self).order_by('-submissionTime')[0:3]
def ownedVotes(self):
return Vote.objects.filter(project=self,upVoted=True).count()
class Vote:
project=models.ForeignKey(Project)
user=models.ForeignKey(User)
vote=models.IntegerField(...)
class Comment:
project=models.ForeignKey(Project)
user=models.ForeignKey(User)
title=models.CharField(...)
Here are relevant parts of my views.py:
def getCurrentUserData(request=None):
if (request==None) or (request.user.is_authenticated()==False):
return {'loggedInUsername':'Anonym','userIsLoggedIn':False}
return {'loggedInUsername':request.user.username,'userIsLoggedIn':True}
def getProjectResponse(request,surveyFile=None,additionalInfo={}):
userVotedUp=[]
if surveyFile!=None:
userVotes=Vote.objects.filter(upVoted=True,surveyFile=surveyFile)
for vote in userVotes:
userVotedUp.append(vote.project.id)
answerDict={'userVotedUp':userVotedUp,'prjCategories':PrjCategory.objects.select_related(),'projects': Project.objects.prefetch_related('category').filter(visible=True),'spammerquestion':spammerquestion.SpammerQuestion().getRandomQuestion(),'rotatingLines':helpers.getRandomRotatingLines(),'backgroundimageurl':helpers.getBackgroundImageUrl()}
answerDict.update(getCurrentUserData(request))
answerDict.update(additionalInfo)
return answerDict
def showProject(request,prjNo):
currentPrj=get_object_or_404(Project,prjNo=prjNo,visible=True)
surveyFile=assignSurveyFile(request,create_surveyFile_if_not_existing=False)
return render_to_response('website/singleproject.html', getProjectResponse(request,surveyFile,{'currentPrj':currentPrj,'immediateProjectID':currentPrj.id}),context_instance=RequestContext(request))
The template contains many iterations over projects and categories, there might be several database calls happening here. Relevant parts of the template are:
{% for project in projects %}
self.vote['{{ project.id }}']=ko.observable(new Vote({'totalVoteNumber':ko.observable({{ project.ownedVotes }}),'userVoteState':ko.observable({% if project.id in userVotedUp %}true{% else %}false{% endif %})}));
self.comments['{{ project.id }}']=ko.observableArray([]);
{% for comment in project.ownedCommentsPreview %}
self.comments['{{ project.id }}'].push(new Comment({'description':'{{ comment.description|striptags|safe }}','submissionTime':'{{ comment.submissionTime|humanDT }}','commentUuid':'{{ comment.commentUuid }}','deletable':false}));
{% endfor %}
{% endfor %}
{% for prjCat in prjCategories %}
.prjCatUnderline{{ prjCat.id }} {border-bottom: 0px solid {{ prjCat.color }};}
.prjCatUnderline{{ prjCat.id }}:hover {border-bottom: 3px solid {{ prjCat.color }};}
{% endfor %}
{% for prjCat in prjCategories %}
{{ prjCat.title }}
{% if not forloop.last %}<span class="catpipe">|</span>{% endif %}
{% endfor %}
<script type="text/javascript">
var projectLocations = [{% for project in projects %}{% if project.location != '' %}['{{ project.title }}', {{ project.location }}, {{ project.id }}, '{{ MEDIA_URL }}{{ project.mapImage }}', {{ project.mapImage.width }}, {{ project.mapImage.height }}, '{{ project.id }}'],
{% endif %}{% endfor %}];
</script>
{% for project in projects %}
<div class="item prjCat{{ project.category.id }}">
<div class="prjnumberbox">
<div class="numberbar" style="background-color:{{ project.category.color }}"></div>
<div class="prjnumber">{{ project.prjNo|stringformat:"02d" }}</div>
<div class="numberbar" style="background-color: {{ project.category.color }}"></div>
</div>
<div class="prjheadline"><span>{{ project.title }}</span></div>
<div class="prjimagecontainer">
<!-- ko with: $root.vote['{{ project.id }}'] -->
<div class="prjimageoverlay"><a data-bind="click: function(data,event) { $root.showSingleProjectData('{{ project.id }}',data) },css : { imgVoted :userVoteState }" class="singleProjectOverlay" href="{% url 'website.views.showProject' prjNo=project.prjNo %}"></a></div>
<div class="prjimage"><img src="{{ MEDIA_URL }}{{ project.teaserImage }}" /></div>
<!-- /ko -->
</div>
<div class="prjtextcontainer" {% if project.ownedComments|length_is:"0" %}style="background-image:none;"{% endif %}>
<div class="prjtext">{{ project.teaserText|safe }} <a class="singleProjectOverlay" data-bind="click: function(data,event) { showSingleProjectData('{{ project.id }}',data) }" href="{% url 'website.views.showProject' prjNo=project.prjNo %}">mehr >></a></div>
<div class="votesline"><span class="voteslinefont" data-bind="with: vote['{{ project.id }}']"> <span class="votecount" data-bind="text: totalVoteNumber">{{ project.ownedVotes }}</span> votes </span></div>
<div class="prjcomments nojs">
{% for comment in project.ownedCommentsPreview|slice:":4" %}
<div class="prjcommentitem">
{{ comment.teaserdescription }}
</div>
{% endfor %}
</div>
<div class="prjcomments" data-bind="foreach: comments['{{ project.id }}'], visible: comments['{{ project.id }}']().length > 0">
<!-- ko if: $index() < 4 -->
<div class="prjcommentitem">
<em data-bind="text: submissionTime"> </em><br/>
<span data-bind="text: description"> </span>
[X]
</div>
<!-- /ko -->
</div>
</div>
</div>
{% endfor %}
For the front page I'd like to retrieve all the projects, most recent three comments, the total number of votes for a project and the comments and votes by the user.
It would be great if that was possible with one db call, or with two, a general one to get the number of votes and the comments, and one for the data specific to the user.
CUrrently I am retrieving all the projects with one call, so I am automatically getting all the project categories. Then I get all the comments at once and assign them to the projects in python. I then get the comments and votes for a certain user with one call each.
Is there a way - without using sql directly - to get
comments and votes for a user with a single database call
comments, projects, accumulated number of votes per project and project categories at once?
One idea would be to download the whole database using select_related() and then sorting everything out in Python, but if in the future I have a large number of votes or comments, this might not be a good idea.

Flask: current page in request variable

In a template, how do I get what page I'm currently on? I'd rather not pass a variable like page , especially when I know some request.xxx can provide me with the information.
<li {% if page=="home" %}class="active"{% endif %}>
Home
</li>
<li {% if page=="about" %}class="active"{% endif %}>
About
</li>
As long as you've imported request, request.path should contain this information.
Using request.path doesn't seem to be a proper approach since you'll have to update the paths in case of changing URL rules or deploying your site under a subfolder.
Use request.url_rule.endpoint instead, it contains actual endpoint name independent of actual path:
(Pdb) request.url_rule.endpoint
'myblueprint.client_pipeline'
In a template:
<li {% if request.url_rule.endpoint == "myblueprint.client_pipeline" %}class="active"{% endif %}>Home</li>
Good luck!
First import request from flask in your application. Then you can use it without passing to template:
<li {%- if request.path == "/home" %} class="active"{% endif %}>
Home
</li>
<li {%- if request.path=="/about" %} class="active"{% endif %}>
About
</li>
To avoid using hard-coded URLs you can use the url_for function like this:
{% for ni in ['index', 'foo', 'bar', 'baz'] %}
<li {%- if request.path == url_for(ni) %} class="active"{% endif %}>{{ ni | capitalize }}</li>
{% endfor %}
In this case index, foo, bar and baz would be function names, used like this in your python code:
#app.route('/')
def index():
Try
<li {% if request.endpoint == "blueprintname.routename" %}class="active"{% endif %}>Home</li>
This one worked for me.
You can also use .split if your url has more stuff in it.
Example:
/product
/product/add
/product/32432/edit
/product/32432/view
{{ request.path.split('/')[1] }}
This will return only "product"