Django comments pagination isnt working - django

there is a trouble I'm new to django and there is an issue I can't understand,
there is a view:
def article(request, article_id = 1, comments_page_number = 1):
all_comments = Comments.objects.filter(comments_article_id = article_id)
paginator = Paginator(all_comments, 2)
comment_form = CommentForm
args = {}
args.update(csrf(request))
args['article'] = Article.objects.get(id = article_id)
args['comments'] = paginator.page(comments_page_number)
args['form'] = comment_form
args['username'] = auth.get_user(request).username
return render_to_response('article.html', args)
there is a template article.html
{% extends 'main.html' %}
{% block article %}
<h4>{{article.article_date}}</h4>
<h2>{{article.article_title}}</h2>
<p> {{article.article_body}}</p>
<hr>
<div class="large-offset-1 large-8 columns">
<p>Комментарии: </p>
{% for comment in comments %}
<p>{{comment.comments_text}}</p>
<hr>
{% endfor %}
{% if username %}
<form action="/articles/addcomment/{{article.id}}/" method="POST" >
{% csrf_token %}
{{form }}
<input type="submit" class="button" value="Add comment">
</form>
{% endif %}
</div>
<div class="row">
<div class="large-3 large-offset-5 columns">
<ul class="pagination">
{% if comments.has_previous %}
<li class="arrow">«</li>
{% else %}
<li class="arrow unavailable">«</li>
{% endif %}
{% for page in comments.paginator.page_range %}
{% if page == comments.number %}
<li class="current">{{ page }}</li>
{% else %}
<li>{{ page }}</li>
{% endif %}
{% endfor %}
{% if comments.has_next %}
<li class="arrow">»</li>
{% else %}
<li class="arrow unavailable">»</li>
{% endif %}
</ul>
</div>
</div>
{% endblock %}
this is my article/urls.py
urlpatterns = patterns('',
url(r'^articles/get/(?P<article_id>\d+)/$','article.views.article'),
url(r'^articles/get/(?P<article_id>\d+)/comments/(\d+)/$', 'article.views.article'),
)
after that on my article page appeared an pages pagination, but when I'm clicking on the second page, for example, it it is just changing my url, but new comments are not appearing, just old ones.
What should I do to do this right? Thank you very much!

Your variable name comments_page_number uses always the default value. Name your second parameter in the url route to match this variable name.

you need :
url(r'^articles/get/(?P<article_id>\d+)/comments/(?P<comments_page_number>\d+)/$', 'article.views.this_article'),

Related

Problem pagination for category posts in Django

