django pagination with search not working - django

MultiValueDictKeyError at /search/
'search'
Request Method: GET
Request URL: http://127.0.0.1:8000/search/?page=2
Django Version: 4.1.5
Exception Type: MultiValueDictKeyError
Exception Value:
'search'
Exception Location: C:\Python311\Lib\site-packages\django\utils\datastructures.py, line 86, in getitem
Raised during: blogs.views.search
Python Executable: C:\Python311\python.exe
Python Version: 3.11.0
views.py
def search(request):
search = request.POST["search"]
blog_search = Blog.objects.filter(Q(title__icontains=search) | Q(description__icontains=search))
paginator = Paginator(blog_search, 5)
page_number = request.GET.get('page')
blogs = paginator.get_page(page_number)
return render(request,"frontend/searchblogs.html",{"blogs":blogs})
<div class="container">
<nav class="navbar navbar-light bg-light justify-content-end">
<form class="form-inline" method="post" action="{%url 'search' %}">
{% csrf_token %}
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" name="search" id="search" >
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</nav>
<h4 class="mt-4"></h4>
{% for blog in blogs %}
<div class="card mb-3" >
<div class="row no-gutters">
<div class="col-md-4">
<img src="{{blog.cover_img.url}}" alt="..." class="bd-placeholder-img card-img-top img-fluid">
</div>
<div class="col-md-8">
<div class="card-body">
<h4 class="card-title text-truncate">{{blog.title}}</h4>
<p class="card-text text-truncate">{{blog.description}}</p>
<div class="d-flex justify-content-between align-items-center">
<p class="text-muted">{{blog.date.date}}</p>
<p class="text-muted"><i class="fa fa-eye pl-2"></i> {{blog.view}}</p>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-end">
{% if blogs.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ blogs.previous_page_number }}">Previous</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1" aria-disabled="True">Previous</a>
</li>
{% endif %}
{% if blogs.number|add:'-4' > 1 %}
<li class="page-item"><a class="page-link" href="?page={{ blogs.number|add:'-5' }}">…</a></li>
{% endif %}
{% for i in blogs.paginator.page_range %}
{% if blogs.number == i %}
<li class="page-item active" aria-current="page">
<span class="page-link">
{{ i }}
<span class="sr-only">(current)</span>
</span>
</li>
{% elif i > blogs.number|add:'-5' and i < blogs.number|add:'5' %}
<li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if blogs.paginator.num_pages > blogs.number|add:'4' %}
<li class="page-item"><a class="page-link" href="?page={{ blogs.number|add:'5' }}">…</a></li>
{% endif %}
{% if blogs.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ blogs.next_page_number }}">Next</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1" aria-disabled="True">Next</a>
</li>
{% endif %}
</ul>
</nav>
</div>

Use:
views.py
def search(request):
search = request.GET["search"]
...
You're passing a GET request through the server (the ?page part of the URL), so you'll have to retrieve the data using request.GET['name']. You should also change your form method to GET. For a search, there isn't a good reason to use POST.
<div class="container">
<nav class="navbar navbar-light bg-light justify-content-end">
<form class="form-inline" method="GET" action="{%url 'search' %}">
{% csrf_token %}
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" name="search" id="search" >
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</nav>
...
</div>
Here's the documentation: https://docs.djangoproject.com/en/4.1/ref/request-response/#querydict-objects
Form methods: https://www.w3schools.com/tags/ref_httpmethods.asp
If you must use the POST method, refer to this question: Paginating the results of a Django forms POST request

Related

Wagtail - Image Optimisation ( How to do it with static and dynamically added image files?)

