jinja2 get whole context in single object within template - jinja2

For example, I have template index.html and custom_jinja2_filter
<h1> My name is {{ name }} </h1>
<h2> I'm {{ year }} years old </h2>
<p> I'd like to pass template context to custom
filter like single object. Is it possible?
{{ ??? | custom_jinja2_filter }}
</p>
def custom_jinja2_filter(context):
name = context['name']
year = context['year']

You can pass the current context to a function marked as callable with #contextfunction:
from jinja2 import contextfunction
#contextfunction
def custom_jinja2_filter(context):
name = context.name
year = context.year
return '(c) {} {}'.format(year, name)

Related

Django How to make the condition correct on an HTML page - search bar

I try to do a search engine if the word in my DB thah I created then display the word on the HTML page and if not then nothing.. I did it right in VIEW but I can not apply it on the HTML page I searched the internet and did not find an answer I'm sure I fall for something stupid.
This is the view
def Search_word(request):
search = request.POST.get("search") #Grab the search item
return render(request,"search_page.html", {"search":search})
this is the html:
{%for i in Word.English_word%}
{%if search in Word.English_word%}
{{search}}
{%endif%}
{%endfor%}
and the urls:
path("Search_page",views.Search_word ,name="Search-page"),
models:
class Words(models.Model):
English_word = models.CharField(max_length=30)
Hebrew_word = models.CharField(max_length=30)
How_To_Remember = models.CharField(max_length=40)
Name = models.CharField(max_length=20)
pub_date = models.DateTimeField()
The problem is that even if the word is valid it does not show me anything ..
You should implement the filtering logic in the view, not in the template. Templates are for rendering logic, not business logic. Furthermore one should filter with the database, since databases are designed to do this.
The view thus looks like:
def Search_word(request):
search = request.POST.get('search')
items = Word.objects.filter(English_word__contains=search)
return render(
request,
'search_page.html',
{'search': search, 'items': items}
)
and then in the template we render this with:
{% for item in items %}
{{ item.English_word }}: {{ item.Hebrew_word }} <br>
{% endfor %}
You can use as lookup __contains to check if the English_word has a substring that is equal to search, with __icontains you check case-insensitive, with __iexact you look for Words that match search case-insensitive, and finally you can filter with Engish_word=search for an exact match.

DJANGO template tags in plain text not displaying