I used the following code for pagination and got the error I left here. please help.
Note that for categories whose number of posts is less than 2 (_paginator), there is no problem, but the same posts are more than two and pagination is done.
urls.py:
from django.urls import path
from . views import home, detail_article, category_list
app_name = "blog"
urlpatterns = [
path('', home, name="home"),
path('page/<int:page>', home, name="home"),
path('post/<slug:slug>', detail_article, name="detail_article"),
path('category/<slug:slug>', category_list, name="category_list"),
path('category/<slug:slug>/page/<int:page>', category_list, name="category_list")
]
views.py:
def category_list(request, slug, page=1):
category = get_object_or_404(Category, slug=slug, status=True)
article_list = category.articles.published()
_paginator = Paginator(article_list, 2)
articles = _paginator.get_page(page)
context = {
'category':category,
'articles':articles
}
return render(request, 'blog/category.html', context)
template.html:
<!-- Paginator -->
{% if articles.has_other_pages %}
<div class="col-12 pagging">
<ul>
{% if articles.has_previous %}
<li>
<a href="{% url 'blog:category_list' category.slug articles.previous_page_number %}">
<i class="fa fa-arrow-right" aria-hidden="true"></i></a>
</li>
{% else %}
<li><i class="fa fa-arrow-right a-active" aria-hidden="true"></i></li>
{% endif %}
<!-- {% for i in articles.paginator.page_range %} {% if articles.number == i %}
<li><span class="a-active">{{ i }}</span></li>
{% else %}
<li>{{ i }}</li>
{% endif %} {% endfor %} -->
{% if articles.has_next %}
<li>
<a href="{% url 'blog:category_list' category.slug articles.next_page_number %}">
<i class="fa fa-arrow-left" aria-hidden="true"></i>
</a>
</li>
{% else %}
<li><i class="fa fa-arrow-left a-active" aria-hidden="true"></i></li>
{% endif %}
</ul>
</div>
{% endif %}
<!-- end paginator -->
and error! :(
error
The HTML in comment is still rendered by the template engine. So you should remove the {% url 'blog:category' %} parts. If you want to put comment in a Django template, you do that between {# … #}, or you can use a {% comment %} … {% endcomment %} template block [Django-doc].
For example:
{% if articles.has_previous %}
<li>
<a href="{% url 'blog:category_list' category.slug articles.previous_page_number %}">
<i class="fa fa-arrow-right" aria-hidden="true"></i></a>
</li>
{% else %}
<li><i class="fa fa-arrow-right a-active" aria-hidden="true"></i></li>
{% endif %}
{% comment %}
<!-- {% for i in articles.paginator.page_range %} {% if articles.number == i %}
<li><span class="a-active">{{ i }}</span></li>
{% else %}
<li>{{ i }}</li>
{% endif %} {% endfor %} -->
{% endcomment %}
{% if articles.has_next %}
<li>
<a href="{% url 'blog:category_list' category.slug articles.next_page_number %}">
<i class="fa fa-arrow-left" aria-hidden="true"></i>
</a>
</li>
{% else %}
<li><i class="fa fa-arrow-left a-active" aria-hidden="true"></i></li>
{% endif %}
fixed problem! :)
{% for i in articles.paginator.page_range %}
{% if articles.number == i %}
<li><span class="a-active">{{ i }}</span></li>
{% else %}
<li>{{ i }}</li>
{% endif %} {% endfor %}

Django - How to load paginated Page (next page) into my Template?

I have a model named "Person" (List of names).
6 Persons named "Anne". My Pagination is 2 per Page.
When i start a search query on my page for "Anne". I get the Response of "6 Results", it shows me the first two Results and it displays "Page 1 of 3. Next. So far everything fine. but when i press "next" the Browser only updates to
..../post_searchtwo/?page=2 but the next two Results will not show up.
(Using Django version 2.2.2 with PostgreSQL 11)
thanks in advance.
views.py
def post_searchtwo(request):
form = SearchForm()
query = None
results = []
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
query = form.cleaned_data['query']
results = Person.objects.annotate(
search=SearchVector('city', 'last_name', 'first_name')
).filter(search=query)
paginator = Paginator(results, 2) # --- Show 2 items per page
page = request.GET.get('page')
try:
post_list = paginator.page(page)
except PageNotAnInteger:
post_list = paginator.page(1)
except EmptyPage:
post_list = paginator.page(paginator.num_pages)
context = {
'form': form,
'query': query,
'page': page,
'post_list': post_list,
'results': results
}
return render(request,'search/post_searchtwo.html', context)
my template / post_searchtwo.htnl
{% extends 'base.html' %}
{% load static %}
{% block custom_css %}
<link rel="stylesheet" type="text/css" href="{% static 'css/home_styles.css' %}">
{% endblock %}
{% block content %}
<form action="." method="get">
{{ form.as_p }}
<input type="submit" value="Search">
</form>
{% if query %}
<h3>Posts containing "{{ query }}"</h3>
<h3>
{% with results.count as total_results %}
Found {{ total_results }} result{{ total_results|pluralize }}
{% endwith %}
</h3>
{% for post in post_list %}
<h4>
{{ post.first_name }} {{ post.last_name }}
</h4>
{% empty %}
<p>Theren are no results for your query.</p>
{% endfor %}
<div class="col-6 offset-md-3">
{% include "pagination.html" with page=post_list %}
</div>
{% endif %}
{% endblock %}
.../pagination.htnl
<div class="pagination">
<span class="step-links">
{% if page.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ page.number }} of {{ page.paginator.num_pages }}.
</span>
{% if page.has_next %}
Next
{% endif %}
</span>
</div>
Update: Thanks to #Daniel Roseman
as Daniel pointed out (down below) here the changes.
.../pagination.htnl
<div class="pagination">
<span class="step-links">
{% if page.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ page.number }} of {{ page.paginator.num_pages }}.
</span>
{% if page.has_next %}
Next
{% endif %}
</span>
</div>

