jinja UndefinedError: 'unicode object' has no attribute 'length' [duplicate] - python

Currently I'm using jinja2 with flask and have stored a blog post using ckeditor in the database.
The data should ideally show an image first and then following the blog posts and some other images which are linked externally to flikr.
I know that I can use the {{ post.body | safe}} inside the single post view of to display the html as a real image instead of html text.
However, how do I NOT show the html but show only the text excerpt in the post in the page where there are multiple links to different prosts and excerpts without the image html showing up.
In this case "This post is dedicated to xyz" should be the excerpt
database body = column
<img alt="15189057555_7670752b57_o" class="main" src="https://farm6.staticflickr.com/5584/15189057555_7670752b57_o.jpg" style="width:100%;max-width:1920px"><p>This post is dedicated to xyz</p>
jinja2
'post' is an post object. I'm trying to limit the excerpt to 100 letters long without the html tags and images.
{{post.body[:100]}}... will show <img alt="15189057555_7670752b57_o" class="main" src="https://farm6.staticflickr.com/5584/1518905755...
The following is a code excerpt to loop through all posts to provide a link to a single blog page, a time stamp, and an excerpt of what the blog is about.
<h1>Latest Posts</h1>
{% if posts %}
{% for post in posts%}
<div class="post">
<h2>{{post.title}}</h2>
<h6>{{post.timestamp.strftime('%a %y/%m/%d')}}</h6>
<p>{{post.body[:100]}}...</p>
<p>Posted By: {{post.author.nickname}}</p>
</div>
{% endfor %}
{% else %}
<h4>No blog posts currently</h4>
{% endif%}
Is there a better way to design this? If so, how? Please keep in mind I would like to be able to insert multiple images and text in the one blog post.
Thanks for all your help!

You have to look at the striptags and truncate filter of Jinja http://jinja.pocoo.org/docs/dev/templates/#builtin-filters
Example:
>>> from jinja2 import Template
>>> template = Template('blogpost: {{ post|striptags }}!')
>>> template.render(post='<img alt="15189057555_7670752b57_o" class="main" src="https://farm6.staticflickr.com/5584/15189057555_7670752b57_o.jpg" style="width:100%;max-width:1920px"><p>This post is dedicated to xyz</p>')
u'blogpost: This post is dedicated to xyz!'
In your case, you want to strip tags, and limit to 100 chars, so replace
<p>{{post.body[:100]}}...</p>
by
<p>{{post.body|striptags|truncate(100)}}</p>

Related

How to load image from backend (SQL textfield ) directly by using Django?

I am trying to make a blogging website. I know django provides argument templates like
{% include images.html with value=sense %}
The above code directly works in HTML and hence everything works. The images are stored in a backend database and connected to everystory by some logic. The user can use the names of the images and call whenever they need to use it
When I try the above code directly in the backend it doesn't work because I think once something is rendered then it doesn't rerender by django HTML
I wish to paste some form of links in the django story backend. such that when it renders in HTML automatically the page should show pics in the appropriate place. If anyone has any idea how to do this kindly let me know.
So when loading stories in the database the user can put some form of links for images in the database and while rendering all images come in a certain format as specified in the block in the blog.So there can be any number of images and the count is not longer fixed as shown in the pics below where I am trying to render a image called sense from the backend which doesn't work.. whereas it directly works in the frontend.
<p>{{object.story_title}}</p>
<p>{{MEDIA_ROOT}}</p>
<p>{{object.story}}</p>
{% include "blogdescription/image.html" with value=sense %}
Thank you for your time.
with regards
Let me start saying that doing exactly what you want is not possible because Jinja will compile and render {{object.story}} and not its content (the include). It does not seem possible to use nested Jinja syntax to load any resources, includes, extends, urls, etc.
Which explains why when you place the include in the template it works but does not inside your model field.
What seems possible is to load an HTML image with a explicit URL to the resource, lets say, the content inside your text field is:
<div style="display: flex; justify-content: center; align-items: center;">
<img src="/static/myimage.jpg" alt="Object Image">
</div>
Template.html (source):
{% block content %}
{{obj.title}}
<br>
{{obj.body|safe}}
{% endblock %}
Alternatively, it is possible to generate a HTML file to render dynamically based on Object.field. Note that this solution is a heavy load on the server, for every request will generate a dynamic file to be rendered.
Obj field value:
{% extends 'base.html' %}
{% block content %}
{{obj.title}}
<hr>
{% include 'includes/image.html' %}
{% endblock %}
views.py:
def story(request, id):
obj = Story.objects.get(id=id)
f = open(f'templates/generated/dynamic_template.html', 'w+')
f.write(obj.body)
f.seek(0)
return render(request, 'generated/dynamic_file.html', {'obj': obj})

How to append specific html to a Django code block using only Python/Django?

