I want to setup filter in templates
I have filtered objects that I wanted, and now how can I setup the template?
So I can filter objects through dropdown?
What I'have done so far
#login_required
def list_jobs(request):
assigned_jobs = Job.objects.filter(assign_to=request.user).order_by('-date_created')
created_jobs = Job.objects.filter(user=request.user).order_by('-date_created')
completed_jobs = Job.objects.filter(completed=False).order_by('-date_completed')
return render(request, 'jobs/list.html', {'created_jobs': created_jobs, 'assigned_jobs': assigned_jobs,
'completed_jobs': completed_jobs})
Example Something like this:
<select id="id">
{% for i in assigned_jobs %}
<option value="{{ i.id }}">{{ i.name }}</option>
{% endfor %}
</select>
Related
I'm doing a search form where an user selects the category and the type of product which is a choice field of the Product model, product_type = models.CharField(max_length=30, choices=TYPE, default='Physical'). I can get the categories but not the choices in TYPE to add to the form.
choices.py
TYPE = [
('PHYSICAL', _('Physical')),
('DIGITAL', _('Digital')),
]
views.py
from .choices import TYPE
def is_valid_queryparam(param):
return param != '' and param is not None
def FilterView(request):
qs = Product.objects.all()
categories = Category.objects.all()
ptypes = Product.product_type.all() # The problem line
category = request.GET.get('category')
ptype = request.GET.get('ptype')
if is_valid_queryparam(category) and category != 'Choose...':
qs = qs.filter(category__name=category)
if is_valid_queryparam(ptype) and ptype != 'Choose...':
qs = qs.filter(product_type=ptype)
context = {
'queryset': qs,
'categories' : categories,
'ptypes' : ptypes,
}
return render(request, 'categories/display_query.html', context)
base.html
<div>
<h3>Advanced Search</h3>
<form method="GET" action="{% url 'filter-view' %}">
<div>
<label for="category">Category</label>
<select name="category">
<option selected>Choose...</option>
{% for cat in categories %}
<option value="{{ cat }}">{{ cat }}</option>
{% endfor %}
</select>
</div>
<div>
<label for="ptype">Product type</label>
<select name="ptype">
<option selected>Choose...</option>
{% for type in ptype %}
<option value="{{ type }}">{{ type }}</option>
{% endfor %}
</select>
</div>
<button type="submit">Search</button>
</form>
</div>
display_query.html
{% extends 'products/base.html' %}
{% block content %}
<div>
<ul>
{% for product in queryset %}
<li>
{{ product.title }}
<span>Author: {{ product.author.username }}</span>
</li>
{% endfor %}
</ul>
</div>
{% endblock content %}
You can use the given code:
p_types_keys = [i[0] for i in TYPE]
p_types_values = [i[1] for i in TYPE]
ptype_dict = dict(zip(p_types_keys, p_types_values))
In the line will return all the keys of your "TYPE"
The second line will return all the keys of your "TYPE"
The Third line will return the key-value pair of your types to add form.
I have a problem in my project.
I want to create a ChoiceField to be categories and subcategories in the models.py file. Well, it must be that I chose the first choice and the second according to the index of the place. For example, like the car and its models, according to the brand I chose in the First ChoiceField, you look at its models in the second field. İn Django.
Welcome to Stack Overflow! I've done this in the past by creating my own widget, a CategorizedSelect, with some jQuery. Here's the code and comments:
my_app/widgets.py:
from django.forms.widgets import Select
class CategorizedSelect(Select):
"""
This widget takes a dict of categories and a list of dicts for items.
It renders two drop downs, the first of the categories, which then
populates the second drop down with the items in that category via
the jQuery chained library.
For example:
# Prepare data for chained dropdown field for security
intl_stocks = Security.objects.filter(
active=True,
security_type__short_name="INT",
).select_related(
'exchange',
).order_by(
'exchange__name', 'name',
)
exchanges, securities = OrderedDict(), []
for intl_stock in intl_stocks:
exchanges[intl_stock.exchange.id] = intl_stock.exchange.name
securities += [{'category_id': intl_stock.exchange.id, 'id': intl_stock.id, 'name': intl_stock.name}]
security = forms.ModelChoiceField(
queryset=Security.objects.none(),
widget=CategorizedSelect(
categories=exchanges,
items=securities,
),
)
"""
template_name = 'my_app/widgets/categorized_select.html'
def __init__(self, attrs=None, categories=None, items=None):
super().__init__(attrs)
self.categories = categories
self.items = items
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
context['categories'] = self.categories
context['items'] = self.items
return context
my_app/templates/my_app/widgets/categorized_select.html:
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-chained/1.0.1/jquery.chained.min.js"></script>
<select id="chain_select_{{ widget.name }}_id" name="chain_select_{{ widget.name }}" class="form-control">
<option value="">--</option>
{% for id, name in categories.items %}
<option value="{{ id }}">{{ name }}</option>
{% endfor %}
</select>
<br>
<select name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
<option value="">--</option>
{% for item in items %}
{% comment %}
If we match the initial value set by the Django form, we need to
set SELECTED on the child, and use jQuery to force the category parent
drop down to the proper selection as well. We will force item.id to a
string since the widget.value.0 is always a string.
{% endcomment %}
{% if item.id|stringformat:"i" == widget.value.0 %}
<option value="{{ item.id }}" class="{{ item.category_id }}" SELECTED>{{ item.name }}</option>
<script>
var selected_category_id = {{ item.category_id }}
</script>
{% else %}
<option value="{{ item.id }}" class="{{ item.category_id }}">{{ item.name }}</option>
{% endif %}
{% endfor %}
</select>
<script>
$("#{{ widget.attrs.id }}").chained("#chain_select_{{ widget.name }}_id");
if(selected_category_id) {
$('#chain_select_{{ widget.name }}_id').val(selected_category_id).change();
$('#chain_select_{{ widget.name }}_id').prop("disabled", true);
$('#{{ widget.attrs.id }}').prop("disabled", true);
}
</script>
The example in the comment shows how this was done for a set of international stocks; the international exchanges were the categories, with the stocks themselves being the items. Good luck!
I am currently doing a search using forms
This is my views.py
class HomeView(generic.ListView):
model = Consultant
template_name = 'sogeti/home.html'
def get_queryset(self):
query = self.request.GET.get('q')
if query:
return Consultant.objects.filter(
Q(first_name__icontains=query) |
Q(last_name__icontains=query) |
Q(group__title_techGroup__contains=query) |
Q(practices__title_practice__contains=query)
)
else:
return Consultant.objects.all()
and this is my home.html
<form action="" method="get" class="form-inline">
<input type="text" name="q" placeholder="Enter Keyword" value="{{ request.GET.q }}" class="form-control">
<select name="filter" class="form-control">
<option value="all">All</option>
<option value="people">People</option>
<option value="certification">Certification</option>
<option value="skillset">Skillset</option>
</select>
<input type="submit" value="Search" class="btn btn-default">
</form>
<ol style="padding-left: 15px">
{% for consultant in object_list %}
<li>
{{ consultant.first_name }}, {{ consultant.last_name }} </br>
Technology Group: {{ consultant.group }} </br>
Primary Practice: {{ consultant.practices }}
<hr style="margin-left: 0">
</li>
{% endfor %}
</ol>
My first problem is that when it tries to search something (Eg: bla) that is not in my database, it returns a blank screen. Nothing at all. Tried searching but could not get any answers.
My second problem is how am I able to specify my search using HTML select and options to filter. As you can see from my home.html I have the tag with option value but no idea how to utilize it for Django.
Thank you so much for your help! Really appriciate it.
About first issue, you actually can double check the object_list before iterate over it, e.g:
{% if object_list %}
<ul>
{% for item in object_list %}
<p>{{item.value}}</p>
{% endfor %}
</ul>
{% else %}
<p>Empty!</p>
{% endif %}
If you're unable to search, then double check your query by using some tools like django-debug-toolbar to take a look at the queries.
About the second question, I recommend you to use Django Form instead, like so:
Create forms.py:
from django.forms import Form, ChoiceField, CharField
class FilterForm(Form):
FILTER_CHOICES = (
('all', 'All'),
('people', 'People'),
('certification', 'Certification'),
('skillset', 'Skillset'),
)
search = CharField(required=False)
filter_field = ChoiceField(choices=FILTER_CHOICES)
Then your view (views.py):
class HomeView(ListView):
model = Consultant
template_name = 'home.html'
def get_queryset(self):
query = self.request.GET.get('search')
filter_field = self.request.GET.get('filter_field')
# Do your filter and search here
return Consultant.objects.all()
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['form'] = FilterForm(initial={
'search': self.request.GET.get('search', ''),
'filter_field': self.request.GET.get('filter_field', ''),
})
return context
and finally your template (templates/home.html):
<form class="row">
{{ form.search }}
{{ form.filter_field }}
<input type="submit" class="btn btn-default" value="Search">
</form>
Hope that would be helpful!
For the first issue, if there is nothing in the database it is returning an empty queryset so if you include
{% if object_list %}
do stuff
{% else %}
No results match your search
{% endif %}
For the second it depends on what you're trying to do, but let's suppose it is a
specific field you're searching.
search_choice = self.request.GET.get('filter')
choice_query = Q(search_field=search_choice)
Then simply add this to your query
views.py
class HomeView(generic.ListView):
model = Consultant
template_name = 'sogeti/home.html'
def get_queryset(self):
queryset = super().get_queryset()
q = self.request.GET.get('q')
if q:
queryset = queryset.filter(
Q(first_name__icontains=q) |
Q(last_name__icontains=q) |
Q(group__title_techGroup__contains=q) |
Q(practices__title_practice__contains=q)
)
filter = self.request.GET.get('filter')
if filter == 'people':
pass
elif filter == '...':
# do sth
return queryset
html
<form action="" method="get" class="form-inline">
<input type="text" name="q" placeholder="Enter Keyword" value="{{ request.GET.q }}" class="form-control">
<select name="filter" class="form-control">
<option value="all">All</option>
{% if request.GET.filter == 'people' %}
<option value="people" selected>People</option>
{% else %}
<option value="people">People</option>
{% endif %}
{% if request.GET.filter == 'certification' %}
<option value="certification" selected>Certification</option>
{% else %}
<option value="certification">Certification</option>
{% endif %}
{% if request.GET.filter == 'skillset' %}
<option value="skillset" selected>Skillset</option>
{% else %}
<option value="skillset">Skillset</option>
{% endif %}
</select>
<input type="submit" value="Search" class="btn btn-default">
</form>
<ol style="padding-left: 15px">
{% for consultant in object_list %}
<li>
{{ consultant.first_name }}, {{ consultant.last_name }} </br>
Technology Group: {{ consultant.group }} </br>
Primary Practice: {{ consultant.practices }}
<hr style="margin-left: 0">
</li>
{% empty %}
No result match q=`<b>{{ request.GET.q }}</b>` & filter=`{{ request.GET.filter }}`
{% endfor %}
</ol>
The order of dictionary is varied each time although using OrderedDict.
I wrote in views.py
from collections import OrderedDict
from django.shortcuts import render
import json
def index(request):
with open('./data/data.json', 'r') as f:
json_dict = json.loads(f.read())
json_data = OrderedDict()
json_data = json_dict
return render(request, 'index.html', {'json_data': json_data})
and I wrote in index.html
<html>
<head>
<script type="text/javascript" src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/chosen/1.8.2/chosen.jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/chosen/1.4.2/chosen.jquery.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/chosen/1.4.2/chosen.css">
</head>
<body>
<select id="mainDD" data-placeholder="Choose" class="chzn-select" style="width:600px;">
{% for i in json_data.items.values %}
<option>{{ i }}</option>
{% endfor %}
</select>
<select name="type" id="type1">
{% for j in json_data.type1.values %}
<option>{{ j }}</option>
{% endfor %}
</select>
<select name="type" id="type2">
{% for k in json_data.type2.values %}
<option>{{ k }}</option>
{% endfor %}
</select>
<select name="type" id="type3">
{% for l in json_data.type3.values %}
<option>{{ l }}</option>
{% endfor %}
</select>
<select name="type" id="type4">
{% for m in json_data.type4.values %}
<option>{{ m }}</option>
{% endfor %}
</select>
</script>
</body>
</html>
Variable of i&j&k&l&m has result of json_data,but this dictionary of json_data is not the order.For example i has {'items': [{'---': '---', ‘A’: ‘a’, ‘B’: ‘b’, ‘C: ‘c’, ‘D’: ‘d’}]} but the order of drill down is b=>c=>d=>a.I want to show a =>b=>c=>d .I think this can be done by using OrderedDict() but it is wrong.How should i fix this?What should I write it?
All you've done is overwrite your parsed JSON with an OrderedDict object; that doesn't do anything useful at all.
Instead, as the documentation shows, you can pass that class as the object_pairs_hook parameter:
json_dict = json.loads(f.read(), object_pairs_hook=OrderedDict)
Your idea is correct. Using OrderedDict will preserve the order of the items in the dictionary. However there is an error in your code:
json_data = OrderedDict()
json_data = json_dict
First you initialize json_data as OrderedDict, but in the second statement you override the variable and assign it the value of json_dict.
Daniel Roseman was faster than me and gave you better answer, I'd just naively done this:
json_data = OrderedDict(json_dict)
There is a multiple checkbox in template, if value contain in render the choice will checked by default. It works well with 1.10.
form.py:
class NewForm(forms.Form):
project = forms.ModelMultipleChoiceField(
widget=forms.CheckboxSelectMultiple,
queryset=Project.objects.filter(enable=True)
)
template:
{% for p in form.project %}
<label for="{{ p.id_for_label }}">
<input type="checkbox" name="{{ p.name }}" id="{{ p.id_for_label }}"
value="{{ p.choice_value }}"
{% if p.choice_value|add:"0" in form.project.initial %} checked{% endif %}>
<p>{{ p.choice_label }}</p>
</label>
{% endfor %}
views.py:
def order_start(request, order_id):
if request.method == 'POST':
form = NewForm(request.POST)
if form.is_valid():
order.end_time = timezone.now()
order.save()
order.project = form.cleaned_data['project']
order.save()
return HttpResponsec(order.id)
else:
form = NewForm(initial={
'project': [p.pk for p in order.project.all()],
})
return render(request, 'orders/start.html', {'form': form, 'order': orderc})
When I upgrade to Django 1.11, {{ p.name }} and {{ p.choice_value }} return nothing. I know 1.11 has removed choice_value, but how to solve this problem?
1.10 https://docs.djangoproject.com/en/1.10/_modules/django/forms/widgets/
1.11 https://docs.djangoproject.com/en/1.11/_modules/django/forms/widgets/
As #L_S 's comments. I debug with dir(form), all value contained in form.project.data here's the correct code:
{% for choice in form.project %}
<labelc for="{{ choice.id_for_label }}">
<input type="checkbox" name="{{ choice.data.name }}" id="{{ choice.id_for_label }}"
value="{{ choice.data.value }}"{% if choice.data.selected %} checked{% endif %}>
{{ choice.data.label }}
</label>
{% endfor %}