How to check whether the date is in the future? - jinja2

I need to display the information if the date given is in the future. Is there a way to do this in a template?
I found out I should compare them as timestamps but the following code gives me "jinja2.exceptions.UndefinedError: 'as_timestamp' is undefined".
{% if as_timestamp(bibjson.discontinued_date) <= as_timestamp(time.today) %}
<p>This date should be displayed only if in the past: {{ date.strftime("%d %B %Y") }}</p>
{% endif %}

It is very easy with custom filter https://docs.djangoproject.com/en/4.1/howto/custom-template-tags/
The filter file:
import datetime
from django.template import Library
register = Library()
#register.filter('date_in_the_past')
def date_in_the_past(date):
now = datetime.datetime.now()
return date <= now
and in the template:
{% load filter %}
{% if bibjson.discontinued_date|date_in_the_past %}
<p>This date should be displayed only if in the past: {{ bibjson.discontinued_date|date:'d F Y' }}</p>
{% endif %}

Related

How to show local time in html?

I have the Django project with the Model to save date_added information. Here's the Model code.
class Outputting(models.Model):
date_added = models.DateTimeField(auto_now_add=True)
And I want to retrieve such date_added information and demonstrate it as the local time in the html. How could I make the transformation? Here's the view.py and html template, but it still show the UTC time.
view.py
def results(request):
user = request.user
data = Outputting.objects.filter(owner=user).order_by('id').values_list('id','date_added')
return render(request, "xx.html", {"data": data})
Html:
<tr>
{% for i in data %}
<td style="word-wrap:break-word;"><div class="panel-body" type="datetime-local"><small>{{ i.1|date:'M d Y H:i:s' }}</small></div></td>
</tr class="something">
{% endfor %}
In your settings.py change the time zone location
TIME_ZONE = 'Africa/Abidjan'
if you don't know your location you can list all available time_zone options by running below command in the Django shell:
In [40]: import pytz
In [41]: pytz.all_timezones
Out[42]:
['Africa/Abidjan',
'Africa/Accra',
'Africa/Addis_Ababa',
...]
Reference: https://stackoverflow.com/a/13867319/7470786
EDIT:
For this, you should dynamically get the location of the user. After searching I came across with this answer which suggest using getTimeZoneOffset.
You have to enable USE_TZ = True in your settings.py if you not.
In order to have value in localtime in the template you can do:
{% load tz %}
{% localtime on %}
{{ value }}
{% endlocaltime %}
Also you can set specific timezone like:
{% load tz %}
{% timezone "Europe/Paris" %}
Paris time: {{ value }}
{% endtimezone %}
Or if you need one value to be converted you can do:
{% load tz %}
{{ value|localtime }}
You can read more in Django official docs.
If you want to store it in UTC and display it in the local time, then do this
{% load tz %}
{% timezone "Asia/Kolkata" %}
India time: {{ value }} #Add your respective time
{% endtimezone %}
{% timezone None %}
Server time: {{ value }}
{% endtimezone %}
This will return UTC if no time zone is given.
Note that - Conversion to local time is not always appropriate.
Also check out the warning inside Official Docs

Comparing dates in Jekyll

I'm trying to compare the current date with the date of the post in jekyll/liquid. If the current date is less than the date of the post, then I want to show the post title.
Here is my code so far:
<header class="announce-ticker">
<div class="container">
{% capture currentDate %}
{{ 'now' | date: '%s'}}
{% endcapture %}
{% assign eventCount = 0 %}
{% assign eventPosts = site.posts %}
{% for post in eventPosts %}
{% capture postDate %}
{{ post.date | date: '%s'}}
{% endcapture %}
{% if currentDate < postDate %}
{% post.title %}
{% assign eventCount = 1 %}
{% endif %}
{{ currentDate}}
{{ postDate }}
{% endfor %}
{% if eventCount == 0 %}
<p>No events</p>
{% endif %}
</div>
</header>
My problem is that it's not showing the post when it is greater than current date.
Any help would be appreciated. Thanks!
Future dated posts are not published by default. Basic way to enable them through command line is to use the future option:
jekyll serve --future
Alternatively, you can add the future parameter to your _config.yml:
future: true
More options in this article.

Posts by month in Jekyll

