How do I assign an ID to a div using Django? - python

I'm using mezzanine, based on the django framework of Python and I'm trying to add a method for my blog posts. In the models.py I have added an incremental counter to be used as an id reference.
`
def get_new_id():
n = 100
i = 1
for i in range(n):
if i ==100:
break
print (i) ##just checking if it actually did what I asked
return i
This way I want to be able to show the newest post on my homepage without having to change it manually.
I'd probably still need to reverse the count so the last blogpost becomes number 1, but regardless, the issue is not that.
I understand the code might already be too little for what I want it to do but even this simple loop does not print i in the console, let alone place itself into the meta tag. I have added the reference to the method in the correct html page (or so I believe)
from blog_post_list.html
{% for blog_post in blog_posts.object_list %}
<div id="{{ blog_post.get_new_id }}" class="post-preview">
<a href="{{ blog_post.get_absolute_url }}">
<h2 class="post-title">
{{ blog_post.title }}
</h2>
</a>
{% if settings.BLOG_USE_FEATURED_IMAGE and blog_post.featured_image %}
{% block blog_post_list_post_featured_image %}
<a href="{{ blog_post.get_absolute_url }}">
<img class="img-thumbnail" src="{{ MEDIA_URL }}{% thumbnail blog_post.featured_image 730 474 %}">
I am wondering if it is just the method that is poorly written or if I'm doing something else wrong entirely. If I can assign an ID to every blogpost I could use it anywhere on my website which would be awesome. I'm a novice still so I appreciate any help that you can muster. For the moment, when I run this code, the ID is NOT implemented in the html, rather the entire method is just ignored. the id meta tag of the div remains empty. However ,from the same page (blog_post_list.html) other methods are invoked and do work properly in the same fashion so the link is there.
Thanks in advance

If you would like to give an id to each item rendered in the for loop, and you would like your id to increment you can simply add a Django for loop counter. In that case this would give a unique id for each item.
{% for blog_post in blog_posts.object_list %}
<div id="{{ forloop.counter }}" class="post-preview">
<a href="{{ blog_post.get_absolute_url }}">
<h2 class="post-title">
{{ blog_post.title }}
</h2>
</a>
{% if settings.BLOG_USE_FEATURED_IMAGE and blog_post.featured_image %}
{% block blog_post_list_post_featured_image %}
<a href="{{ blog_post.get_absolute_url }}">
<img class="img-thumbnail" src="{{ MEDIA_URL }}{% thumbnail blog_post.featured_image 730 474 %}">
...
Also, FYI: if there are 101 items in your queryset and you give id=1 for the first one and 101st one, id will not be unique. In HTML you should give unique ids to elements.

Related

how to use integer value from for loop to get a list element in django template

I have a list of numbers in views.py list=[0,1,2,3,4,5] (it is not the same all the time I'm fetching it from API)
then in my search.html I have written the following code:-
{% for i in list %}
<a href="https://example.com//{{ id[i] }}">
<img class="row_poster" src="https://this.isapi.org/{{poster[i]}}" alt="" />
<h4>{{title[i]}}</h3>
</a>
{% endfor %}
where the id, poster, title are lists passed through views.py
I want to get elements of each list 1 by 1 I tried adding for loop for each but the result was bad all posters render first and then titles were rendering I want to know how can I use it to call items from the list or any other by which I can access elements for all lists in a single loop.
I have also tried {% with abcd=i %} but the result was the same keep getting this error
Could not parse the remainder: '[i]' from 'id[i]'
To achieve that, first create your own filter:
#register.filter
def get_index(lst, i):
return lst[i]
Which you can then use in your template like:
{% for i in list %}
<a href="https://example.com//{{ id|get_index:i }}">
<img class="row_poster" src="https://this.isapi.org/{{poster|get_index:i}}" alt="" />
<h4>{{title|get_index:i}}</h3>
</a>
{% endfor %}
For information on how to register custom tags look here.

How to access variables within html template url_for

I'm building a Netflix like website for my Devops course. I made a Python list of dictionaries (Mockfilms) to define my films, and want to populate a database (Ratings) with reviews in preparation for sending data in the format :filmid: :userid: :rating: to a recommendation engine.
My index page is a list of film images with a link to a review form under each one. I want each review form to appear on a different url (/review/ID where ID is saved in mockfilms as oid). In order to do this I want to access mockfilms.oid, then pass it to the view function to make the url for the form. Once the form is complete I then want to add this ID to the Ratings database. Here is what I have so far:
Index:
{% extends "base.html" %}
{% block content %}
<h1>Hello, {{ current_user.username }}! Welcome to our extensive video library:</h1>
{% for film in mockfilms %}
{% set ID = film.oid %}
<div>
<a href = {{ film.video }}>
<img src = {{ film.image }} alt = "doh" style = "width:200px;height:200px;border:0;">
</a>
</div>
<div>
">Leave a review here!
{% endfor %}
{% endblock %}
Route:
#app.route('/review/<ID>', methods = ['GET', 'POST'])
#login_required
def review(ID):
form = ReviewForm()
if form.validate_on_submit():
review = Ratings(User_id = current_user.id, Score_given = form.score.data, Film_id = ID)
db.session.add(review)
db.session.commit()
flash('Thanks for your review')
return redirect(url_for('index'))
return render_template('review.html', title='Review Page', form=form)
The following error is what I get when I run it:
File "/home/jc/Desktop/Lokal/DevopsAssig/microblog/Kilfinnan/lib/python3.5/site-packages/werkzeug/routing.py", line 1768, in build
raise BuildError(endpoint, values, method, self)
werkzeug.routing.BuildError: Could not build url for endpoint 'review'. Did you forget to specify values ['ID']?
From this I assume that the issue is with the ID variable within this template. My searchings and learnings led me to believe that {% set %} in the index template would let me declare the ID variable and then use it in the dynamic.
Try this:
{% block content %}
<h1>
Hello, {{ current_user.username }}!
Welcome to our extensive video library:
</h1>
{% for film in mockfilms %}
<div>
<a href="{{ film.video }}">
<img src="{{ film.image }}" alt="doh" style="width:200px;height:200px;border:0;" />
</a>
</div>
<div>
<a href="{{ url_for('review', ID=film.oid) }}">
Leave a review here!
</a>
</div>
{% endfor %}
{% endblock %}
Ultimately your solution was quite close, but it is not necessary to use the Jinja set command when you need to pass the variable into url_for() function using the keyword for the parameter. You could still do it using {% set ID = film.oid %} but it would be a bit superfluous.
Try to provide key=value arguments into your url_for function.
Something like this
">Leave a review here!
Also Flask have a great documentation, Flask docs

How To Print Descendants Of GAE NDB onto Jinja2?

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 %}

Introduction pages for categories in Pelican

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.

Complex comparisons on yesno filter?

I'm quite new at python/django.
I love django's templates, but there is one recurrent thing I cannot find
It's very common for me to have one conditional attribute on a (probably long) HTML tag. Most of the times that's an extra CSS class.
For example, let's say you have two links to switch languages, and you want to enable only one at a time. I find myself doing something like this:
{% get_language_info for LANGUAGE_CODE as l %}
<a href="/path/to/switch/to/spanish"
class="{% ifequal l.code "es" %} disable {% endifequal %}">
<img src="/spanish/flag/url" alt="Spanish">
</a>
<a href="/path/to/switch/to/english"
class="{% ifequal l.code "en" %} disable {% endifequal %}">
<img src="/english/flag/url" alt="English">
</a>
Other examples may be while rendering a list of items and checking for the "selected" one, etc.
On other languages I did this with a ternary operator, but I know that's considered "evil" on the python/django world :-)
I wonder if there's a way to leverage from the "yesno" filter. I've tried to do something like:
{{l.code=="es"|yesno:"disabled,"}}
But I couldn't get it to work... am I missing something?
Thanks in advance.
The problem is simply with your syntax in the code you posted:
{{l.code=="es"|yesno:"disabled,"}}
It's actually processed like:
{{ l.code=={{"es"|yesno:"disabled,"}} }}
(Note: that code doesn't work, it's just meant to illustrate how Django reads it)
What you want is a custom template tag that works like the if templatetag but returns like the yesno filter. You could search around on something like djangosnippets.com; maybe someone has already done the work for you. Otherwise, I'd suggest looking at the Django source code for those two and try to merge them into your own templatetag.
Or you could use jQuery/javascript to set the class:
http://api.jquery.com/attr/
something like this - not tested!
{% get_language_info for LANGUAGE_CODE as l %}
<script>
{% if l.code='es' %}
$('.english').attr('class','disable');
{% else %}
$('.english').attr('class','disable');
{% endif %}
</script>
<a href="/path/to/switch/to/spanish"
id="spanish" class='enable">
<img src="/spanish/flag/url" alt="Spanish" >
</a>
<a href="/path/to/switch/to/english"
id="english" class='enable">
<img src="/english/flag/url" alt="English">
</a>

Categories

Resources