I am making an app that displays questions. The question model has a text field and an image field. Each question has a template that is stored in my database in the text field. My problem is when I want to access images from the model, template tags are displayed as text and not rendering. My code:
# question model
class Question(models.Model):
question_text = models.TextField()
question_image = models.FileField(upload_to='static/images/questions', blank=true)
# question view
def question(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'questiontemplate.html', {'question': question})
# template
{% extends 'base.html %}
{% load static %}
{% autoscape off %}
{{ question.question_text }}
{% endautoscape %}
# in my database:
question.question_text = '<p> some html
{{ question.question_image.url }}
some html </p>'
question.question_image = 'image.png'
This works fine and renders the html perfectly except the template tag is not rendered and does not not give the image url
I want this to be the output:
Some html
static/images/questions/image.png
some html
But instead this is the output:
some html
{{ question.question_image.url }}
some html
Any suggestions to how the template tags could be render from the database text would be much appreciated.
Thanks for reading
Django doesn't know that the content in your model field is itself a model. The template can't know that. The only way to make this work is to treat that field itself as a template, and render it manually.
You could do that with a method on the model:
from django.template import Template, Context
class Question(models.Model):
...
def render_question(self):
template = Template(self.question_text)
context = Context({'question': self})
rendered = template.render(context)
return mark_safe(rendered)
Now you can call it in your template:
{{ question.render_question }}

Jekyll Liquid Array ID Not Working

I have a CSV file in my _data folder and I am trying to specify the row of the CSV to access in my Front Matter and then return specific columns from the CSV based on the row specificed in the Front Matter.
Here's the CSV file:
name,description
Dallas,Big City in Texas
And here's the contents of my index.html file:
---
city: "Dallas"
---
{{ site.data.data[page.city].description }}
Per the Jekyll Docs page on using data files, I should be able to use this syntax to access data files in this way, but the compiled html file does not include any data.
I have tested other ways of accessing the contents of the CSV file and those work, so it doesn't appear to be a problem with the data file or the site itself but rather with using the [ ] array id Liquid syntax.
Looks like you have misunderstood the [] notation for a hash structure.
I will first orient you on how the [] is supposed to work..
Expanding your data.csv a bit:
name,description
Dallas,Big City in Texas
Houston,Another City in Texas
and "inspecting" your the data object obtained from the above CSV file,
{{ site.data.data | inspect }}
on building the site, you'll see that the resultant object is simply an Array of Hashes :
<p>
[
{"name"=>"Dallas", "description"=>"Big City in Texas"},
{"name"=>"Houston", "description"=>"Another City in Texas"}
]
</p>
which means you can only access individual hash entry by referencing its index number.
i.e. {{ site.data.data[0] }} will give you the first hash and {{ site.data.data[1] }} will give you the next hash.
and therefore {{ site.data.data[0].description }} will give you the result you expect to get:
<p>
Big City in Texas
</p>
Now that you know how [] works for data hashes, lets simply get to the solution.
To access elements in an Array, one can simply iterate through the Array objects and reference necessary entries:
{% for entry in site.data.data %}
<div>
<span>{{ entry.name }}</span> : <span>{{ entry.description }}</span>
</div>
{% endfor %}
will give you:
<div>
<span>Dallas</span>
<span>Big City in Texas</span>
</div>
<div>
<span>Houston</span>
<span>Another City in Texas</span>
</div>

Display time stored in database in HTML (django)

I'm building a bus booking website using Django. Users fill From, To, Bus type(ordinary or Volvo) and date. Results display the buses available on that route on that particular date. I made three tables - Bus, Route, and Frequency. You can check my models.py and views.py here - https://dpaste.de/Oi6a I convert the date to the corresponding day of the week. I have filtered out the buses, However, I want to display time on the template. This is part of my views.py code:
def select(request):
bus_type = request.GET.get('bus_type')
bus_from = request.GET.get('bus_from')
bus_to = request.GET.get('bus_to')
date_string = request.GET.get('date')
date = datetime.strptime(date_string, '%Y-%m-%d')
day = calendar.day_name[date.weekday()]
kwargs = { '{0}__range'.format(day): ["00:00:00", "23:59:59"],}
qs = Frequency.objects.filter(bus__type_of_bus=bus_type, bus__route__location_from=bus_from, bus__route__location_to=bus_to, **kwargs)
context = {'qs': qs, 'date':date_string,}
template = 'select.html'
return render(request, template, context)
As you can see qs filters the buses available and is then passed to the template. This is a part of the template:
<div id="pricing-table" class="clear">
{% for info in qs %}
<div class="price_block">
<h3>{{ info.bus.type_of_bus }}<span>{% if info.bus.type_of_bus == 'Volvo' %} Rs 550 {% else %}Rs 330 {% endif %}</span></h3>
Book
<ul>
<li><b>Bus Number -</b> {{ info.bus.bus_number }}</li>
<li><b>Route -</b> {{ info.bus.route }}</li>
<li><b>Date -</b> {{ date }}</li>
<li><b>Time -</b> {{ info.day }}</li>
</ul>
</div>
In the last line of this HTML file, I have added info.day. What I want is that this displays the time that bus operates on the given day. For example, If a person searches a bus on 29th April. 29th April will be converted to corresponding day i.e. Friday. The frequency table has 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' and 'Sunday' as attributes and these all are TimeField(). qs filters the buses and passes to the template. I want {{ info.day }} to show the time when the bus operates. Instead, it shows nothing. But when I change {{ info.day }} to {{ info.Friday}} it start showing the time. How can I display the time without having to manually go and change the day in {{ info.(here) }} every time I search for a bus. I didn't make it very clear, but I hope you understand. Let me know if you don't.
You can create a custom template tag do this for you and a method on the model.
I haven't tested this code, but this should work with or without small adjustments
Add this method to the Frequency model:
def get_day_info(self, date):
# Where date_string would be a datestring
date = datetime.strptime(date_string, '%Y-%m-%d')
day = calendar.day_name[date.weekday()]
info_time = getattr(self, '{}'.format(day))
return info_time
And register this as a template tag.
#register.simple_tag
def get_day_info(info, date):
return info.get_day_info(date)
You would call it in the template like this:
<li><b>Time -</b> {% get_day_info info {{ date }} %}</li>

Working with links in Django

I am working in a small blog application using Django. Sorry if the question is obvious, but I am a newbie. Actually it is my third since I started an online course. I have the following Queryset:
def all(request):
allTiles = Post.objects.values('title')
allPosts = Post.objects.all()[:3]
context = {'Posts': allPosts,"Titles":allTiles}
template = "home.html"
return render(request, template, context)
and the follwing html code:
<ol class="list-unstyled">
{% for singleTile in Titles %}
<li>{{singleTile.title}}</li>
{% endfor %}
</ol>
As you can see every title creates an link. Lets assume a person decides to read one of the posts. How can I use the title name and send a request back to the database to get the content of the post.
It is better to use the id or slug field for such task.
But if you surely want to use the title as the GET parameter then apply the urlencode filter to the field's value:
<a href="{% url 'post_detail' %}?title={{ singleTile.title|urlencode }}">
{{ singleTile.title }}
</a>
And the view will be something like this:
def post_detail(request):
post = get_object_or_404(Post, title=request.GET.get('title'))
return render(request, 'post_detail.html', {'post': post})
UPDATE: If you decide to go with the id/slug option then you can use the generic DetailView:
<a href="{% url 'post_detail' singleTile.id %}">
{{ singleTile.title }}
</a
urls.py:
from django.views.generic.detail import DetailView
from app.models import Post
url(r'^post/(?P<pk>\d+)/$', DetailView.as_view(model=Post),
name='post_detail')
You have to configure url first like
{% url 'app.views.post_id' singleTile.id %}</li>
In your urls
url(r'^post/(?P<post_id>\d+)/$', views.by_id, name='post_id'),
And in your views
def post_id(request, post_id):
allTiles = Post.objects.get(id=post_id)
return render(request, template, context)