How to get multiple choices from template in views.py - django

In my template i have a multiple-choice-object like this:
<form action="/hmi/give_trend3/" method="get">
<p>
<select name="n" size="3" multiple="multiple">
{% for tag in tags %}
<option>{{ tag.name }}</option><br>
{% endfor %}
</select>
</p>
</form>
and i want to get all the values (of the multiple-choice) in my
views.py:
def give_trend3(request):
v = request.GET['v']
b = request.GET['b']
nn = request.GET['n'] ....
but in the value nn I find only the last value of the choices.
How do I do that?

Try this,
vals = request.GET.getlist("n", '')
Also bind the id to the options in your template,
<select name="n" size="3" multiple="multiple">
{% for tag in tags %}
<option value="{{ tag.id }}">{{ tag.name }}</option><br>
{% endfor %}
</select>

Related

convert string value to integer in Django template

In home.html
<div class="container">
<div class="row">
<div class="col-md-6">
<h3>Select products:</h3>
<form id="selectProduct" role="search" method="get" action="{% url 'home' %}">
<select name="parameters" data-placeholder="Choose products" class="chosen-select" multiple tabindex="4">
{% for p in productnames %}
{% if k == p %}
<option value="{{ p.productnames }}" selected> {{ p.productnames }} </option>
{% else%}
<option value="{{ p.id }}"> {{ p.productnames }} </option>
{% endif %}
{% endfor %}
</select><br/>
<label for="submit"></label><button id="submit" type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
<div class="row"></div><br />
<h3> Distribution of sales in the products:</h3>
</div>
</div>
{% for p in productList %}
{% for pin in productnames %}
<p>{{pin.id}} {{p}}</p>
{% if p == pin.id %}
<p>exists</p>
{% else %}
<p>not exist</p>
{% endif %}
{% endfor %}
{% endfor %}
<p>{{ productList }}</p>
in this html file 'p' always returns a string value for ex: it returns like '10' instead of 10. all i want is to convent this '10' to 10 or convert returned other p_in value to 10 to '10'.
in views.py
def productList(request):
if request.method == 'GET':
p = request.GET.get('parameters')
print(p)
#k = request.GET('parameters[]')
productnames = Products.objects.all()
context = {
'productList': p, 'productnames': productnames,
}
return render(request, 'home.html', context)
I tried to convert the values of the p in product list to integer. because it dosen't mactch the format with pin.id
You filter the queryset in the template using if-else which is not ideal. Instead you should perform this filtering in the view itself. Also your parameters is a select tag which may have multiple selected values yet you use .get('parameters') which will only give you one value instead you should use the getlist method [Django docs] of the QueryDict:
def productList(request):
if request.method == 'GET': # Do you even need to check this? You appear to only use a GET request...
p = request.GET.getlist('parameters')
productnames = Products.objects.all()
filtered_products = Products.objects.filter(pk__in=p)
context = {
'productList': p, 'productnames': productnames, 'filtered_products': filtered_products
}
return render(request, 'home.html', context)
In the template your loop would simply become:
{% for product in filtered_products %}
{{ product.productnames }}
{% endfor %}
Note: You should use a form class instead of manually making a form. See Building a form in
Django.
Also a models name should be singular hence instead of
Products you should name it Product. In general in
your code you also break various naming conventions in Python, I would
suggest you to look at PEP 8 -- Style Guide for Python
Code
In views.py
def productList(request):
if request.method == 'GET':
p = request.GET.getlist('parameters')
print(p)
#k = request.GET('parameters[]')
productnames = Products.objects.all()
context = {
'productList': p, 'productnames': productnames,
}
# --- logic later for chart ------
return render(request, 'home.html', context)
In home.html
<div class="container">
<div class="row">
<div class="col-md-6">
<h3>Select products:</h3>
<form id="selectProduct" role="search" method="get" action="{% url 'home' %}">
<select name="parameters" data-placeholder="Choose products" class="chosen-select" multiple tabindex="4">
{% for p in productnames %}
{% if k == p %}
<option value="{{ p.productnames }}" selected> {{ p.productnames }} </option>
{% else%}
<option value="{{ p.id }}"> {{ p.productnames }} </option>
{% endif %}
{% endfor %}
</select><br/>
<label for="submit"></label><button id="submit" type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
<div class="row"></div><br />
<h3> Distribution of sales in the products:</h3>
</div>
</div>
{% for p in productList %}
{% for pin in productnames %}
<p>{{pin.id|stringformat:"s"}} {{p}}</p>
{% if p == pin.id|stringformat:"s" %}
<p>exists</p>
{% else %}
<p>not exist</p>
{% endif %}
{% endfor %}
{% endfor %}
<p>{{ productList }}</p>
Note {{value|stringformat:"s"}} can be used to convert integer value to string value