so I want to run my site with my images displayed as quickly as possible and the images are added either by giving the {% static "path/to/image.jpg" %} or by rendering the image tag for wagtail image uploads {% image image_name original as img %}. Currently, the site has considerably slowed down with lots of images, especially loading time for the images. Any possible options to optimise those images through Wagtail? It would be of great help. Thanks
An example with images loading by static tag as well as image tag in wagtail.
{% extends "base.html" %} {% load static wagtailcore_tags wagtailimages_tags %} {% block extra_css %}
<link rel="stylesheet" href="{% static 'css/technologies.css' %}"> {% endblock %} {% block nav_projects %} class="active" {% endblock %}{% block content %}
<div class="inner-page project-page">
<div class="inner-hero" style="background-image: url(/static/images/banner_a/project_bg.png);background-attachment: fixed;">
<div class="container-fluid inner-top-section mt-0 px-5">
<div class="row flex-lg-row-reverse align-items-center g-5 py-5 p-4">
<div class="col-10 col-sm-8 col-lg-6">
</div>
<div class="col-lg-6">
<h1 class="display-5 fw-bold lh-1 mb-3">{{self.header_title}}</h1>
<p class="lead">{{self.meta_content}}</p>
<!-- <div class="d-grid gap-2 d-md-flex justify-content-md-start">
<span class="txt">Know more</span>
</div> -->
</div>
</div>
</div>
</div>
{% if page.dblock_content %}
<div class="d-block sub-hero position-relative" style="background-color: #4A4A4A">
<div class="bg-set-wrp">
<div class="left-bg-set">
<img class="zoom-fade" src="{% static 'images/project-elm/elm-1.png' %}" alt="">
</div>
<div class="bottom-bg-set">
<img class="zoom-fade" src="{% static 'images/project-elm/elm-4.png' %}" alt="">
</div>
<div class="right-bg-set">
<img class="zoom-fade" src="{% static 'images/project-elm/elm-3.png' %}" alt="">
</div>
<div class="center-bg-set">
<img class="zoom-fade" src="{% static 'images/project-elm/elm-3.png' %}" alt="">
</div>
<div class="top-bg-set">
<img class="zoom-fade" src="{% static 'images/project-elm/elm-3.png' %}" alt="">
</div>
<div class="right-top-bg-set">
<img class="zoom-fade" src="{% static 'images/project-elm/elm-2.png' %}" alt="">
</div>
</div>
<div class="container px-4 py-5 position-relative" style="z-index: 11">
<div class="row align-items-center" style="padding: 6rem 0;">
<div class="col-lg-12 text-white">
<p class="lead1">
<span class="qte1">"</span> {% for block in page.dblock_content %} {% include_block block %} {% endfor %}
<span class="qte2">"</span>
</p>
</div>
</div>
</div>
</div>
{% endif %}
<div class="project-display px-5 project-box">
{% if posts.paginator.num_pages > 1 %}
<div class="d-flex justify-content-end blog-item">
<nav aria-label="...">
<ul class="pagination">
{% if posts.has_previous %}
<li class="page-item">
<a class="page-link" style="color: #000;" href="?page={{ posts.previous_page_number }}" tabindex="-1" aria-disabled="true">Previous</a>
</li>
{% endif %} {% for page_num in posts.paginator.page_range %}
<li class="page-item {% if page_num == posts.number %} active{% endif %}"><a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a></li>
{% endfor %} {% if posts.has_next %}
<li class="page-item">
<a href="?page={{ posts.next_page_number }}" class="page-link">
Next
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
<div class="container-fluid">
{% endif %} {% for post in posts %}
<div class="align-items-center pt-5 row {% if forloop.counter|divisibleby:2 %} flex-lg-row-reverse {% endif %}">
<div class="col-10 col-lg-5 col-sm-8 m-0 popannime">
{% image post.project_image original as pr_img %}
<img src="{{pr_img.url}}" class="d-block mx-lg-auto img-fluid" alt="" width="700" height="500" loading="lazy" style="width: 290px;">
</div>
<div class="col-lg-7 m-0">
<h1 class="lh-2 mb-3">{{ post.project_list_title }} </h1>
<p class="lead">{{post.project_list_subtitle}} </p>
<div class="d-grid d-md-flex gap-2">
<span class="txt">Know more</span><span class="arrow"></span>
</div>
</div>
</div>
{% endfor %}
</div>
{% if posts.paginator.num_pages > 1 %}
<div class="d-flex justify-content-end blog-item">
<nav aria-label="...">
<ul class="pagination">
{% if posts.has_previous %}
<li class="page-item">
<a class="page-link" style="color: #000;" href="?page={{ posts.previous_page_number }}" tabindex="-1" aria-disabled="true">Previous</a>
</li>
{% endif %} {% for page_num in posts.paginator.page_range %}
<li class="page-item {% if page_num == posts.number %} active{% endif %}"><a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a></li>
{% endfor %} {% if posts.has_next %}
<li class="page-item">
<a href="?page={{ posts.next_page_number }}" class="page-link">
Next
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
{% endif %}
</div>
</div>
{% endblock %}

