Django add link after slice - django

i have the following in my html template:
<h1><u>{{ post.title }}</u></h1>
<p>{{ post.content|slice:":1000"|linebreaksbr }}</p>
i want that after the slice to 1000 chars a href to the full article gets displayd.
e.g.:
<h1><u>{{ post.title }}</u></h1>
<p>{{ post.content|slice:":1000"|link:"... read on" href= url 'post_detail'|linebreaksbr }}</p>
any idea?

Well separate the text of the partial article from the link. Like:
<p>{{ post.content|slice:":1000"|linebreaksbr}}
read on</p>
Typically by splitting up problems in subproblems, the problem becomes easier to manage.
The {% url ... %} is probably with pk=post.pk or something similar, since otherwise it would link to the post_details, but without a specific post.
Alternatively, if you only want to show read on when the content is sliced, you can use an {% if ... %}:
<p>{{ post.content|slice:":1000"|linebreaksbr}}
{% if post.content|length > 1000 %}
read on
{% endif %}</p>

Related

Django ListView works but DetailView not displaying Model Data

I am helping my daughter with her computing Project for school. It is a simple generic forum type application.
She has a ListView for a model which works fine:
{% extends 'users/main.html' %}
<!-- Here is where our content will begin -->
{% block content %}
<h1>This is posts.html!</h1>
<br/>
{% for obj in object_list %}
<h2>{{ obj.topic }}</h2>
{{ obj.date_posted }}
<br/>
{{ obj.content }}
<br/>
Author: {{ obj.author }}
<br/><br/>
{% endfor %}
{% endblock %}
She then added a DetailView which is simply the same code with the loop removed:
{% extends 'users/main.html' %}
<!-- Here is where our content will begin -->
{% block content %}
<h1>This is posts.html!</h1>
<br/>
{{ obj.id }}
<h2>{{ obj.topic }}</h2>
{{ obj.date_posted }}
<br/>
{{ obj.content }}
<br/>
Author: {{ obj.author }}
<br/><br/>
{% endblock %}
This is then called with a '....post/1/' (post id = 1 does exist (checked via DB Browser and in the ListView) and the path and naming of the template is correct.
Frustratingly, this displays the page but not the details inside the django temp language brackets (object.topic etc)!
When I look at the page source for the section dealing with the detail, I get:
screenshot of page
and the source code looks like so:
<h1>This is posts.html!</h1>
<br/>
<h2></h2>
<br/>
<br/>
Author:
<br/><br/
It is simply ignoring the bracketed templating code - any ideas?
Django DetailView returns 'object' inside context by default.
If you did not change 'context_object_name' variable, then use {{object}} instead of {{obj}}
<h1>This is posts.html!</h1>
<br/>
{{ object.id }}
<h2>{{ object.topic }}</h2>
{{ object.date_posted }}
<br/>
{{ object.content }}
<br/>
Author: {{ object.author }}
<br/><br/>
Really thanks a lot for all of this.
I corrected my template to include 'object' and made it march all conventions to avoid having to send in context information.
It still wouldn't work.
I rebooted localhost repeatedly because it all made no sense.
Finally, I rebooted my daughters PC and immediately, everything worked.
A lesson learned and as a dad helping a 17 year old daughter who did his Computer Science degree 40(!) years ago, another lesson in how complicated and challenging understanding a framework can be.
I must say - it has been fun.
Thanks again,
Howard.

What does this html tag mean in django's example?

This is django's polls demo, and most are well documented. However, in this part:
https://docs.djangoproject.com/en/3.0/intro/tutorial04/
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
Vote again?
The documentation doesn't say anything about this part:
vote{{ choice.votes|pluralize }}
And from the generated html page, I can't see what's the role of this piece?
pluralize is an in-built Django template tag that attempts to convert the word that it is appended to to plural. So you feed it a number, and if the number is 1 then it returns '', but if the number is greater than 1, it returns 's'.
https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#pluralize

NoReverseMatch when rendering page

I seem to know where the issue is located since I can get around it, but for getting around it I have to sacrifice a function I really want to keep.
Here is the relevant code in the non-working state:
{% if sections %}
{% for item in sections %}
<a class="sections" href="{% url 'sections:generate' item.section.slug %}">{{ item.section.title }}</a>
{% for subsection in item.subsections %}
<p>{{ subsection.title }}</p>
{% endfor %}
{% endfor %}
{% else %}
<p>Error retrieving sections or no sections found</p>
{% endif %}
The problem part above is in the link tag. Let me explain by showing the related view.py:
def index(request):
sections = Section.objects.all()
context = {
'sections': [],
}
for section in sections:
context.get("sections").append(
{
'section': section,
'subsections': get_subsections(section),
}
)
return render(request=request, template_name='index.html', context=context)
So, 'sections' is an iterable list of items, containing for every items a dictionary with two entries. One, 'section' and one 'subsection'. There are multiple subsections for every section, this is what I really want to accomplish.
Ordinarily, when not bothering with subsections and simply iterating over a list of sections works fine. The template code for that would look something like:
{% for section in sections %}
{{ section.title }}
{% endfor %}
NOTE! The code above works just fine! But as soon as I add 'sections' as a list of dictionaries and have to reference the slug by item.section.slug the pages stop rendering.
Please advise.
Try using tuples:
View:
context['sections'] = [(section, tuple(get_subsections(section))) for section in sections]
Template:
{% for section, subsections in sections %}
<a class="sections" href="{% url 'sections:generate' section.slug %}">{{ section.title }}</a>
{% for subsection in subsections %}
<p>{{ subsection.title }}</p>
{% endfor %}
{% endfor %}

How can I show just the most recent post on my home page with jekyll?

<ul class="entries">
{% for post in paginator.posts %}
<li>
<a href="{{ post.url }}">
<h3>{{ post.title }}</h3>
<p class="blogdate">{{ post.date | date: "%d %B %Y" }}</p>
<div>{{ post.content |truncatehtml | truncatewords: 60 }}</div>
</a>
</li>
{% endfor %}
</ul>
That shows all my posts, I just want to show the most recent.
This can be accomplished through the use of limit:
{% for post in site.posts limit:1 %}
... Show the post ...
{% endfor %}
You can also use limit and offset together to "feature" your most recent post:
<h1>Latest Post</h1>
{% for post in site.posts limit:1 %}
... Show the first post all big ...
{% endfor %}
<h1>Recent Posts</h1>
{% for post in site.posts offset:1 limit:2 %}
... Show the next two posts ...
{% endfor %}
Rather than create a loop, just assign the variable and move on...
{% assign post = site.posts.first %}
(Edit 2018) Since someone wanted to know how to iterate other posts after you've done this:
{% for post in site.posts offset:1 %}
... Show the next posts ...
{% endfor %}
If you got here for the question as stated in the title, "How can I show just the most recent post on my home page with jekyll?" and not "how do I show only the latest post in my template," the following might be helpful.
Given a brand new Jekyll version 3.7.3 install with the default minima theme, create a file, _layouts/home.html with the following content:
---
layout: none
---
{{ site.posts.first }}
Causes Jekyll 3.7.3 to show the first post, using the post template, as the home page.
It appears you can also just access the latest post via the first index of site.posts as in:
{%- assign latest_post = site.posts[0] -%}
Latest post: {{ latest_post.title }}
While site.posts.first works too as mentioned by someone else, the above example also provides a consistent manner for accessing other indices besides just the first (not that you would ever need to). Also, I didn't have enough reputation to add this answer as a comment instead :)

How do you limit list objects template side, rather than view side

One of the ways to limit objects is to add a limitation to a function like this
def ten_objects():
obj = Model.objects.all()[0:10] # limit to 10
return {'objects': obj}
However how do you achieve this inside a template rather than inside a view?
I know you can filter through objects within a template and limit characters but how do you actually limit the amount of objects displayed in a loop. Via the template. for example the following code will loop through all objects....
<ul>
{% for new in news %}
<li>
<p>{{ news.title }}</p>
<p>{{ news.body }}</p>
</li>
{% endfor %}
</ul>
How do I break the loop, say after the firs 3 objects/items? And how do I do it inside the template?
There is a slice filter that you can use in templates. This works exactly the same as slicing within the view.
{% for new in news|slice:":10" %}
You want to use the slice template filter
Here's your example altered to use it:
<ul>
{% for new in news|slice:":3" %}
<li>
<p>{{ new.title }}</p>
<p>{{ new.body }}</p>
</li>
{% endfor %}
</ul>