Problem with getting the select option data

I am having problem to get the selected data from a form. Here is my form
<form action="#" method="GET">
{% csrf_token %}
<select name="country" id="selectcountries" class="custom-select">
<option>Select country</option>
{% for item in countries %}
<option val="{{ item.name }}"> {{ item.name }} </option>
{% endfor %}
</select>
<select name ="city" id="selectcities" class="custom-select">
<option>Select city</option>
</select>
<select class="custom-select" name="option" >
<option selected> Tourist Spot </option>
<option> Hotel </option>
<option> Restaurent </option>
</select>
<button type="submit" class="btn tour-btn"><i class="fa fa-search pr-2" aria-hidden="true"></i> Search </button>
</form>
And my views.py is
def advanceSearch(request):
country = request.GET.get('country')
city = request.GET.get('city')
option = request.GET.get('option')
if request.method == "GET" :
if country:
message = 'q= %s' % country
else:
message = 'Empty'
else:
message = 'oops'
return HttpResponse(message)
HTTPResponse always give me empty message even after with passing values by the form. I want to get the data from this form but i cant.
I tried to replicate the scenario with the provided code, and I think your search view is not getting executed. You have provided {% url 'advanceSearch' %} in the anchor tag inside button. It should be in the action attribute of the form.
<form action="{% url 'advanceSearch' %}" method="GET">
{% csrf_token %}
<select name="country" id="selectcountries" class="custom-select">
<option>Select country</option>
{% for item in countries %}
<option val="{{ item.name }}"> {{ item.name }} </option>
{% endfor %}
</select>
<select name ="city" id="selectcities" class="custom-select">
<option>Select city</option>
</select>
<select class="custom-select" name="option" >
<option selected> Tourist Spot </option>
<option> Hotel </option>
<option> Restaurent </option>
</select>
<button type="submit" class="btn tour-btn"><i class="fa fa-search pr-2" aria-hidden="true"></i>Search</button>
</form>

Extra chars in django template

I've some code like this:
<select id="form.category}}">
{% for category in form.category %}
<option value="{{ category }}"></option>
{% endfor %}
</select>
And result is:
https://zapodaj.net/940329c1516df.png.html
Why?
#edit
category = models.CharField(max_length=100, choices=get_categories())
def get_categories():
categories = (
("wydarzenia", "wydarzenia"),
("informacje", "informacje"),
("konkursy", "konkursy"),
("wycieczki", "wycieczki"),
("sport", "sport"),)
return categories
form.category is a field in model
The option looks empty because you are not showing anything inside the options tag. You need to display some labels for option tag. Do something like this if category is an object and it has attributes like id and name.
<select id="form.category">
{% for category in form.category %}
<option value="{{ category.id }}">{{category.name}}</option>
{% endfor %}
</select>
If category is a string or number do something like this
<select id="form.category">
{% for category in form.category %}
<option value="{{ category }}">{{category}}</option>
{% endfor %}
</select>
Bear in mind that form.category should be an iterable.

Access a list within a dict in request.POST