Using django-filter generic view and paginate_by, how to build the pagination urls?

First time using django-filter, so I might be using it wrong.
I'm basically trying to mimic Django Admin filtering, using a generic FilterView, setting filterser_class and adding paginate_by
filters.py
class ProductFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='icontains', label='Filter by Title')
categories = django_filters.AllValuesFilter(
field_name='categories__name',
label="Filter by Category",
widget=django_filters.widgets.LinkWidget(attrs={'class': 'list-menu'}),
)
brand = django_filters.AllValuesFilter(
field_name='brand__short_name',
label="Filter by Brand",
widget=django_filters.widgets.LinkWidget(attrs={'class': 'list-menu'}),
)
class Meta:
model = Product
fields = ['categories', 'brand', 'name']
views.py
class ProductFilterView(FilterView):
filterset_class = ProductFilter
paginate_by = 20
product_filter.html
<section class="section-content padding-y">
<div class="container">
<div class="row">
<aside class="col-md-3">
<div class="card">
<form method="get">
{% csrf_token %}
{% for field in filter.form.visible_fields %}
<article class="filter-group">
<header class="card-header">
<a href="#" data-toggle="collapse" data-target="#collapse_1" aria-expanded="true" class="">
<i class="icon-control fa fa-chevron-down"></i>
<h6 class="title">{{ field.label_tag }}</h6>
</a>
</header>
<div class="filter-content collapse show" id="collapse_1">
<div class="card-body">
{{ field }}
</div> <!-- card-body.// -->
</div>
</article> <!-- filter-group .// -->
{% endfor %}
<input type="submit" class="btn btn-block btn-primary" value="Filter"/>
</form>
</div> <!-- card.// -->
</aside> <!-- col.// -->
<main class="col-md-9">
<header class="border-bottom mb-4 pb-3">
<div class="form-inline">
<span class="mr-md-auto">{{ filter.qs | length }} products found </span>
</div>
</header><!-- sect-heading -->
<div class="row">
{% for obj in page_obj %}
<div class="col-md-4">
<figure class="card card-product-grid">
<div class="img-wrap">
<img src="/media/{{ obj.productimage_set.first.image|default:'products/missing.png' }}">
</div> <!-- img-wrap.// -->
<figcaption class="info-wrap">
<div class="fix-height">
{{ obj.name }}
<div class="price-wrap mt-2">
<span class="price">$ {{ obj.price }}</span>
<!--<del class="price-old">$1980</del>-->
</div>
</div>
Add to cart
</figcaption>
</figure>
</div> <!-- col.// -->
{% endfor %}
</div> <!-- row end.// -->
<nav class="mt-4" aria-label="Page navigation">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item"><a class="page-link" href="?page=1">First</a></li>
<li class="page-item"><a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" href="#">First</a></li>
<li class="page-item disabled"><a class="page-link" href="#">Previous</a></li>
{% endif %}
{% for page in page_obj.paginator.page_range %}
{% ifequal page page_obj.number %}
<li class="page-item active"><a class="page-link">{{ page }}</a></li>
{% else %}
<li class="page-item"><a class="page-link" href="?page={{ page }}">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item"><a class="page-link" href="?page={{ page_obj.next_page_number }}">Next</a></li>
<li class="page-item"><a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">Last</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" href="#">Next</a></li>
<li class="page-item disabled"><a class="page-link" href="#">Last</a></li>
{% endif %}
</ul>
</nav>
</main> <!-- col.// -->
</div>
</div> <!-- container .// -->
</section>
It almost works as intended.
But those pagination urls will reset any filtering.
I'm considering using {{ request.GET.param1 }} to rebuild all the filters, but it doesn't feel like the right way to solve this.
I've tried a solution using context processors, as described by José L. Patiño here:
How to paginate Django with other get variables?
But it leads to another problem: it's possible to reapply filtering after advancing some pages, and it results in invalid pages.
Any suggestions?