I am trying to create an archive page of posts from my website. What I would like is to be able to have a pages for each list of posts by month in this format:
www.mywebsite.com/2016/11 would display all posts for November 2016.
Can I have a page for each month I have posted that is dynamically created each time I post in a new month? I don't want to have to manually create a new page for each month.
I already can group posts by year like so:
<ul>
{% for post in site.posts %}
{% assign currentdate = post.date | date: "%Y" %}
{% if currentdate != date %}
<li id="y{{currentdate}}">{{ currentdate }}</li>
{% assign date = currentdate %}
{% endif %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
Thanks for any help.
You can modify your date filter to integrate the month, e.g. date: "%B %Y". That's what I used in a layout, with a separate <ul> for each month.
From documentation, month-only values for the date filter are:
%b: abbreviated month name.
%B: full month name.
%m: month of the year (01 - 12).
Complete loop:
<ul>
{% for post in site.posts %}
{% assign currentdate = post.date | date: "%B %Y" %}
{% if currentdate != date %}
<li id="y{{currentdate}}">{{ currentdate }}</li>
{% assign date = currentdate %}
{% endif %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
About generating the pages, AFAIK this can only be done through a plugin. If you can't use plugins, e.g. if you're hosting your pages on GitHub, the best you can do is to reduce your pages to a short YAML frontmatter relying on a layout, like in this answer.

Get Django User group in HTML

I am trying to get Django user's group in HTML for an if tag. This is what I tried:
{% ifequal user.groups.all.0 'ABC' %}
{% endif %}
But this is not working. What other way is there?
Try this:
{% for group in request.user.groups.all %}
{% if group.name == 'ABC' %}{% endif %}
{% endfor %}
Or
{% if request.user.groups.all.0.name == 'ABC' %}{% endif %}
You have to access the current user object from the request context variable. For this, make sure that django.template.context_processors.request is in your template settings.
request.user.groups.all.0 returns a Group model object, so you have to compare against the name field.
I think you will have to use a little Python here. For example, a custom template tag:
#register.filter(name='has_group')
def has_group(user, group_name):
return user.groups.filter(name=group_name).exists()
And in your template:
{% if request.user|has_group:"ABC" %}
...
{% endif %}
(Source: http://www.abidibo.net/blog/2014/05/22/check-if-user-belongs-group-django-templates/)
But maybe you should actually use permissions here.
https://docs.djangoproject.com/en/1.8/topics/auth/default/#authentication-data-in-templates
Edit: Here is a more complete example of the custom template tag:
settings.py:
INSTALLED_APPS = [
...
'yourapp',
...
]
Filesystem:
yourproject/
manage.py
yourproject/
settings.py
wsgi.py
...
yourapp/
__init__.py
templatetags/
__init__.py
yourapp_extras.py
...
yourapp_extras.py:
from django import template
register = template.Library()
#register.filter(name='has_group')
def has_group(user, group_name):
return user.groups.filter(name=group_name).exists()
Template:
{% load yourapp_extras %}
{% if request.user|has_group:"ABC" %}
...
{% endif %}
To get a more thorough understanding of this, I highly recommend reading Django's excellent documentation.
<h1>{{ user.groups.all.0 }}</h1>
{% if user.groups.all.0.name == 'Team2' %}
<h1>YES</h1>
{% else %}
<h1>NO</h1>
{% endif %}
Here, the user.groups.all.0 gives you the first group assigned to the user.
For eg. if the logged in user has groups assigned to him as- 'Team2', 'Programmer', 'Beginner'.
Then {{user.groups.all.0}} will print Team2.
I've used it to print and check the logged in user's group in html template.
OR
{% if request.user|has_group:"mygroup" %}
<h1>Has group mygroup</h1>
{% endif %}
Also works fine in django v1.11. This will check if the current user has 'mygroup' assigned to it or not.
However you'll need to add
from django import template
from django.contrib.auth.models import Group
register = template.Library()
#register.filter(name='has_group')
def has_group(user, group_name):
group = Group.objects.get(name=group_name)
return True if group in user.groups.all() else False
inside a group_check.py in below file structure
--app
|templates
|templatetags
|-- group_check.py

Show Only Future Posts in Jekyll

Is there a way I can create a loop in Jekyll that shows only posts starting today and into the future in chronological order? I'm making a GitHub Pages site for a meetup group and I'm kinda stuck.
This code below can do the trick:
{% assign curDate = site.time | date: '%s' %}
{% for post in site.posts %}
{% assign postStartDate = post.date | date: '%s' %}
{% if postStartDate >= curDate %}
Post datas here
{% endif %}
{% endfor %}
But you will need to "build" your site every day as Github only updates when there is a push to your repository.