Next Page / Previous Page not working for Django pagination - python

I was hoping someone could help me with a pagination question.
I am trying to use Django pagination following the information on this page (https://docs.djangoproject.com/en/2.2/topics/pagination/). Whilst I have successfully displayed the correct number of items on the first page and the last page works, the next and previous pages keep taking me to the first page.
I think the issue may revolve around the ‘request’ element and I’m not sure if I am picking up an incorrect version. The example states:-
def listing(request):
contact_list = Contacts.objects.all()
paginator = Paginator(contact_list, 25) # Show 25 contacts per page
page = request.GET.get('page')
contacts = paginator.get_page(page)
return render(request, 'list.html', {'contacts': contacts})
The command:
page = request.GET.get(‘page’)
returns “AttributeError: 'Request' object has no attribute 'GET'”
By replacing this code with:
page = request.args.get('page', type=int)
the code successfully renders the first (and last) page but next and previous do not work.
As background I built my system on the Flask megatutorial but I have been unable to use that pagination, I understand because I haven’t used the Flask SQL Alchemy for creating and updating databases. My routes file has
from flask import request
Should I replace this with another utility's “request” and if so, which?

It seems the problem was in a missing () within the HTML file:-
next
listed within the example should have been:
next

Related

Django Pagination not work in the next page

I'm building an application that allows to page the result of a search. The results can be numerous that's why I used django's pagination. I have configured filters and sorting of results displayed by 10:
`
def search_details(request, type_anc):
querylist = Annonce.objects.filter(type_annonce = type_anc, is_published=True)
...........
paginator = Paginator(querylist, 10)
page = request.GET.get('page')
paged_listings = paginator.get_page(page)
`
When I click on the button that sends me to the next page, 'order_by' is not respected.
For example I have a result that sorts the price by descending order and the last element is 850 000, in the next page the prices displayed should be below 850 000.
Can you help me?
Actually, this question seems to be unclear but I framed my answer according to the details provided. (Please provide a meaningful problem statement, need modal and template details also to provide a solution...)
Here Your modal name is Announce, you need to paginate by 10 and it's a search function. here I assume your template name to be 'XYZ.html' so views gonna be
views.py
from django.core.paginator import Paginator
from django.shortcuts import render
from .moddels import Announce
def search_details(request, type_anc):
announce_list = Announce.objects.filter(type_annonce=type_anc, is_published=True)
paginator = Paginator(announce_list, 10)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(resuest, 'XYZ.html', {'page_obj': page_obj})
Here page_obj holds the data for the page that which user requests... you can render the data in the template by following the Django docs.Here is the link https://docs.djangoproject.com/en/4.1/topics/pagination/#:~:text=%7B%25%20for%20contact,%3C/div%3E

Django session variables not saving when back button clicked

On my page i am trying to implement a recently viewed section on my home page.
The problem is when I append a new item to request.session["recently-viewed"], the item i just viewed gets deleted from the list when i load a new page.
The item view is a page which displays the details about a specific item. I want that particular item to be added and saved into a session variable. When the user visits any other page the session variable "recently-viewed" should be saved. Recently viewed items can then be displayed on the home page.
There is a similar question that has been asked but the only answer was a solution using javascript. If possible could solutions stay away from javascript.
views.py
def item(request, item_id):
if "recently-viewed" not in request.session:
request.session["recently-viewed"] = [item_id]
else:
request.session["recently-viewed"].append(item_id)
when in item view:
request.session["recently-viewed"] = ["item1", "item2"]
when another page is loaded:
request.session["recently-viewed"] = ["item1"]
Django, by default, only saves the session when a key has been deleted or assigned to. Because you are mutating a list you need to tell Django to save the session
request.session["recently-viewed"].append(item_id)
request.session.modified = True

DjangoCMS - multiple sites with shared pages

I'm trying to build several websites with DjangoCMS with some shared pages. Is it possible to create a page which is shared across all django Sites?
With a basic DjangoCMS configuration, when a page is published on a Site it does not appear on other Site. I am wondering if this is configurable in any way.
When looking at the code I've seen that the TreeNode is linked to a specific Site (https://github.com/divio/django-cms/blob/develop/cms/models/pagemodel.py#L52), so I guess that if it's possible it won't be that simple.
class TreeNode(MP_Node):
# [...]
site = models.ForeignKey(
Site,
on_delete=models.CASCADE,
verbose_name=_("site"),
related_name='djangocms_nodes',
db_index=True,
)
# [...]
I'd be fine with an external module if DjangoCMS does not handle this, or even some ideas or lead of how to approach this, I really don't have a clue.
Thanks a lot!
I've solved this issue with some ugly patches in the DjangoCMS code itself.
from cms import cms_menus
from cms.templatetags import cms_tags
from cms.utils import page
# Ugly-patching DjangoCMS so that a page from another Django Site can be displayed
def new_get_page_from_path(site, path, preview=False, draft=False):
"""
Resolves a url path to a single page object.
Returns None if page does not exist
"""
from cms.models import Title
titles = Title.objects.select_related('page__node')
published_only = not draft and not preview
if draft:
titles = titles.filter(publisher_is_draft=True)
elif preview:
titles = titles.filter(publisher_is_draft=False)
else:
titles = titles.filter(published=True, publisher_is_draft=False)
titles = titles.filter(path=(path or ''))
titles = list(titles.iterator())
for title in titles:
if title.page.node.site_id != site.pk:
continue
if published_only and not page._page_is_published(title.page):
continue
title.page.title_cache = {title.language: title}
return title.page
# This is the different part from the DjangoCMS code:
# re do the same loop, but this time ignore the Site filtering
for title in titles:
if published_only and not page._page_is_published(title.page):
continue
title.page.title_cache = {title.language: title}
return title.page
return
# Ugly-patching DjangoCMS so that a page from another Django Site can fetched
# using {% pageurl %} (for example)
def new_get_page_queryset(site, draft=True, published=False):
from cms.models import Page
if draft:
pages = Page.objects.drafts().on_site(site)
if pages:
return pages
if published:
pages = Page.objects.public().published(site)
if pages:
return pages
pages = Page.objects.public().on_site(site)
if pages:
return pages
# This is the different part from the DjangoCMS code:
# re do the same logic, but this time ignore the Site filtering
if draft:
return Page.objects.drafts()
if published:
return Page.objects.public().published()
return Page.objects.public()
page.get_page_from_path = new_get_page_from_path
page.get_page_queryset = new_get_page_queryset
cms_tags.get_page_queryset = new_get_page_queryset
cms_menus.get_page_queryset = new_get_page_queryset
Then I'm importing this file before the urlpatterns variable in the urls.py file (warned you it was ugly).
What DjangoCMS does is that it tries to find the Page with the Site given in the request. If the Page is not found, DjangoCMS would raise a 404 error, but in our case we re-do the same query but this time without the Site filter.
This way a Page created on one Site is accessible on each sub-Site.
I then needed some Page accessible on every Site with most of the content identical, but SOME different content. I've solved this issue by using the static_placeholder tag which can be specified per sub-Site. http://docs.django-cms.org/en/latest/reference/templatetags.html#static-placeholder

Dynamic URL and Jinja templates

I've been trying to create user interface to filter out results from my database. Important thing is that I want the filters to be 'additive'. So if user selects one filter, page redirects and displays results. After that, user can select another filter and the results are narrowed down to both filters. This should continue for any number of filters.
This is how it looks now
#app.route('/')
def home():
kind = request.args.get('kind')
price = request.args.get('price')
category = request.args.get('category')
filters = {}
if price is not None: filters['params.price'] = {'$lt' : int(price) }
if kind is not None: filters['kind'] = kind
if category is not None: filters['category'] = category
posts = db.collection.find(filters)
return render_template('home.html', posts=posts)
and links for my hrefs using jinja2 templates look like
<li>Label</<li>
<li>Label</li>
<li>Label</li>
... many more similar links
Currently this works as override for the URL. If I click any of those links it just replaces the whole URL and uses the variable from the link.
first link: http://127.0.0.1/?kind=m
second link: http://127.0.0.1/?price=5000
third link: http://127.0.0.1/?category=p
What I'd like it to do is to append the query - If i click any of the links it remembers previous selected filters and 'adds' last clicked link. Below I show how I expect for it to work.
first link: http://127.0.0.1/?kind=m
second link: http://127.0.0.1/?kind=m?price=50000
second link: http://127.0.0.1/?kind=m?price=50000?category=p
You could pass all filter values (None initially) to the view, and add them as arguments to the url_for calls. Filters which are None will not be included in the links.

Managing django urls

I am making a personal site. I have a blog page(site.com/blog), where I have a list of my blog posts. If I want to check a blog post simple enough I can click it and the code:
<h1>{{ obj.topic_title }}</h1>
will get me there. Also if I want to go to my contacts page (site.com/contacts). Easy enough I click nav contacs button and I go there
Contacts
but if I enter a blog post (site.com/blog/1), I am using the same template and if I want to go to my contacts page I have to yet again click the
Contacts
link, but that will port me to a 404 page site.com/blog/contacts . How do I deal with this problem without harcoding every single page
Use the built-in Django url template tag, which takes the view name and returns an absolute path to it.
Returns an absolute path reference (a URL without the domain name) matching a given view and optional parameters.
You can give it a view name and any of its view parameters as well. This is much better than how you link to the blog page:
{% url 'blog-view-name' obj.id %}
This ensures that if you ever change the structure of your views, it will still not break your links.

Categories

Resources