Django - Pagination

I'm working on To-Do App.
I have two kinds of data,
Upcoming To-do Item and
Completed To-do Items.
So, I'm filtering data in views.py as upcoming items and completed items. I want to display them on the same page using pagination. I'm getting result too but if upcoming item completed in page-1 I was unable to visit page-2 because upcoming item for page-2 was empty, but I have items on completed items. I couldn't see that.
views.py
#login_required(login_url='login')
def home(request):
todo_form = TodoForm()
current = timezone.now()
todo_items_upcoming = Todo.objects.filter(user_id=request.user, completed=False).order_by('-date_created')
todo_items_completed = Todo.objects.filter(user_id=request.user, completed=True)
pagi1 = Paginator(todo_items_upcoming, 4)
pagi2 = Paginator(todo_items_completed, 4)
page_num = request.GET.get('page')
page_num2 = request.GET.get('page')
page_obj = pagi1.get_page(page_num)
page_obj2 = pagi2.get_page(page_num2)
if request.method == "POST":
todo_form = TodoForm(request.POST)
if todo_form.is_valid():
data = todo_form.cleaned_data.get('title')
obj = Todo.objects.create(date_created=current, title=data, user_id=request.user)
context = {'todo_form':todo_form, 'page_obj':page_obj, 'page_obj2':page_obj2}
return render(request, 'todo/main.html', context)
main.html
{% extends 'todo/index.html' %}
{% load crispy_forms_tags %}
{% block content %}
<nav aria-label="...">
<ul class="pagination justify-content-center">
<!-- pagination - previous pages -->
{% if page_obj.has_previous or page_obj2.has_previous %}
<li class="page-item">
{% if page_obj.has_previous %}
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" tabindex="-1">«</a>
{% else %}
<a class="page-link" href="?page={{ page_obj2.previous_page_number }}" tabindex="-1">«</a>
{% endif %}
</li>
{% endif %}
<!-- pagination - current page -->
<li class="page-item active">
<a class="page-link" href="?page={{ page_obj.number }}">{{ page_obj.number }}</a>
</li>
<!-- pagination - Next pages -->
{% if page_obj.has_next or page_obj2.has_next %}
<li class="page-item">
{% if page_obj.has_next %}
<a class="page-link" href="?page={{ page_obj.next_page_number }}">»</a>
{% else %}
<a class="page-link" href="?page={{ page_obj2.next_page_number }}">»</a>
{% endif %}
</li>
{% endif %}
</ul>
</nav>
<div class="center-column">
<h2 class="heading" style="text-align: center;">Hello {{ request.user.username }}, Here's your ToDo List</h2>
<form action="" method="POST" id='form-create'>
{% csrf_token %}
<div style="text-align: center;">
{{ todo_form.title }}
<button type="submit" class="form-control btn btn-primary mb-3 mr-sm-2">Add Items</button>
</div>
</form>
<h4 class="heading" style="text-align: center;">Upcoming ToDo Items</h4><br>
<div class="row">
<div class="col" id="upcomItem">
<ul class="list-group" id="upcomingItems">
{% for i in page_obj %}
<li class="list-group-item list-group-item-primary mb-2" id="upcomingItem">{{ i.title }}
<div class="float-right">
<button type="submit" class="btn-sm btn-danger ml-2 mt-2 mr-2 mb-1">Delete</button>
</div>
<div class="float-right">
<button type="submit" class="btn-sm btn-success ml-2 mt-2 mr-2 mb-1" id="update_btn">Update</button>
</div>
<div class="float-right">
<button type="submit" class="btn-sm btn-dark ml-2 mt-2 mr-2 mb-1" id="completed_btn">Completed</button>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
<hr style="border-top: 1px solid #999; ">
<div class="row">
<div class="col">
<h4 class="heading" style="text-align: center;">Completed ToDo Items</h4>
<ul class="list-group" id='compItems'>
{% for i in page_obj2 %}<hr>
<li class="list-group-item list-group-item-primary mb-2" id="upcomingItem">{{ i.title }}
<div class="float-right">
<button type="submit" class="btn-sm btn-danger ml-2 mt-2 mr-2 mb-1">Delete</button>
</div>
<div class="float-right">
<button type="submit" class="btn-sm btn-success ml-2 mt-2 mr-2 mb-1" >Update</button>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endblock %}
At first I have used or in template tags in if condition I got this error. Error Message occurs when I try to add new to-do item
I tried and operator in template tags I didn;'t even get page-2 link eventhough I have upcoming items and no extra completed items.
Use or operator as #Willem pointed. And you active link href must be {{ page_obj.number }} instead {{ page_obj.page_number }}:
<li class="page-item active">
<a class="page-link" href="?page={{ page_obj.number }}">{{ page_obj.number }}</a>
</li>
As you can see your error EmptyPage raised in your template at line 18
Your conditions should be a disjunction of the conditions of the paginators, so or instead of and:
{% if page_obj.has_previous or page_obj2.has_previous %}
…
{% endif %}
the same for .has_next. The previous and next page then should be handled by checking which page object has a next page, so:
{% if page_obj.has_next or page_obj2.has_next %}
<li class="page-item">
{% if page_obj.has_next %}
<a class="page-link" href="?page={{ page_obj.next_page_number }}">»</a>
{% else %}
<a class="page-link" href="?page={{ page_obj2.next_page_number }}">»</a>
{% endif %}
</li>
{% endif %}
That being said, I'm not sure this provides the best user experience. Perhaps it is better to make two separate paginations (so work with ?pagedone=…&pagetodo=…).