In my html I am dynamically generating drop-down options with the same name
<form action="{% url manageCsv %}" method="post">
{% csrf_token %}
<p>
<input type="hidden" name="doc_id" value="{{ doc_id }}">
{% for column in file_columns %}
Column {{ forloop.counter0|add:1 }}
<select name="columns">
<option value="blank"></option>
{% for column_value in file_columns %}
<option value="{{ column_value }}">{{ column_value }}</option>
{% endfor %}
</select>
{% endfor %}
</p>
<p>
<input type="submit" value="Submit" />
</p>
</form>
UPDATE:
My Views.py :
def manageCsv(request):
if request.method == 'POST':
file_id = request.POST['doc_id']
csvColumns = request.POST['columns']
print >> sys.stderr, csvColumns['columns']
return HttpResponseRedirect(reverse('index'))
In my view when I print my request.POST I get everythin I need :
<QueryDict: {u'csrfmiddlewaretoken': [u'lGlxVmiYI9xFb5bV7cJPrP9GR0t0LYTi'], u'doc_id': [u'14'], u'columns': [u'Organisation', u'Sum of products']}>
But the problem I am facing is that when I assign csvColumns = request.POST['columns'] , csvColumns prints out only Sum of products from the list and not the entire List [u'Organisation', u'Sum of products']
How can I get the entire list ? What have I missed ?
Any help on this would be great
Thanks in advance
Try to do it like this as explained in the docs:
csvColumns = request.POST.getlist('columns',None)
Hope this helps!

How do I iterate over the options of a SelectField in a template?

I have a select field in the form and now I need to iterate over options in this field.
{{ form.myselect }} gives me this:
<select name="myselect" id="id_myselect">
<option value="" selected="selected">---------</option>
<option value="2">Item 1</option>
<option value="3">Item 2</option>
...
</select>
Now I need to add some attributes to the options and because of that what I need is:
<select name="myselect" id="id_myselect">
{% for x in form.myselect %}
<option value="{{ x.id }}">{{ x.name }}</option>
{% endfor %}
</select>
but there is an error:
Caught TypeError while rendering: 'BoundField' object is not iterable
I tried form.myselect.all, form.myselect.option_set but it gives nothing
I've been struggling with this problem today and found the solution. Yes, you can iterate over options of the select tag directly in template. Here's how to do it in template:
<select id="id_customer" name="customer">
{% for x, y in form.fields.customer.choices %}
<option value="{{ x }}"{% if form.fields.customer.value == x %} selected{% endif %}>{{ y }}</option>
{% endfor %}
</select>
In this case I have a customer field in the form which has choices set up as follows:
class SomeForm(forms.Form):
customer = forms.ChoiceField(label=u'Customer')
def __init__(self, *args, **kwargs):
super(SomeForm, self).__init__(*args, **kwargs)
self.fields['customer'].choices = [(e.id, e.customer) for e in Customers.objects.all()]
Got it to work with:
<select name="myselect" class="i-can-add-my-own-attrs-now" id="id_myselect">
{% for id, name in form.myselect.field.choices %}
<option value="{{ id }}">{{ name }}</option>
{% endfor %}
</select>
BUT REALLY, a better way to do this is with django-widget-tweaks:
{% load widget_tweaks %}
{{ form.myselect|add_class:"i-can-haz-custom-classes-easily" }}
Doing it with django-widget-tweaks will also set the default 'selected="selected"' for you, which is super nice!
I do this way:
<select id="id_construction_type" name="construction_type" class="form-control input-md">
{% for value, key in form_urban.fields.construction_type.choices %}
<option value="{{ value }}"{% if form_urban.initial.construction_type == value %} selected {% endif %}>
{{ key }}
</option>
{% endfor %}
</select>
This is a cleaner solution, you can set the attributes using a custom Widget. This way you don't have to render the field manually:
class CustomSelectWidget(forms.Select):
def create_option(self, name, value, *args, **kwargs):
option = super().create_option(name, value, *args, **kwargs)
if value:
instance = self.choices.queryset.get(pk=value) # get instance
option['attrs']['custom_attr'] = instance.field_name # set option attribute
return option
class SomeForm(forms.ModelForm):
some_field = forms.ModelChoiceField(
queryset=SomeModel.objects.all(),
widget=CustomSelectWidget
)
With radio buttons in your template use.
<table>
{% for x,y in form.fields.Customer.choices %}
<tr>
<td><input id="id_Customer_{{x}}" {% if form.fields.Customer.value == x %}checked="checked"{% endif %} name="Customer" type="radio" value="{{x}}" /></td>
<td>{{ y }}</td>
</tr>
{% endfor %}
</table>