Django-cms haystack search - placeholder content - python

i have problem with results in django-cms and haystack search. I'm using django-cms-search plugin, haystack as backend. Haystack returns correct results. But i want to show "teaser" in search results.
I can access absolute URL and title of page via template this way:
{% for result in page.object_list %}
<div class="searchResults">
<h2>{{ result.object.get_title }}</h2>
{{ result.object.placeholders.all }}
<p>{% blocktrans %} Read more {% endblocktrans %}</p>
Problematic part is {{ result.object.placeholders.all }}. I have on every page content in placeholder with name content.
{{ result.object.placeholders.all }} returns only name of the placeholders.
Search results should look like this:
PAGE TITLE
PAGE TEASER
READ MORE LINK
In teaser there should be first 50 words from search-matched page.
Is this possible to access placeholder content from template?
Thank you for your tips.

Haystack has templatetag higlight which creates "teaser" as i requested.
Template code can look like this:
{{ result.object.get_title }}
{% highlight result.text with request.GET.q max_lenght 40 %}
{{ result.object.get_absolute_url }}
Thanks to guys from #haystack IRC channel.

Related

Lektor CMS : Can't get lektor-tags to work properly, The requested URL was not found on the server

I am trying to build a blog using lektor CMS, for that.. i needed a tags system, after searching i found a lektor plugin on lektor docs called lektor-tags
I followed every step on the docs, struggled a lot and even visited the github repo to see if is there anything else not included in the docs.
My problem is when i try to visit localhost:5000/{the_tag_name} say like localhost:5000/python i always get a 404 Not Found saying that
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
This is what i did so far:
Before using lektor-tags:
I changed the route for the blog posts to be /posts instead of /blog.
Added slug format to models/blog.ini in [children]
[children]
model = blog-post
order_by = pub_date, title
slug_format = {{ (this.pub_date|dateformat('YYYY/M/') if this.pub_date) ~ this._id }}
Created 3 posts, everything was working properly.
At this point i wanted to use a tags system so i chosen to use lektor-tags, what i did was:
Installation
lektor plugins add lektor-tags
Created configs/tags.ini with this config:
parent = /
url_path = {{ this.parent.url_path }}{{ tag }}
tags_field = tags
ignore_missing = true
template = tags.html
Created templates/tags.html with the following content:
{% extends "layout.html" %}
{% block title %}{{ this.title }}{% endblock %}
{% block body %}
<div class="container mt-3">
<b>Tag: {{ this.tag }}</b>
<b>Items:</b>
<ul>
{% for i in this.items %}
<li>{{ i._id }}</li>
{% else %}
<li><em>No items.</em></li>
{% endfor %}
</ul>
</div>
{% endblock %}
Edited models/blog-post.ini and added:
[fields.tags]
type = strings
In templates/blog-post.html i added the following to show links to the page that contain a list of all posts with the specific tag:
{% if this.tags %}
<ul>
{% for t in this.tags -%}
<li>
<a href="{{ ('/' ~ t.lower())|url }}">
All posts tagged {{ t }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
Finally i updated a post to contain some tags from the admin and made sure it's there in content.lr for that post. so i stopped the lektor dev server and run it again lektor servor with no errors to be present.
The links were there in the post for the tags but when i click and follow a link say for example for the python tag localhost:5000/python i get 404 Not Found. i am new to lektor. i'm wondering what i did wrong and how can i get this to work properly?
NB: Other plugins i used are lektor-minify, lektor-disqus-comments the docs for these plugins were straightforward and i didn't got confused, but when it comes to this specific plugin i were confused, struggling: the docs were not that great and explaining, i felt completely lost!
Update
I created a github repo containing the code and what i have done so far so you can easily replicate this.
Update 2
I managed to get this to work properly see my answer below, however now i'm wondering how to set the root as the parent in other words how to edit this expression :
<a href="{{ ('/posts#tag/' ~ t.lower())|url }}">
to generate a source path for each of the blog post's tags but using root as the parent.
As you can see i tried this :
<a href="{{ ('/' ~ t.lower())|url }}">
but this doesn't work properly.
It's worth mentioning that lektor uses jinja2 templating language.
So Basically it was me doing this wrong because i wanted to use the root as the parent in tags.ini like so :
parent = /
I ended up changing the expression '/blog#tag/' ~ t.lower() in blog-post.html to something like :
<a href="{{ ('/' ~ t.lower())|url }}">
making it not able to generate a source path for each of the blog post's tags
What i changed and worked was :
I chosen posts to be the parent, updated the configs/tags.ini to :
parent = /posts
url_path = {{ this.parent.url_path }}{{ tag }}
tags_field = tags
ignore_missing = true
template = tags.html
Updated templates/blog-post.html :
{% if this.tags %}
<ul>
{% for t in this.tags -%}
<li>
# '/posts#tag/' ~ t.lower() because i changed the route of blog to posts
<a href="{{ ('/posts#tag/' ~ t.lower())|url }}">
All posts tagged {{ t }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
After running lektor clean --yes then lekor server everything was working properly including the tags system.

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

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.

Why django finds errors inside comment blocks in template?

Sometime Django finds an error in a template. I Would like to comment out the row to debug but django keeps to find the error even in the comment.
For example this link give me an error because url 'prova' don't exist.
<!--Prova<br/>-->
another example: here {{ field }} give an error (and I don't know why but this is another problem)
<!--{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.label }}
{{ field }}
{{ field.help_text }}
<br />
{% endfor %}-->
Maybe there's another way to comment?
Thank you
Django still parses the code; it doesn't care about HTML comments. If you want to ensure that it does not get rendered at all, you should use the Django comment tags, {% comment %}...{% endcomment %}.
For a single line, you can wrap things in {# ... #}.
See the docs.

Django: How to associate a comment to its corresponding OP in the HTML template?

I have designed a simplistic posting and comment system where each postcomment object is associated with its corresponding newpost object using foreign key. My problem is that the comments in the template aren’t showing under their corresponding newpost object. For example, if there are a total of 3 newposts and 3 comments under each post for a total of 9 comments, the template displays all 9 comments under each 3 posts (for a total of 27 comments). I need help figuring out how to correctly associate each comment with its corresponding post and not just loop through my ‘allcomments’ field under each post. Thanks for any help and hints.
postset = pagename.newpost_set.all().order_by('-postdate') #i use this to get a queryset of all posts on the selected page and order them so newest posts show up at the top
allposts = newpost.objects.filter(newposttag=‘userpage’) #i use this to get a queryset of all posts on the corresponding user’s page for the next line, this might seem redundant after the above, but it works because the postset is what I end up using in the template.
allcomments = postcomment.objects.filter(commenttag=allposts) #i use this to get a queryset of all the comments from each post in the ‘allposts’ queryset
Here is my template for displaying the above information that I have acquired
{% for postset in postset %}
<br>{{ postset.postcontent }} {{postset.postdate }} - {{ postset.postlikes }} likes Comment</br>
{% for allcomments in allcomments %}
<br> {{ allcomments.comment }} {{allcomments.postcommentdate }} - {{ allcomments.commentlikes}}
{% endfor %}
{% endfor %}
How about updating your template as follows:
{% for post in postset %}
<br>{{ post.postcontent }} {{post.postdate }} - {{ post.postlikes }} likes Comment</br>
{% for comment in post.postcomment_set.all %}
<br> {{ comment.comment }} {{comment.postcommentdate }} - {{ comment.commentlikes}} </br>
{% endfor %}
{% endfor %}
This way, you iterate over your posts and for each post, you retrieve the comments related to that post through the post.postcomment_set.all expression.
Please let me know if that helps you.
ps: I don't think that you need those three queries in your view though.

Categories

Resources