Get Django search query right

Im currently facing a problem since a couple of days for now. I simply want to implement a search view into my Django app. But when i try to search something on my App i get the following error:
init() takes 1 positional argument but 2 were given__init__() takes
In the end i want that my Query is a combination of category and searchword. So that the user can filter specific categories (Just like Amazon.com searchfield) e.g.: http://127.0.0.1:8000/search/?category=1&q=hallo
base.html
...
<div class="globalsearch">
<form id="searchform" action="{% url 'search' %}" method="get" accept-charset="utf-8">
<label for="{{ categorysearch_form.category.id_for_label }}">In category: </label> {{ categorysearch_form.category }}
<input class="searchfield" id="searchbox" name="q" type="text" placeholder="Search for ...">
<button class="searchbutton" type="submit">
<i class="fa fa-search"></i>
</button>
</form>
</div>
</div>
...
categorysearch_form is a dropdown selector that gets his ID from the Database.
views.py
...
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
from django.views.generic import ListView
class globalsearch(ListView):
"""
Display a Post List page filtered by the search query.
"""
model = Post
paginate_by = 10
def get_queryset(self):
qs = Post.objects.published()
keywords = self.request.GET.get('q')
if keywords:
query = SearchQuery(keywords)
title_vector = SearchVector('title', weight='A')
content_vector = SearchVector('content', weight='B')
tag_vector = SearchVector('tag', weight='C')
vectors = title_vector + content_vector + tag_vector
qs = qs.annotate(search=vectors).filter(search=query)
qs = qs.annotate(rank=SearchRank(vectors, query)).order_by('-rank')
return qs
...
urls.py
...
url(r'^search/$', views.globalsearch.as_view(), name='search'),
...
Search.html results are getting displayd here:
{% extends 'quickblog/base.html' %}
{% block content %}
{% 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 %}
{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
<li>«</li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in paginator.page_range %}
{% if page_obj.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li>»</li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
{% endblock %}
Project: https://github.com/rsmvdl/quickblog
Since globalsearch is class based view it should be globalsearch.as_view() in your urls:
url(r'^search/$', views.globalsearch.as_view(), name='search'),

is_paginated not working properly for class based views in Django

book_list.html
{% extends "base.html" %}
{% block content %}
<h3> Available books </h3>
{% if book_list %}
<ul>
{% for book in book_list %}
<li> {{book.title }} <small> by {{book.author }}</small></li>
<p>{{ book.summary }}
{% endfor %}
<ul>
{% endif %}
{% if is_paginated %}
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
previous
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
{% endif %}
</span>
</div>
{% else %}
<h4> pagination not working</h4>
{% endif %}
{% endblock %}
class in views.py :
class BookListView(generic.ListView):
model = Book
paginate_by = 2
queryset =Book.objects.all()
urls.py :
urlpatterns =[
url('^$',views.index, name ='index'), # matching with an empty string
url('^books/$',views.BookListView.as_view(),name ='books'), #the one to which I am adding the paginator
url('^book/(?P<pk>\d+)/$',views.BookDetailView.as_view(),name='book-detail'),
]
Book model :
class Book(models.Model):
title=models.CharField(max_length=100)
author = models.ForeignKey('Author',on_delete=models.SET_NULL,null = True)
summary = models.TextField(max_length=200,help_text="Enter the description")
isbn = models.CharField('ISBN',max_length=13 ,help_text='13 Character ISBN number' )
genre = models.ManyToManyField(Genre,help_text = 'selct a genre for this book')
class Meta:
ordering =["title"]
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('book-detail',args=[str(self.id)] )
The book_list gets rendered perfectly, the problem is with the paginator, the is_paginated condition is not working and it executes the else statement, I have been trying for more than 3 hours, but couldn't find a solution, What Am I missing here ?
Django version : 1.11.2
Python : 3.5
Edit :
update 1: The problem was the paginate_by value was two, and the total items to display was also two hence it didn't initiate the is_paginated tag,It worked fine when I added one item more than paginate_by value.
use this, you had some problem with the if condition
{% extends "base.html" %}
{% block content %}
<h3> Available books </h3>
{% if object_list %}
<ul>
{% for book in object_list %}
<li> {{book.title }} <small> by {{book.author }}</small></li>
<p>{{ book.summary }}
{% endfor %}
<ul>
{% if is_paginated %}
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
previous
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
{% endif %}
</span>
</div>
{% else %}
<h4> pagination not working</h4>
{% endif %}
{% else %}
<h4> No book</h4>
{% endif %}
{% endblock %}

how to make flask pagination keep the query condition

here is my view function:
def get_user_info():
form = UserInfoForm()
query = UserInfo.query
if form.validate_on_submit():
query = query.filter_by(sex=form.sex.data)
flag = False
page = request.args.get('page', 1, type=int)
pagination = query.paginate(page=page, per_page=10, error_out=False)
return render_template("user_info.html", form=form,data=pagination.items, pagination=pagination)
and here is part of my html:
<form class="form-inline" action="{{url_for('.get_user_info')}}", method="post">
{{ form.csrf_token }}
<div class="panel-body">
<div class="form-group">
{{ form.sex.label }}:
{{ form.sex(class="form-control") }}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-primary") }}
</div>
</div>
and here is my pagination macro:
{% macro pagination_widget(pagination, endpoint) %}
{% if pagination.total != 0 %}
<ul class="pagination">
<li{% if pagination.page == 1 %} class="disabled"{% endif %}>
<a href="{% if pagination.page != 1 %}{{ url_for(endpoint, page=1, **kwargs) }}
{% else %}#{% endif %}">««</a>
</li>
<li{% if not pagination.has_prev %} class="disabled"{% endif %}>
<a href="{% if pagination.has_prev %}{{ url_for(endpoint, page=pagination.page - 1, **kwargs) }}
{% else %}#{% endif %}">«</a>
</li>
{% for p in pagination.iter_pages() %}
{% if p %}
<li {% if p == pagination.page %} class="active"{% endif %}>
{{ p }}
</li>
{% endif %}
{% endfor %}
<li{% if not pagination.has_next %} class="disabled"{% endif %}>
<a href="{% if pagination.has_next %}{{ url_for(endpoint, page=pagination.page+1, **kwargs) }}
{% else %}#{% endif %}">»</a>
</li>
<li{% if pagination.page == pagination.pages %} class="disabled"{% endif %}>
<a href="{% if pagination.page != pagination.pages %}{{ url_for(endpoint, page=pagination.pages, **kwargs) }}
{% else %}#{% endif %}">»»</a>
</li>
</ul>
{% endif %}
{% endmacro %}
I use a selectfiled sex in my page, when I select male in my page, I get the paginate object and my first page user is all male.But when I click next page, the results will have both male and female, I just want it like the first page, it has only male user info. Thanks.
I have resolved my problem today.
There are *args, and **kwargs for any macro, so I can pass parameters of query condition to it and in my view functions use request.args.get() to obtain parameters and set it to form.