Keep django pagination and search filters when submitting form on same page

I have a view which has a list of all customers on one side, which also has working pagination and search/ filter functionality.
Where I am stuck is, if I have a form & button on my list to select a customer to view on the other side of the page, and it clears my current pagination page and any filters applied to the customer list when I run the function to pick up the selected customer.
How can I have a form action = "{% url 'some_function' %}" and keep the pagination and search.
http://localhost:8000/clients/clean?page=8&search_term=nsw
Current view:
def customer_list_clean(request, selected = None):
if selected != None:
selected = Client_Customer.objects.get(id = selected)
try:
msg = request.GET['search_term']
except:
msg = ""
clients = Client_Customer.objects.distinct().filter(Q(customer_name__contains = msg) |
Q(physical_address__street_address__contains = msg) |
Q(physical_address__suburb__suburb__contains = msg) |
Q(physical_address__suburb__post_code__contains = msg) |
Q(physical_address__suburb__region__state_abb__contains = msg)
).order_by('customer_name')
if msg:
messages.success(request, (f"Customer records filtered by: {msg}"))
found = clients.count()
if clients.filter(confirmed= False).count()>0:
messages.info(request, (f"Some customers records have not been validated!"))
#Pagination
page = request.GET.get('page', 1)
paginator = Paginator(clients, 25)
try:
clients = paginator.page(page)
except PageNotAnInteger:
clients = paginator.page(1)
except EmptyPage:
clients = paginator.page(paginator.num_pages)
if selected != None:
context ={'clients':clients, 'found':found, 'msg':msg, 'selected':selected}
else:
context ={'clients':clients, 'found':found, 'msg':msg}
return render(request, 'clients/client_list_clean.html',context)
Clients are displayed in a table (nothing special)
client_list_clean.html
{%extends 'base.html'%}
{%block body%}
<div style="margin-left: 1.2em;margin-right: 1.2em;">
<h1>Admin | Edit Customers</h1>
<h4>({{found}} records found)</h4>
<hr>
<form action = "{% url 'clients:customer_list_clean' %}" enctype="multipart/form-data" class="form-inline my-2 my-lg-0">
<!-- {% csrf_token %} -->
<input class="form-control mr-sm-2" type="search" placeholder="Search records" aria-label="Search" name = "search_term">
<button class="btn btn-outline-info my-2 my-sm-0" type="submit">Search / Clear</button>
</form>
<hr>
{%include 'client_pagination.html'%}
<div class="row">
<div class="col">
<div class="container-split" style ="height: 50vh; margin-top:3px;">
<table class = "table">
<thead>
<tr>
<th scope="col">Customer <button class="btn btn-outline-info my-2 my-sm-0" type="button">Asc</button> <button class="btn btn-outline-info my-2 my-sm-0" type="button">Desc</button></th>
<th scope="col" style="text-align:center">Type</th>
<th scope="col" style="text-align:center">Address
<button class="btn btn-outline-info my-2 my-sm-0" type="button">Asc</button> <button class="btn btn-outline-info my-2 my-sm-0" type="button">Desc</button></th>
<th scope="col" style="text-align:center">Details</th>
</tr>
<thead>
<tbody>
{% for client in clients %}
<tr>
{% if client.confirmed == False %}
<td style="background-color:#d5edf6">{{client.customer_name}}</td>
<td style="text-align:center; background-color:#d5edf6">{{client.client_type}}</td>
<!-- <td>{{client.confirmed}}</td> -->
{% for add in client.physical_address_set.all %}
<td style="text-align:right; background-color:#d5edf6">{{add}}</td>
<td style="text-align:right; background-color:#d5edf6">
<form class="" action="{% url 'clients:customer_list_clean' %}" enctype="multipart/form-data" >
<button class="btn btn-outline-info my-2 my-sm-0" type="submit">View</button>
</form>
</td>
{% endfor %}
{% else %}
<td>{{client.customer_name}}</td>
<td style="text-align:center">{{client.client_type}}</td>
{% for add in client.physical_address_set.all %}
<td style="text-align:right">{{add}}</td>
<td style="text-align:right">Something</td>
{% endfor %}
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<hr>
</div>
</div>
<div class="col">
<div class="row">
<h3>Merge Stuff</h3>
</div>
<div class="row">
<p>some merge stuff</p>
{{selected.customer_name}}
</div>
<hr>
<div class="row">
<h3>Detail stuff</h3>
</div>
<div class="row">
<br>
<p>Some stuff</p>
</div>
</div>
</div>
</div>
{%endblock body %}
Pagination is in another template and "included" on the html page
pagination.html:
{% if clients.has_other_pages %}
<ul class="pagination">
{% if clients.number >= 11 %}
<li class="page-item"><a class="page-link" href="?page=1 &search_term={{ msg }}">FIRST</a></li>
{% endif %}
{% if clients.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ clients.previous_page_number }}&search_term={{ msg }}" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</a>
</li>
{% endif %}
{% if clients.number|add:'-9' > 1 %}
<li class="page-item"><a class="page-link" href="?page={{ clients.number|add:'-10' }}&search_term={{ msg }}"><em>- 10</em></a></li>
{% endif %}
{% for i in clients.paginator.page_range %}
{% if clients.number == i %}
<li class="page-item active">
<a class="page-link" href="#">{{ i }}<span class="sr-only">(current)</span></a>
</li>
{% elif i > clients.number|add:'-10' and i < clients.number|add:'10' %}
<li class="page-item"><a class="page-link" href="?page={{ i }}&search_term={{ msg }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if clients.paginator.num_pages > clients.number|add:'9' %}
<li class="page-item"><a class="page-link" href="?page={{ clients.number|add:'10' }}&search_term={{ msg }}"><em>+ 10</em></a></li>
{% endif %}
{% if clients.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ clients.next_page_number }}&search_term={{ msg }}" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">Next</span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">Next</span>
</a>
</li>
{% endif %}
</ul>
{% endif %}
It's all good, I worked it out.
Using an a tag instead of a form to add an additional term to the url.
<a class="btn btn-outline-info my-2 my-sm-0" href="?page={{ clients.number }}&search_term={{ msg }}&selected={{ client.id }}">View</a>
views.py
try:
print(request.GET['selected'])
except:
pass
I am yet to do something with the selected id, but I now have it in the function none the less.

