search data with multiple values in django - python

Want to filter data with multiple values in django.Currently i can only take two value from html but only one value filtering
This is my views code
p = request.GET.getlist('passout',[])
c = request.GET.getlist('course',[])
s = request.GET.getlist('skill',[])
search_variables = {}
if p:
for l in p:
search_variables['passout__yearofpassing__contains'] = l
print("#####",p)
if s:
for j in s:
search_variables['skill__skill_name__contains'] = j
if c:
for k in c:
search_variables['course__course_name__contains'] = k
print("##kk",k)
datas_list = Student.objects.filter(
**search_variables, status="Active").order_by('id')
This is html code
<div class="col col-sm-3" style="margin-right:-80px;">
<select class="selectpicker" id="passout" name="passout" placeholder="Select YOP" multiple >
{% for j in p %}<option value="{{ j }}" selected>{{i.yearofpassing}}</option> {% endfor %}
{% for i in yr %}
<option value="{{i.yearofpassing}}">{{i.yearofpassing}}</option>
{% endfor %}
</select>
</div>
<div class="col col-sm-3" style="margin-right:-80px;" >
<select class="selectpicker" name="course" id="course" placeholder="Select Course" multiple >
{% for j in c %}<option value="{{ j }}" selected >{{i.course_name}}</option> {% endfor %}
{% for i in cr %}
<option value="{{i.course_name}}">{{i.course_name}}</option>
{% endfor %}
</select>
</div>
<div class="col col-sm-3" style="margin-right: -350px;">
<select class="selectpicker" id="skill" name="skill" placeholder="Select Skills" multiple >
{% for j in s %}<option value="{{ j }}" selected >{{i.skill_name}}</option>{% endfor %}
{% for i in sl %}
<option value="{{i.skill_name}}" >{{i.skill_name}}</option>
{% endfor %}
</select>
</div>
<button id="search4" style="margin-left: 320px; " class="au-btn btn-info btn-sm" >Search </button>
<button id="search" style="margin-left: 1px; " class="au-btn btn-info " > <i style="font-size:medium; margin-bottom: 1px; " class='fas fa-sync'></i></button>
in this image i search student with year of passout 2019 it shows a result
if i search with two or three values it shows nothing but in db the students are present

the thing is that you don't have that data for all search filters because Django filter work with AND operator and in your image you said give me a result that happened in 2019 AND 2020 and this is not possible.
the filter is working you just need to store the right data.

Related

How to take multiple inputs from the same input field and display each value individually?

I have input field like this :
<form action="worldle" method="post">
{% csrf_token %}
<input type="text" name="text" placeholder="Guess the Flag"><br>
<input type="submit" name="Submit">
I want to display each value in the list. For that i've created a list like this :
<div class="card" style="width: 18rem;">
<ul class="list-group list-group-flush">
<li class="list-group-item">{{ values }}</li>
<li class="list-group-item">{{ values }}</li>
<li class="list-group-item">{{ values }}</li>
</ul>
</div>
I don't know how to display second value and third value in the second and third list .
views.py is :
def worldle(request):
value= request.POST.get('text',False)
values = value.lower()
world= Worldle.objects.all()
rand=random.choice(world)
bcd= rand.title.lower()
result = ''
if values == bcd:
messages.info(request, 'Correct')
result = 'correct'
else:
result='Wrong'
return render(request,'worldle.html',{'rand':rand,'values':values,'rst':result})
So I want to display multiple values in the list from the same input field. How do I achieve this? Thanks

modify the value of paginate_by for all pages