I have a form I'm working with in Django.
I have a built in error message I'm trying to get to render on the form.
My first step is to get the error message to render on the form and then I will go into the function and tweak when it shows up.
My problem emerges when it comes to doing it in python.
Normally, my preferred way would be to JQuery for the footer and use JavaScript to append/prepend the HTML. Then set it to show/hide based on conditionals.
However, for this I am wanting to do it in Python to make it easier for the people working w/ me.
Here's an example of the error message HTML I would like to use for appending to something else in JS.
error_field.append('<em for="name" class="form-error-message text-danger">');
Here is an example of the Django Code Block I would like to add it within
{% block form-footer %}
{{ block.super }}
{% endblock %}
What is the easiest way to accomplish this within Python/Django? To be clear, I can figure out the conditional stuff myself. Just the rendering of the specific HTML/CSS error class I have already created. I should be able to do the conditional/function part of this myself.
I can just show you an example, this is a part of my project
views.py
try:
user=User.objects.get(username=username)
except:
messages.info(request,'username does not exist')
return redirect('login')
return render(request,'users/login-register.html')
html
{% if messages %}
{% for i in messages %}
<div class="alert alert--{{i.tags}}">
<p class="alert__message">{{i}}</p>
<button class="alert__close">x</button>
</div>
{% endfor %}
{% endif %}
You can use this anywhere in your html page. This is a common page, and everything in here is extended. And of course this is an example similar to your problem. Check it out if you want

Django - Creating an if statement based on the request path : not working

I'm trying to create a div within my view that should only be generated if both the words 'org' and 'dashboard' are in the page URL. I've looked at other similar questions on SO but they the solutions don't seem to work for me.
I have also tried putting the phrases org and dashboard within quotation marks which will actually display the div on the page; however this will be displayed on the page regardless of whether those phrases are in the page URL.
HTML:
{% if org and dashboard in request.path %}
<div id='url-req-brn'>
<div class='max margins'>
<h4 id='url-req-brn-h4'>You must be logged in to view the requested page.<h4>
</div>
</div>
{% endif %}
Thanks
Update:
Current solutions provide clarity as to the mistake I made in the HTML, however the div still doesn't display when I have a URL containing 'org' and 'dashboard'.
Do I have to define what 'request.path' means in my views.py file?
You'll have to quote org and dashboard as strings, and then test their containment separately:
{% if 'org' in request.path and 'dashboard' in request.path %}
The syntax follows that of plain Python.
Reference
Template complex expressions

Creating a "Recent Posts" list in a sidebar.

I'm working on a simple blog app in Django, and i'm having trouble figuring out how to dynamically generate the five most recent posts in a side bar. Each of my views are class based and they extend a generic template, each view maps to one template which I believe is the correct way to do it. I've looked for a way to do this using template tags, but it seems Django doesn't like you to put any logic inside of your templates.
The problem I believe is that I want this to exist within my base.html because I want the recent posts to be displayed site-wide, is a view even supposed to map to your base.html or does that cause problems, i'm pretty new with this. I don't know how to approach this, whether i'm supposed to create a new view for base.html or if I should use my template tags, or if I should extend an existing view(but if I do that it won't be site wide?).
I essentially want the following(they're ordered in reverse chronological order)
{% for post in post_list[:4] %}
{{ post.title }}
{% endfor %}
You can use a template tag. More specifically, an inclusion tag is what you need. This allows you to insert a rendered snippet anywhere inside your template via a small view-like piece of code.
For example, create a templatetags/blog_tags.py file (it's important that you create the templatetags folder within your app; Django searches for them here by default) in your blog app and add the following:
from django import template
register = template.Library()
#register.inclusion_tag('blog/snippets/recent_posts.html')
def render_recent_blogposts():
return {
# This is just an example query, your actual models may vary
'post_list': BlogPost.objects.all().order_by("published_on")[:4]
}
now create a blog/snippets/recent_posts.html template (it can be anywhere as long as it mathecs the #register.inclusion_tag(...) above.):
<ul>
{% for post in post_list %}
<li> {{ post.title }}</li>
...
{% endfor %}
</ul>
finally, in your original template, you can now render your template tags:
<aside>
{% load blog_tags %}
{% render_recent_blogposts %}
</aside>

'Anchoring' in Django templates

I'm trying to build a simple blog with Django, and now i'm stuck on something thats probably really easy to fix.
In one of my views, i'm loading all of the blogposts sorted chronologically, nothing strange there.
Now i'd like to load that page, and add an anchor-point to each post, so that they are indivudually reachable.
template:
{% for post in allPosts %}
<div id="post">
<h4>{{post.title}}</h4>
<br>
{{post.content}}
<br>
<i>{{post.datetime}}</i>
</div>
<br>
{% endfor %}
I'm using a blank url to load the index-page; so this view is reached from http://localhost:8000 in devmode.
Now, if i add an anchor-point (in lack of a better word..) to each of my posts, like:
modifying: <div id="post">
to <div id="post_{{post.id}}">
Should make every post, in that page, reachable via:
http://localhost:8000#post_1
..and so on..
Which works just fine, when the url is typed directly in the address-field of the browser, but when i try reaching it from a link from within the page itself, nothing happends..
Really grateful for any pointers, to where my problem might lie..
Get rid of the 'http://localhost' part. Just use the '#post_xx' part has the href.
i.e., I believe you need to do Post 35 when you create a link to an anchor within the same page

Categories