Django: logic not well applied in template using permissions (perm

I develop a Django app
I have specifics permission on 2 differents models
I use these permissions to display or not some link in a navbar
but I have an unexpected behavior I do not understand
below the html code with Django logic
code between should not be display with one of my user that do not have the two permissions
I control to be sure permissions are effectively False but even without permissions, links 'Randomize a patient' and 'Reallocate a patient' are displayed
what is wrong in my logic?
I give at the end, the entire navbar html code
partial template :
{% if user.is_authenticated %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{% trans 'Randomization' %}</a>
<div id="randomize" class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
{% if user_allowed_to_randomize and user_can_randomize or allowed_to_randomize and can_randomize %}
**<!-- SHOULD NOT BE DISPLAY - START-->**
{% if perms.randomization.can_randomize %}
<a class="dropdown-item" href="{% url 'randomization:randomisation_edit' %}">{% trans 'Randomize a patient' %}</a>
{% endif %}
{% if perms.randomization.can_reallocate %}
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="{% url 'randomization:reallocate_edit' %}">{% trans 'Reallocate a treatment' %}</a>
{% endif %}
**<!-- SHOULD NOT BE DISPLAY - END-->**
{% endif %}
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="#">{% trans 'Pharmacy' %}</a>
</li>
{% endif %}
complete template :
{% load static %}
{% load i18n %}
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4">
<div class="container">
<a class="navbar-brand" href="">Intense TBM</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li>
</li>
<li class="nav-item active">
<a class="nav-link" href="{% url 'home' %}">{% trans 'Home' %}<span class="sr-only">(current)</span></a>
</li>
{% if user.is_authenticated %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{% trans 'Randomization' %}</a>
<!--Vérification stock via requete ajax stock avant d'afficher les menus deroulants-->
<div id="randomize" class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
<!--affichage par défaut pour les profils utilisateurs 'Site'-->
<!--OU SI DROIT ATTRIBUE APRES SELECTION LISTE SITE-->
{% if user_allowed_to_randomize and user_can_randomize or allowed_to_randomize and can_randomize %}
{% if perms.randomization.can_randomize %}
<a class="dropdown-item" href="{% url 'randomization:randomisation_edit' %}">{% trans 'Randomize a patient' %}</a>
{% endif %}
{% if perms.randomization.can_reallocate %}
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="{% url 'randomization:reallocate_edit' %}">{% trans 'Reallocate a treatment' %}</a>
{% endif %}
{% endif %}
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="#">{% trans 'Pharmacy' %}</a>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link" href="#">{% trans 'Contact' %}</a>
</li>
</ul>
{% if user.is_authenticated %}
<ul class="navbar-nav">
<!--Vérification stock via requete ajax stock avant d'afficher le message d'alerte-->
<li class="nav-item" id="alerte">
<!--affichage par défaut pour les profils utilisateurs 'Site'-->
{% if user_allowed_to_randomize and not user_can_randomize or allowed_to_randomize and not can_randomize %}
<a class="nav-link" id="informations" href="#" style="color:red; padding-right: 50px;"><strong>{% trans 'Insufficient stock' %}</strong></a>
{% endif %}
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ user.username }}
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
<!--Sélection d'un site-->
<form id="site_selectionne" method="POST" class="post-form">
{% csrf_token %}
<div class="form-group">
<!--data-randomization-url utilisé pour passer l'url dans le fichier .js qui ne considère pas les tag dajgo-->
<!--data-randomization-url récupéré pour définir l'url de la requete ajax-->
<select name="site" class="form-control" id="site" data-randomization-url="{% url 'randomization:stock' %}">
<option></option>
{% for site in sites %}
<!--récupération du site sélectionné middleware/context_processor-->
{% if site.sit_abr == site_selectionne %}
<option value="{{ site.sit_ide }}" selected>{{ site.sit_nom }} - {{ site.reg.pay.pay_nom }}</option>
{% else %}
<option value='{{ site.sit_ide }}'>{{ site.sit_nom }} - {{ site.reg.pay.pay_nom }}</option>
{% endif %}
{% endfor %}
</select>
</div>
</form>
<!---->
<a class="dropdown-item" href="{% url 'password_change' %}">{% trans 'Change password' %}</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="{%url 'logout'%}">{% trans 'Logout' %}</a>
</div>
</li>
</ul>
{% else %}
<form class="form-inline my-2 my-lg-0">
{% trans 'Login' %}
</form>
{% endif %}
</div>
</div>
</nav>