I have a follow-up question on the answer to Change value for paginate_by on the fly
I added the following in the HTML
<form method="GET">
<select name="paginate_by" id="">
<option value="5">5</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="50">50</option>
</select>
<input type="submit" value="Paginate">
</form>
and this function in my ListView class
class ReviewPostListView(ListView):
model = Reviews
template_name = 'reviews/reviews.html'
context_object_name = 'rows'
ordering = ['id']
paginate_by = 5
def get_paginate_by(self, queryset):
return self.request.GET.get("paginate_by", self.paginate_by)
it is working great, and the paginate_by is added to the URL. My problem is when I click on the second page it goes back to 5.
This is my pagination HTML
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?page=1">First</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-info mb-4" href="?page={{ num }}">{{num}}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class="btn btn-outline-info mb-4" href="?page={{ num }}">{{num}}</a>
{% endif %}
{% endfor %}
{%if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?page={{page_obj.next_page_number}}">Next</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
{% endif %}
{% endif %}
What is the pythonic of keeping the paginate_by (if exists) parameter in the URL when looping on the pages?
Using {{ request.GET.paginate_by }}, you can access the paginate_by query parameters in your template.
So, your pagination HTML will look like:
{% if is_paginated %}
{% firstof request.GET.paginate_by "5" as paginate_by %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?page=1&paginate_by={{ paginate_by }}">First</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-info mb-4" href="?page={{ num }}">{{num}}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class="btn btn-outline-info mb-4" href="?page={{ num }}">{{num}}</a>
{% endif %}
{% endfor %}
{%if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?page={{page_obj.next_page_number}}&paginate_by={{ paginate_by }}">Next</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.paginator.num_pages }}&paginate_by={{ paginate_by }}">Last</a>
{% endif %}
{% endif %}
firstof is will set the value of paginate_by to the query parameter or 5, which will be the default value.
You can create a template tag which will handle the query params for you.
Here are two simple tags
#register.simple_tag(takes_context=True)
def add_get_param(context, **kwargs):
"Used to add/replace query parameters to the current URL."
params = context["request"].GET.dict()
params.update(kwargs)
return "?{}".format(urlencode(params))
#register.simple_tag(takes_context=True)
def remove_get_param(context, *args):
"Used to remove query parameters from the current URL."
params = context["request"].GET.dict()
for key in args:
params.pop(key, None)
return "?{}".format(urlencode(params))
And your HTML will look like
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?paginate_by={% add_get_param page=1 %}">First</a>
<a class="btn btn-outline-info mb-4" href="{% add_get_param page=page_obj.previous_page_number %}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-info mb-4" href="{% add_get_param page=num %}">{{num}}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class="btn btn-outline-info mb-4" href="?paginate_by={{ paginate_by}}&page={{ num }}">{{num}}</a>
{% endif %}
{% endfor %}
{%if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="{% add_get_param page=page_obj.next_page_number %}">Next</a>
<a class="btn btn-outline-info mb-4" href="{% add_get_param page={{ page_obj.paginator.num_pages %}">Last</a>
{% endif %}
{% endif %}
With this whatever was already there in the query params will continue to be there, only the page will be changed. So this works if you decide to add more params such as for filtering.
You can try this in your HTML template:
<select name="paginate_by" onchange="location = this.value;">
<option value="">select</option>
<option value="?paginate_by=5&{{page_obj.number}}">5</option>
<option value="?paginate_by=10&{{page_obj.number}}">10</option>
<option value="?paginate_by=20&{{page_obj.number}}">20</option>
<option value="?paginate_by=50&{{page_obj.number}}">50</option>
</select>
Pass the paginate_by object into the html and add it to the pagination links. see below code:
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?paginate_by={{ paginate_by}}&page=1">First</a>
<a class="btn btn-outline-info mb-4" href="?paginate_by={{ paginate_by}}&page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-info mb-4" href="?paginate_by={{ paginate_by}}&page={{ num }}">{{num}}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class="btn btn-outline-info mb-4" href="?paginate_by={{ paginate_by}}&page={{ num }}">{{num}}</a>
{% endif %}
{% endfor %}
{%if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?paginate_by={{ paginate_by}}&page={{page_obj.next_page_number}}">Next</a>
<a class="btn btn-outline-info mb-4" href="?paginate_by={{ paginate_by}}&page={{ page_obj.paginator.num_pages }}">Last</a>
{% endif %}
{% endif %}

How to increment variable in Django template?

I was making a grid and need to declare the variable and increment it.
{% for new, des, i, link, published, author in mylist %}
{% if x == 1 %}
<div class="col-md-6">
<div class="h-100 mt-2 row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">
<div class="col p-4 d-flex flex-column position-static">
<strong class="d-inline-block mb-2 text-primary">World</strong>
<h5 class="mb-0">{{new}}</h5>
<div class="mb-1 text-muted">{{published}}</div>
<p class="card-text mb-auto">{{des}}</p>
Continue reading
</div>
<div class="col-auto d-none d-lg-block">
<img class="bd-placeholder-img" src="{{i}}" width="200" height="250" >
</div>
</div>
</div>
{% endif %}
{% endfor %}
Help me to declare variable x and increment it like x+1 inside the template
I was trying {% with x=0 %} but that's not working
Try this below:
{% set x = 0 %}
{% for new, des, i, link, published, author in mylist %}
{% set x = x + 1 %}
{% if x == 1 %}
<div class="col-md-6">
<div class="h-100 mt-2 row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">
<div class="col p-4 d-flex flex-column position-static">
<strong class="d-inline-block mb-2 text-primary">World</strong>
<h5 class="mb-0">{{new}}</h5>
<div class="mb-1 text-muted">{{published}}</div>
<p class="card-text mb-auto">{{des}}</p>
Continue reading
</div>
<div class="col-auto d-none d-lg-block">
<img class="bd-placeholder-img" src="{{i}}" width="200" height="250" >
</div>
</div>
</div>
{% endif %}
{% endfor %}
django has a {{ forloop.counter }}. You can use this.

iterate trough a forms in dictionary passed from view to html in python with jinja

I would appreciate your help in the below problem:
I need to use 3 different models in a python app which I want the user to populate from a HTML form. I want to use model forms and I pass all the three different form in one dictionary (see my views.py):
def new_sales_trip(request):
if request.method == "POST":
Restaurant_Form = RestaurantForm(request.POST)
SalesEvent_Form = SalesEventForm(request.POST)
NextAction_Form = NextActionForm(request.POST)
if Restaurant_Form.is_valid() and SalesEvent_Form.is_valid() and NextAction_Form.is_valid():
Restaurants = Restaurant_Form.save()
SalesEvents = SalesEvent_Form.save(False)
NextActions = NextAction_Form.save(False)
SalesEvents.restaurants = Restaurants
SalesEvents.save()
NextActions.restaurants = Restaurants
NextActions.save()
return redirect('/')
else:
allforms = {
'Restaurant_Form': Restaurant_Form,
'SalesEvent_Form': SalesEvent_Form,
'NextAction_Form': NextAction_Form,
}
return render(request, 'sales/SalesTrip_form.html', allforms)
else:
Restaurant_Form = RestaurantForm()
SalesEvent_Form = SalesEventForm()
NextAction_Form = NextActionForm()
c = {}
c.update(csrf(request))
allforms = {
'Restaurant_Form': Restaurant_Form,
'SalesEvent_Form': SalesEvent_Form,
'NextAction_Form': NextAction_Form,
}
return render(request, 'sales/SalesTrip_form.html', allforms)
So far it works - however I don't know how to use this dictionary to iterate trough in my template so I shouldn't reference all the form by name separatelly. I try to to do something like this:
{% for key, value in allforms.items %}
{% for field in value %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <!--this gonna be only displayed if there is an error in it-->
<span class="text-danger small">{{ field.errors }}</span>
</div>
<label class="control-label col-sm-2">{{ field.label_tag }}</label>
<div class="col-sm-10"> <!--this gonna be displayed if there is no error -->
{{ field }}
</div>
</div>
{% endfor %}
{% endfor %}
Unforunatelly it is not rendering anything but a blank page. If I try the .items() property than it says:
Could not parse the remainder: '()' from 'allforms.items()'
You just need to add () to the end of items:
e.g.,
{% for key, value in allforms.items() %}
{% for field in value %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <!--this gonna be only displayed if there is an error in it-->
<span class="text-danger small">{{ field.errors }}</span>
</div>
<label class="control-label col-sm-2">{{ field.label_tag }}</label>
<div class="col-sm-10"> <!--this gonna be displayed if there is no error -->
{{ field }}
</div>
</div>
{% endfor %}
{% endfor %}

How to set/get variable in Jinja2

I can't understand, why this code is not work:
{% set t_c = 'param_1' %}
<div class="col-sm-9">
<select id="category" name="category" class="form-control " required>
<option></option>
{% for c in categories %}
{% if c.id|string == org.category.id %}
{% set t_c = 'param9' %}
<option value="{{ c.id }}" selected>{{ c.name }} </option>
{% else %}
<option value="{{ c.id }}">{{ c.name }} </option>
{% endif %}
{% endfor %}
</select>
</div>
<input id="category_h" name="category_h" type="hidden" value="{{ t_c }}">
Why t_c in last line is 'param_1', when condition {% if c.id|string == org.category.id %} is true?
Thanks.
UPDATE
I have fast solution on JavaScript with jQuery+Select2 like:
var category = $("#category"),
category_h = $("#category_h");
category.select2();
category_h.val(category.find("option:selected").text());
t_c = 'param9' is local to the scope of the for loop
There are workarounds to extend beyond inner block scope

Categories