I want to show a button if the user is a superuser. I've found differents examples but my code doesn't work. The button doesn't appear. Anybody knows why?
views.py
def inici(request):
zones = Zona.objects.all()
return render_to_response('principal/inici.html', dict(zones=zones),
context_instance = RequestContext(request))
inici.html
{% if not user.is_authenticated %}
....
{% else %}
<ul>
<li class="nivell1">
Logout
</li>
<li class="nivell1">
<a class="nivell1" herf="#"> Configuració </a>
</li>
{% if request.user.is_superuser %}
<li class="nivell1">
Crear zona
</li>
{% endif %}
</ul>
{% endif %}
I only have a user in the database and he is a super user. I can see the "logout" button and the other one, but not the "crear zona" button.
You want this Generic view:
class IniciView(ListView):
template_name = 'principal/inici.html'
model = Zona
are the context processors in settings?
This is more redeable:
{% if user.is_authenticated %}
<ul>
<li class="nivell1">
Logout
</li>
<li class="nivell1">
<a class="nivell1" herf="#"> Configuració </a>
</li>
{% if user.is_superuser %}
<li class="nivell1">
Crear zona
</li>
{% endif %}
</ul>
{% else %}
...
{% endif %}
I've changed {% if request.user.is_superuser %} to {% if user.is_superuser %}
Related
There is new option to create pagination range - get_elided_page_range
https://docs.djangoproject.com/en/3.2/ref/paginator/#django.core.paginator.Paginator.get_elided_page_range
How should I use it? How can I set args? I am using CBV ListView.
I tried https://nemecek.be/blog/105/how-to-use-elided-pagination-in-django-and-solve-too-many-pages-problem but it didn't work for me.
I have 81 pages and current page is 10. Problem is I am always have range 1 2 3 4 ... 80 81
What am I doing wrong?
#views.py
class TrailersListView(ListView):
queryset = Trailer.objects.all()
paginate_by = 10
#template.html
{% for i in paginator.get_elided_page_range %}
{% if page_obj.number == i %}
<li class="active page-item">
<span class="page-link">{{ i }}</span>
</li>
{% else %}
{% if i == paginator.ELLIPSIS %}
<li class="page-item">
<span class="page-link">{{ paginator.ELLIPSIS }}</span>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endif %}
{% endfor %}
The page number is not passed to the "get_elided_page_range" method and it uses the default value (1) all the time. So I created a custom tag to pass it a number.
appname/templatetags/paginator_tags.py
from django import template
from django.core.paginator import Paginator
register = template.Library()
#register.simple_tag
def get_proper_elided_page_range(p, number, on_each_side=3, on_ends=2):
paginator = Paginator(p.object_list, p.per_page)
return paginator.get_elided_page_range(number=number,
on_each_side=on_each_side,
on_ends=on_ends)
template.html
{% load paginator_tags %}
{% get_proper_elided_page_range paginator page_obj.number as page_range %} <!-- here -->
{% for page_num in page_range %}
{% if page_obj.number == i %}
<li class="active page-item">
<span class="page-link">{{ i }}</span>
</li>
{% else %}
{% if i == paginator.ELLIPSIS %}
<li class="page-item">
<span class="page-link">{{ paginator.ELLIPSIS }}</span>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endif %}
{% endfor %}
You can add additional arguments, e.g:
{% get_proper_elided_page_range paginator page_obj.number 1 1 as page_range %}
If you are using a class-based view such as ListView in the question's example, then if you trigger pagination by setting the paginate_by member, the page_obj object is available in the get_context_data method. From this method, you can invoke get_elided_page_range on the Paginator to set extra context for the template being rendered.
Example:
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
page: Page = context['page_obj']
context['paginator_range'] = page.paginator.get_elided_page_range(page.number)
return context
You can then access paginator_range from within your template.
Usage note: this method returns a generator which yields either an int (which is a valid page number) or a str (…), which is not.
I implemented the Django pagination to slice the results of the search on my site.
# views.py
def search(request):
# Keywords
if 'keywords' in request.GET:
keywords = request.GET['keywords']
if keywords:
title_list_control_valve = queryset_list.filter(title__icontains=keywords).order_by('title')
description_list_control_valve = queryset_list.filter(description__icontains=keywords).order_by('description').distinct('description')
result_list_control_valves = list(chain(title_list_control_valve,
description_list_control_valve))
result_list_control_valves_2 = list(dict.fromkeys(result_list_control_valves))
paginator = Paginator(result_list_control_valves_2, 1)
page = request.GET.get('page')
paged_queries = paginator.get_page(page)
context = {
'queries': paged_queries,
}
return render(request, 'pages/search.html', context)
else:
return render(request, 'pages/search.html')
else:
return render(request, 'pages/search.html')
the URL of the site when showing search results is :
http://localhost:8000/pages/search/?keywords=something
It works perfectly fine on the first page only. From the second page on, it shows an empty page, and the URL of the site changes to:
http://localhost:8000/pages/search/?page=2
I link to other pages in the HTML as following:
<div class="col-md-12">
{% if queries.has_other_pages %}
<ul class="pagination">
{% if queries.has_previous %}
<li class="page-item">
«
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link">«</a>
</li>
{% endif %}
{% for i in queries.paginator.page_range %}
{% if queries.number == i %}
<li class="page-item active">
<a class="page-link">{{i}}</a>
</li>
{% else %}
<li class="page-item">
{{i}}
</li>
{% endif %}
{% endfor %}
{% if queries.has_next %}
<li class="page-item">
»
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link">»</a>
</li>
{% endif %}
</ul>
{% endif %}
</div>
The ?keywords=something part of the URL goes away.
is it the problem?
how to make the other page's link work too?
Add keywords to your GET params. For ex. href="?page={{queries.previous_page_number}}&keywords={{request.GET.keywords}}"
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 %}
I have a class based view that I am using to display a queryset in a table. I am also using a couple formsets to filter this queryset. I am using the get_queryset() method provided as part of the generic.ListView class to filter the diplayed results. Here is basically what my class looks like:
from django.views import generic
class UnifiedSingleSearch(generic.ListView):
template_name = 'app/foo.html'
model = MyModel
paginate_by = 30
def get_queryset(self):
if self.request.POST: # If we got here because of a search submission, filter
return MyModel.objects.filter('Some stuff base on the POST data')
return MyModel.objects.all() # Otherwise, just show everything
Because I am using a formset to submit multiple search criteria, I have to use a POST request. Upon initial submission of the form, the page reloads with a correctly filtered querset. However when I try to use my pagination controls, the POST request is thrown away and the page acts as if I am going to page#2 of MyModel.objects.all() instead of my filtered down subset.
How can I retain my filtered queryset when using pagination controls?
Here is the HTML for the pagination controls:
{% if is_paginated %}
<nav aria-label="Pagination nav">
<ul class="pagination">
{# Back a page #}
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">❮</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">❮</span>
</li>
{% endif %}
{# Page numbers #}
{% for i in paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item active">
<span class="page-link">{{ i }}
<span class="sr-only">(current)</span>
</span>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endfor %}
{# Next page #}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">❯</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">❯</span>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% else %}
<p>No MyModel objects found</p>
{% endif %}
Switching to a GET request was the answer. Pagination controls also had to be edited a bit to retain the passed querystring. They should all include {{ request.GET.urlencode }} and then you tack on the page logic to the end like usual. Ends up looking something like this:
<li class="page-item">
<a class="page-link" href="?{{ request.GET.urlencode }}&page={{ page_obj.next_page_number }}">❯</a>
</li>
I've been trying to construct my own tag for pagination - pagetag.
But when I render this:
{% if people.has_previous %}
<li><a href={% pagetag people.previous_page_number %}>«</a></li>
{% else %}
<li class="disabled">«</li>
{% endif %}
{% for page in people.paginator.page_range %}
{% if page == people.number %}
<li class="disabled">{{page}}</li>
{% else %}
<li><a href={% pagetag page %}>{{page}}</a></li>
{% endif %}
{% endfor %}
{% if people.has_next %}
<li><a href={% pagetag people.next_page_number %}>»</a></li>
{% else %}
<li class="disabled">»</li>
{% endif %}
I get folowing links on first page:
<li class="disabled">«</li>
<li class="disabled">1</li>
<li><a href=/?page=page>2</a></li>
<li><a href=/?page=page>3</a></li>
<li><a href=/?page=people.next_page_number>»</a></li>
Not the desired ?page=2 and so on.
def pagetag(parser, token):
tokens = token.split_contents()
print tokens
if len(tokens) < 1:
raise TemplateSyntaxError, "pagetag takes at least 1 arguments"
return PageNode(tokens[1].strip())
How to pass the arguments correctly?
Use simple tags. For example:
#register.simple_tag
def pagetag(page):
return '/?page=' + page
Then, in your view, make sure to use {{ }} instead of {% %}:
<li>{{page}}</li>
Note: It's not recommended to use a different tag just for prepending a simple string. Just do it like in the documentation.