I just tried to add paginator for my search results page but it didn't work. I have 10 articles in search results and I set 3 for each page, which means totally the results list will be divided into 4 pages. However, when I searched keywords, it showed all 10 articles in the same page and the paginator didn't work.
My view.py is:
def search_titles(request):
q = request.GET.get('q')
error_msg = ''
if not q:
error_msg = 'Please enter keywords!'
return render(request, 'search_results.html', {'error_msg': error_msg})
else:
nq = q.split(' ')
a_list = Q(article_ti__icontains=nq[0]) | Q(article_content__icontains=nq[0]) | Q(
abstract__icontains=nq[0]) | Q(
author__icontains=nq[0])
for i in nq[1:]:
a_list.add(Q(article_ti__icontains=i) | Q(article_content__icontains=i) | Q(abstract__icontains=i) | Q(author__icontains=i), a_list.connector)
queryset = Article.objects.filter(a_list).distinct()
queryset_count = queryset.count()
paginator = Paginator(queryset, 3)
page_var = 'page'
page = request.GET.get(page_var, 1)
try:
sets = paginator.page(page)
except PageNotAnInteger:
sets = paginator.page(1)
except EmptyPage:
sets = paginator.page(paginator.num_pages)
return render(request, 'search_results.html', {'error_msg': error_msg, 'b_list': queryset, 'a_list_count': queryset_count, 'sets': sets, 'page_var':page_var})
my HTML code is:
<div class="ui text container">
{% if error_msg %}
<p>{{ error_msg }}</p>
{% else %}
{% for a in b_list %}
<div class="ui segment">
<a target="_blank" href={{ a.get_abs_url }}>
<h3>{{ a.article_ti }}</h3>
<h5>{{ a.author }}</h5>
<p>{{ a.abstract }}</p>
</a>
</div>
{% empty %}
<div class="ui segment">No results for '{{ request.GET.q }}'</div>
{% endfor %}
{% endif %}
</div>
<div class="pagination" id="m">
<span class="step-links">
{% if sets.has_previous %}
<<
<
{% endif %}
<span class="current"><input name="enter_page" value="{{ sets.number }}" id="page_num"> of {{ sets.paginator.num_pages }}</span>
{% if sets.has_next %}
>
>>
{% endif %}
</span>
</div>
I tried several methods on stackoverflow but still no work. Could anyone give me some suggestions?
I'll be very appreciated if you can help me!
In your template your are looping over 'b_list',
{% for a in b_list %}
<div class="ui segment">
<a target="_blank" href={{ a.get_abs_url }}>
<h3>{{ a.article_ti }}</h3>
<h5>{{ a.author }}</h5>
<p>{{ a.abstract }}</p>
</a>
</div>
{% empty %}
<div class="ui segment">No results for '{{ request.GET.q }}'</div>
{% endfor %}
change this to,
{% for a in sets %}
<div class="ui segment">
<a target="_blank" href={{ a.get_abs_url }}>
<h3>{{ a.article_ti }}</h3>
<h5>{{ a.author }}</h5>
<p>{{ a.abstract }}</p>
</a>
</div>
{% empty %}
<div class="ui segment">No results for '{{ request.GET.q }}'</div>
{% endfor %}
Related
I am a super beginner with HTML, however, I am trying to resolve an issue with my website. I am trying to concatenate a wildcard(*) to the end of whatever a consumer tries to search so that it picks up similarly tagged items, however, I cannot figure out where to add said code... Our current search query works well when pulling up items based on partial keywords, but when hitting the 'enter' button it will say it could not find any products.
Additional notes: This is a Shopify website with a theme from halothemes so most of this is coded by them.
{% assign grid_results = true %}
<div class="search-page collection-template" data-search-page>
<div class="container">
{% if search.performed %}
{% comment %}
Avoid accessing search.results before the opening paginate tag.
If you do, the pagination of results will be broken.
{% endcomment %}
{% paginate search.results by 15 %}
{% comment %}
We don't have any results to show. Feel free to show off featured products
or suggested searches here.
{% endcomment %}
{% if search.results_count == 0 %}
<header class="page-header">
<h2>
{% render 'multilang' with settings.search_1 %}
<strong> "{{ search.terms }}" </strong>
{% render 'multilang' with settings.search_2 %}
</h2>
</header>
{% else %}
<header class="page-header">
<h2>
{% render 'multilang' with settings.search_3 %}
<strong> "{{ search.terms }}" </strong>
{% render 'multilang' with settings.search_4 %}
</h2>
</header>
{% comment %}
Each result template, based on the grid_layout variable above
{% endcomment %}
<div class="block-row col-main">
{% if grid_results == false %}
<div class="product-collection products-list product-search row">
{% for product in search.results %}
<div class="grid-item col-12{% if settings.product_image_border%} grid-item-border{% endif %}">
{% render 'search-result' with product as product %}
</div>
{% endfor %}
</div>
{% else %}
<div class="products-grid product-search row product-collection">
{% for product in search.results %}
<div class="grid-item col-6 col-md-4{% unless settings.layout_style == 'layout_style_1170' %} col5 col-lg-3{% endunless %}{% if settings.product_image_border%} grid-item-border{% endif %}">
{% if settings.style_product_grid == 'style_product_grid_2' %}
{% render 'product-grid-item-style-2' with product as product %}
{% else %}
{% render 'product-grid-item' with product as product %}
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
{% if paginate.pages > 1 %}
<div class="padding">
{% render 'pagination-page' paginate: paginate %}
</div>
{% endif %}
{% endpaginate %}
{% else %}
{% comment %}
If search.performed is false, someone either accessed the page without
the q parameter, or it was blank.
Be sure to show a search form here, along with anything else you want to showcase.
{% endcomment %}
<header class="page-header">
<h2 style="text-align:center" {% if settings.enable_multilang %}data-translate="general.search.title"{%endif%}>{{ 'general.search.title' | t }}</h2>
<div class="header-search__form">
<form action="/search" method="get" class="search-bar" role="search">
<input type="hidden" name="type" value="product">
<input type="search" name="q"
{% if settings.enable_multilang %} data-translate="general.search.placeholder" translate-item="placeholder"{% endif %}
placeholder="{{ 'general.search.placeholder' | t }}"
class="input-group-field" aria-label="Search Site" autocomplete="off">
<button type="submit" class="btn icon-search">
{% render 'icon-search' %}
</button>
</form>
</div>
</header>
{% endif %}
Please let me know if you guys need any additional information! Thank you!
You can use a simple script to add a wildcard to the search query on submitting the form e.g:
var searchForm = document.querySelector(".search-bar");
searchForm.addEventListener("submit", function(e) {
var searchInput = searchForm.querySelector("[name=q]");
var q = searchInput.value;
if (!q.match(/\*$/)) {
e.preventDefault();
searchInput.value = q + "*";
searchForm.submit();
}
});
I have been working on a project and one of the functions that it has it to delete posts, when in the imagelist view, I am able to delete those posts but when I am in the profile view which shows the user's posts when I try to delete it, a 404 error page not found shows up. I dont know where the error is but I think it is on the profile view.
views.py
def profile(request, pk=None):
if pk:
post_owner = get_object_or_404(User, pk=pk)
user_posts=Post.objects.filter(user_id=pk)
else:
post_owner = request.user
user_posts=Post.objects.filter(user_id=pk)
return render(request, 'profile.html', {'post_owner': post_owner, 'user_posts': user_posts,})
profile.html
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ user.profile.image.url }}">
<div class="media-body">
<h2 class="account-heading">{{ post_owner.username }}</h2>
<p class="text-secondary">{{ post_owner.email }}</p>
</div>
</div>
<div>
{% for Post in user_posts %}
<li class="list-group-item">{{ Post.text }}
{{ Post.user }}
{% if Post.posti %}
<img src="{{ Post.posti.url }}" alt="image here" style="max-width: 300px; max-height: 300px">
{% endif %}
{% if Post.user == user %}
<div class="float-right">
<form action="delete_image/{{ Post.id }}/" action="post">
<button type="submit" class="btn btn-outline-danger btn-sm">Delete</button>
</form>
</div>
{% endif %}
</li>
{% endfor %}
</div>
</div>
urls.py
urlpatterns = [
path('profile/<int:pk>/', views.profile, name='profile_pk'),
path('imagepost', views.uimage, name='image'),
path('imagelist', views.imagelist, name='imagelist'),
path('delete_image/<int:image_id>/', views.delete_image, name='delete_image'),
]
All I did for fixing this problem was create add an if statement to my imagelist.html
{% if image.user == user %}
{{ image.user }}
{% else %}
{{ image.user }}
{% endif %}
I want that a message gets displayd if no search results are found but somewho im doing it wrong! Is
if post in object_list.count == 0
unsuitable?
My Django template:
{% extends 'quickblog/base.html' %}
{% block content %}
{% if post in object_list.count == 0 %}
<p>No results, sorry :(</p>
{% else %}
{% for post in object_list %}
<div class="post">
<h1><u>{{ post.title }}</u></h1>
<p>{{ post.content|linebreaksbr }}</p>
<div class="date">
<a>Published by: {{ post.author }}</a><br>
<a>Published at: {{ post.published_date }}</a><br>
<a>Category: {{ post.category }}</a><br>
<a>Tag(s): {{ post.tag }}</a>
</div>
</div>
{% endfor %}
{% endif %}
I made a small blog site and is not showing all the items from the database. If i try to see the posts from my phone i see only 3 posts, when in my DB there are 9. When i click on one post i got a Not Found error saying that the requested URL posts/legea etc was not found on server.
LE: My server is inside a VM. Is this maybe an issue?
This is the link that should have all of the posts: http://cohen.ro/posts/
PS I dont have a migrations folder. I just created now and put an init.py file in it. Bu still after running migrate didn't see the migrations and the result is the same.
However, if i enter in admin trhourgh site/admin i can see all of the posts in DB and when i go back to the site all of the items are out there and i can read the posts.
Can someone, please help me in order to fix this?! thank you!
My post List:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block head_title %} Blog | {% endblock %}
{% block content %}
<div class="container-fluid" style="width:91%;color: currentColor;!important;">
<div class="row" id="list_posts" style="background-color: white;padding-top: 40px;">
<br/>
<br/>
<br>
{% for obj in object_list %}
<div class="col-sm-4">
<div class="thumbnail">
{% if obj.image %}
<img src="{{ obj.image.url }}"/>
{% endif %}
<div class="caption" style="color:currentColor">
{% if obj.draft %} <h3>Staff Only Draft</h3> {% endif %}{% if obj.publish > today %}<h3>Staff Only: Future Post{%endif%}</h3>
<h2><a href='{{ obj.get_absolute_url }}' >{{obj.title }}</a> </h2>
<h5>{{obj.location }} </h5>
{% if obj.user.get_full_name %}<p>Author: {{ obj.user.get_full_name }}</p>{% endif %}
<p> {{ obj.content |linebreaks |truncatechars:150}}</p>
{# <p>View</p>#}
</div>
</div>
</div>
{# {% cycle "" "" "<div class='col-sm-12'><hr/></div></div><div class='row'style='background-color:white;color:currentColor'>" %}#}
{% cycle "" "" "<div class='col-sm-12'><hr/><br/></div><div class='row'style='background-color:white;color:currentColor'></div>" %}
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if object_list.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ object_list.number }} of {{ object_list.paginator.num_pages }}.
</span>
{% if object_list.has_next %}
next
last »
{% endif %}
</span>
</div>
</div>
</div>
Post Form:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block head_title %} Blog | {% endblock %}
{% block content %}
<div class="container-fluid" id="post_form_id" style="background-color: teal">
<div class="col-sm-6 offset-sm-3">
<h1> Form </h1>
<form method='POST' action='' enctype="multipart/form-data"> {% csrf_token %}
{{ form |crispy }}
<input type="submit" class="btn btn-default" role="button" value="Create Post">
</form>
</div>
</div>
{% include 'navbar_bottom.html' %}
{% endblock %}
My Post detail:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load i18n %}
{% block head_title %} Blog | {% endblock %}
{% block content %}
<div class="container-fluid" id="detail_posts" style="background-color: white">
<div class="col-xs-12 offset-xs-0 col-sm-6 offset-sm-3">
{% if instance.image %}
<img src="{{ instance.image.url }}" class="img-responsive" />
{% endif %}
<h1> {{ title }} <small> {% if instance.draft %} <span style="color:red">{% trans "Draft" %}</span> {% endif %}</small></h1>
{% if instance.user.get_full_name %}
<p> {% trans "Autor:" %} {{ instance.user.get_full_name }}</p>
{% endif %}
{{ instance.location |linebreaks }} <br/>
{{ instance.content |linebreaks }} <br/>
Facebook
Twitter
<a href="https://www.linkedin.com/shareArticle?mini=true&url={{ request.build_absolute_uri }}/&title={{ instance.title }}&source={{ request.build_absolute_uri }}">
Linkedin </a>
Reddit
<a href='https://plus.google.com/share?url={{ request.build_absolute_uri }}'>GooglePlus</a>
</div>
</div>
{% include 'navbar_bottom.html' %}
{% endblock content%}
My views:
from contact.forms import ContactForm
from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from contact.forms import ContactForm
from django.utils.translation import ugettext_lazy as _
import requests
from django.conf import settings
from django.contrib import messages
def index(request):
return render(request, 'home.html')
def board(request):
return render(request, 'board.html')
def persoanefizice(request):
return render(request, 'persoanefizice.html')
def consultanta(request):
return render(request, 'consultanta.html')
def cyberintelligence(request):
return render(request, 'cyberintelligence.html')
#
# def pay(request):
# return render(request, 'pay.html')
def blog(request):
return render(request, 'blog.html')
def contact(request):
if request.method == 'GET':
form = ContactForm()
else:
form = ContactForm(request.POST)
if form.is_valid():
contact_name = form.cleaned_data['numele_dumneavoastra']
contact_phone = form.cleaned_data['numarul_de_telefon']
# contact_period = form.cleaned_data['perioada_cand_va_putem_contacta']
subject = contact_name + " | " + contact_phone
content = form.cleaned_data['mesajul_dumneavoastra']
contact_email = form.cleaned_data['emailul_dumneavoastra']
''' Begin reCAPTCHA validation '''
recaptcha_response = request.POST.get('g-recaptcha-response')
data = {
'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
'response': recaptcha_response
}
r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data)
result = r.json()
''' End reCAPTCHA validation '''
if result['success']:
try:
send_mail(subject,content,contact_email, ['greatjobdone770#gmail.com'])
except BadHeaderError:
return HttpResponse('Invalid header found.')
return redirect('success')
else:
form = ContactForm()
return render(request, "contact.html", {'form': form})
def success(request):
return HttpResponse('Succes! Multumim pt mesajul trimis.')
I want to populate a twig page with information stored in the database. I use a loop to make multiple divs containing different entries of the same tables. The only problem is that I want to group the divs by4.. and I can't stop the loop when I reach the fourth step. In the end i get a big colon of divs.
Can anyone please tell me how to group the divs by 4?
This is my twig template:
<form method="POST" id="form-book">
<section id="portfolio" class="container main">
<ul class="gallery col-4">
{% for type in typeandrooms %}
{% for t, room in type %}
<li>
{% if t == 0 %}
<div class="preview">
{% set var_id = 'bundles/twnelo/images/portfolio/thumb/item' %}
{% set var_id = var_id ~ room.getType.id %}
{% set var_id = var_id ~ '.jpg' %}
<img src="{{ asset(var_id) }}">
<div class="overlay">
</div>
</div>
<div class="desc">
<h5> {{ room.getType.name }} </h5>
<strong>Beds: </strong>Double bed<br/>
<strong>Available rooms: </strong> {{ type|length }} <br/>
<strong>Prices: </strong> {{ room.getPrice }} <br/>
<button type = "submit" name="singleapartment" value = "{{ room.getType.id }}" class="btn btn-success btn-small">Book a room !</button>
</div>
{% endif %}
{% if loop.index % 4 == 0 and loop.index > 0 %}
</li>
Al 4-lea pas
<li>
{% endif %}
</li>
{% endfor %}
{% endfor %}
</ul>
</section>
</form>
{% endfor %}
Problem is solved. This is the new template:
<form method="POST" id="form-book">
<section id="portfolio" class="container main">
<ul class="gallery col-4">
{% for rooms in typesandrooms %}
{% for room in rooms %}
{% if loop.index == 1 %}
<li>
<div class="preview">
{% set var_id = 'bundles/twnelo/images/portfolio/thumb/item' %}
{% set var_id = var_id ~ room.getType.id %}
{% set var_id = var_id ~ '.jpg' %}
<img src="{{ asset(var_id) }}">
<div class="overlay">
</div>
</div>
<div class="desc">
<h5> {{ room.getType.name }} </h5>
<strong>Facilities: </strong>{% for facility in room.getFacilities %} {% if loop.index < 4 %} {{ facility.getFacility }}; {% endif %} {% endfor %}<br/>
<strong>Available rooms: </strong> {{ rooms|length }} <br/>
<strong>Prices: </strong> {{ room.getPrice }} Lei <br/>
<button type = "submit" name="singleapartment" value = "{{ room.getType.id }}" class="btn btn-success btn-small">Book a room !</button>
</div>
</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</section>
</form>
You have to open the first row right before the loop.
{% for type in typeandrooms %}
+ <li>
{% for t, room in type %}
- <li>
And close the last one right after
{% endif %}
- </li>
{% endfor %}
+ </li>
{% endfor %}
And given this line {% if t==0 %} I reckon you'll need to use a counter instead of index.loop. Else you could end up with less than 4 room per list row. The best practice would be to parse the array first in your controller and remove the rooms with t==0 then just remove the {% if t==0 %} line in your twig template and it'll work with index.loop, you want to keep the logic in twig to a minimum.