How to display a tree in select2? - django

I have a Categories tree (MP_Node). It is necessary to display them in the form of a tree at the select2.
models.py
class Category(MP_Node):
....
forms.py
class ProductCreateForm(forms.ModelForm):
class Meta:
model = Product
fields = (
...., 'category', ....
)
def __init__(self, *args, **kwargs):
super(ProductCreateForm, self).__init__(*args, **kwargs)
self.fields['category'].empty_label = None
self.fields['category'] = ModelChoiceField(queryset=Category.objects.all(), widget=forms.Select(
attrs={'class': 'select2', 'style': 'width: 165px'}))
html
<div class="field inline select">
<label for="id_category" class="subhead">Категория:</label>
<select name="category" style="width: 165px" required="" class="select2 select2-hidden-accessible" id="id_category" tabindex="-1" aria-hidden="true">
<option value="" selected="">---------</option>
<option value="1">Food</option>
<option value="4">Meal</option>
<option value="2">Sweet</option>
<option value="3">Milk</option>
<option value="9">Sport</option>
<option value="6">Football</option>
<option value="7">Ball</option>
<option value="5">Form</option>
<option value="8">Shirt</option>
<option value="10">T-Shirt</option>
<option value="11">Attribute</option>
</select>
<span class="select2 select2-container select2-container--default select2-container--focus" dir="ltr" style="width: 165px;"><span class="selection"><span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-labelledby="select2-id_category-container"><span class="select2-selection__rendered" id="select2-id_category-container"><span class="select2-selection__placeholder"> </span></span><span class="select2-selection__arrow" role="presentation"><b role="presentation"></b></span></span></span><span class="dropdown-wrapper" aria-hidden="true"></span></span>
</div>
I get select
Food
Meal
Sweet
Milk
Sport
Football
Ball
Form
Shirt
T-Shirt
Attribute
Need to receive
Food
Meal
Sweet
Milk
Sport
Football
Ball
Form
Shirt
T-Shirt
Attribute
js
$('select').select2({
placeholder: " ",
minimumResultsForSearch: Infinity
});

Was looking for the same thing.
Found this: https://github.com/clivezhg/select2-to-tree
Compat: Select2 4+
Also looked at this, but did not use:
https://github.com/maliming/select2-treeview

Use django-select2 to display tree struture effectively

Related

Django Select2Widget not getting styled properly with crispy forms

I'm using the django-select2 package to implement Searchable Select on a ForeignKey field.
I was successful in getting the functionality to work by following the steps mentioned in the docs but I am having trouble with the styling.
To render my form I use crispy-forms. All the other widgets get rendered properly except the Select2Widget.
As can be seen in the above image, the height and width of the form element is not dynamic like other elements.
HTML code generated:
<div class=""> <select name="current_user" data-minimum-input-length="0" data-allow-clear="true" data-placeholder=""
class="select2widget form-control django-select2" required id="id_current_user">
<option value=""></option>
<option value="">---------</option>
<option value="4" selected>Arpita</option>
</select> </div>
</div>
<div id="div_id_device_admin" class="form-group"> <label for="id_device_admin" class=" requiredField">
Device admin<span class="asteriskField">*</span> </label>
<div class=""> <select name="device_admin" data-minimum-input-length="0" data-allow-clear="true" data-placeholder=""
class="select2widget form-control django-select2" required id="id_device_admin">
<option value=""></option>
<option value="">---------</option>
<option value="4" selected>Arpita</option>
</select> </div>
</div>
This is how I set the widget in ModelForm.
def __init__(self, *args, in_org, **kwargs):
...
self.fields['current_user'].widget = Select2Widget()
self.fields['current_user'].queryset = in_org.user_set.all()
I feel this is mostly an issue with CSS styling and I am unable to figure out the issue. Any help would be greatly appreciated.
For those who are looking for a solution (though I think it's not the best),
you can fix the layout issue by passing attrs={'data-width': '100%'}
e.g.
self.fields['current_user'].widget = Select2Widget(attrs={'data-width': '100%'})
or
current_user = forms.ChoiceField(
widget=ModelSelect2Widget(
model=User,
search_fields=['username__istartswith'],
attrs={'data-width': '100%'},
),
)

Django forms ChoiceField: how to add data attributes to input radios?

I have a form with a choicefield:
class CheckoutForm(forms.Form):
shipping_method = forms.ChoiceField(widget=forms.RadioSelect)
How can I add data attributes to every choice? Something like:
<ul id="id_shipping_method">
<li>
<label for="id_shipping_method_0">
<input class="form-control" id="id_shipping_method_0" name="shipping_method" type="radio" value="C" data-method="courier"> Express courier</label></li>
<li>
<label for="id_shipping_method_1">
<input checked="checked" class="form-control" id="id_shipping_method_1" name="shipping_method" type="radio" value="yy" data-method="shop">In shop</label></li>
</ul>
Edit: Reread the question, updated a few things
A bit messy, but this should get you on the right track. You need to override some of the rendering components of the RadioSelect.
from django import forms
CHOICES = (('C','Express courier'),('yy','In shop'), ('h','By hand'))
class MyRadioChoiceInput(forms.widgets.RadioChoiceInput):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
method = {'C': 'courier', 'yy': 'shop', 'h': 'hand'}.get(self.choice_value)
self.attrs['data-method'] = method
class MyRadioFieldRenderer(forms.widgets.ChoiceFieldRenderer):
choice_input_class = MyRadioChoiceInput
class MyRadioSelect(forms.RadioSelect):
renderer = MyRadioFieldRenderer
class CheckoutForm(forms.Form):
shipping_method = forms.ChoiceField(choices=CHOICES, widget=MyRadioSelect(attrs={'class': 'form-control'}))
Example:
a = CheckoutForm()
for x in a:
print(x)
Result:
<ul id="id_shipping_method">
<li><label for="id_shipping_method_0"><input class="form-control" data-method="courier" id="id_shipping_method_0" name="shipping_method" type="radio" value="C" /> Express courier</label></li>
<li><label for="id_shipping_method_1"><input class="form-control" data-method="shop" id="id_shipping_method_1" name="shipping_method" type="radio" value="yy" /> In shop</label></li>
<li><label for="id_shipping_method_2"><input class="form-control" data-method="hand" id="id_shipping_method_2" name="shipping_method" type="radio" value="h" /> By hand</label></li>
</ul>

Trying to fill a form with Scrapy FormRequest, unexpected results

I'm trying to fill the form that is at www.wetseal.com/Stores that allows selecting the state to show stores from.
<form action="http://www.wetseal.com/Stores?dwcont=C73689620" method="post" id="dwfrm_storelocator_state">
<fieldset>
<div class="form-row required ">
<label for="dwfrm_storelocator_address_states_stateUSCA">
<span>State</span>
<span class="required-indicator">*</span>
</label>
<select id="dwfrm_storelocator_address_states_stateUSCA" class="input-select required" name="dwfrm_storelocator_address_states_stateUSCA">
<option value="">Select...</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
<option value="AR">Arkansas</option>
<option value="CA">California</option>
<option value="CO">Colorado</option>
<option value="CT">Connecticut</option>
<option value="DE">Delaware</option>
<option value="FL">Florida</option>
<option value="GA">Georgia</option>
<option value="HI">Hawaii</option>
<option value="ID">Idaho</option>
<option value="IL">Illinois</option>
<option value="IN">Indiana</option>
<option value="KS">Kansas</option>
<option value="KY">Kentucky</option>
<option value="MD">Maryland</option>
<option value="MA">Massachusetts</option>
<option value="MI">Michigan</option>
<option value="MN">Minnesota</option>
<option value="MS">Mississippi</option>
<option value="MO">Missouri</option>
<option value="NE">Nebraska</option>
<option value="NV">Nevada</option>
<option value="NH">New Hampshire</option>
<option value="NJ">New Jersey</option>
<option value="NM">New Mexico</option>
<option value="NY">New York</option>
<option value="NC">North Carolina</option>
<option value="ND">North Dakota</option>
<option value="OH">Ohio</option>
<option value="OK">Oklahoma</option>
<option value="OR">Oregon</option>
<option value="PA">Pennsylvania</option>
<option value="PR">Puerto Rico</option>
<option value="RI">Rhode Island</option>
<option value="SC">South Carolina</option>
<option value="SD">South Dakota</option>
<option value="TN">Tennessee</option>
<option value="TX">Texas</option>
<option value="VA">Virginia</option>
<option value="WA">Washington</option>
<option value="WV">West Virginia</option>
<option value="WI">Wisconsin</option>
</select>
</div>
<button type="submit" name="dwfrm_storelocator_findbystate" value="Search">
Search
</button>
</fieldset>
</form>
Looking with Chrome I can see the request being made and the form params:
That said, I have a very simple spider that, looking at the docs, sends a FormRequest to that URL to fill the form (In this case I'm testing for Arizona shops - AZ):
class WetSealStoreSpider(Spider):
name = "wetseal_store_spider"
allowed_domains = ["wetseal.com"]
start_urls = [
"http://www.wetseal.com/Stores"
]
def parse(self, response):
yield FormRequest.from_response(response,
formname='dwfrm_storelocator_state',
formdata={'dwfrm_storelocator_address_states_stateUSCA': 'AZ',
'dwfrm_storelocator_findbystate': 'Search'},
callback=self.parse1)
def parse1(self, response):
print response.status
print response.body
When it gets to make the FormRequest, looking at the response, everything seems OK:
But in the callback method, I see this in the response:
It looked like a GET request was made at the end, and the url is all wrong:
'http://www.wetseal.com/Search?q=&dwfrm_storelocator_findbystate=Search&dwfrm_storelocator_address_states_stateUSCA=AZ'
Any idea what I'm doing wrong?
Thanks!
You're using formname but the form doesn't have a name.
Try using formxpath='id("dwfrm_storelocator_state")' instead.
try this
states = response.xpath(
".//select[#id='dwfrm_storelocator_address_states_stateUSCA']//option[#value!='']/#value").extract()
url = self.get_text_from_node(response.xpath("//form[#id='dwfrm_storelocator_state']/#action"))
for state in states:
form_data = {'dwfrm_storelocator_address_states_stateUSCA': state,
"dwfrm_storelocator_findbystate": "Search"}
yield FormRequest(url,
formdata=form_data,
callback=self.your_Callback)

How to setup the initial value in select control?

I'm trying to setting up a select control on a form, but not achieving the expected results. For me, the strangest thing is it working in the previous control, same type.
This is the function involved:
class ProofMSPE(CrearEvidencia):
model = VRL02
form_class = VRL02Form
def get_form(self, form_class):
form = super(ProofMSPE, self).get_form(form_class)
form.fields['miembro'].queryset = self.pipol
if self.pipol.count() == 1:
form.fields['miembro'].widget.initial = [self.pipol[0].id]
form.fields['meta'].initial = self.meta
form.fields['meta'].widget.attrs['disabled'] = True
return form
The meta's control is select and I got the expected behavior, ie automatically selects an initial value (form.fields['meta'].initial = self.meta and inthe next lines, it disabled (form.fields ['meta']. widget.attrs ['disabled'] = True). This is the output in the rendered template:
<!-- begin meta-->
<div class="row">
<div class="col s12 input-field">
<select id="id_meta" name="meta" disabled>
<option value="">---------</option>
<option value="1" selected="selected">JOCE-1</option>
<option value="2">VEL-1</option>
<option value="3">VEL-2</option>
<option value="4">VEL-3</option>
</select>
<label for="id_meta">Evidencia para la meta</label>
</div>
</div>
<!-- end ./meta -->
On the other hand, with the pipol field I'm unable to get the same result. The difference, by the way, is this field has some logic: I get a filtered list of people with same criteria and the widget is create whit this list (form.fields['miembro'].queryset = self.pipol).
So far so good, but if the queryset has only one result (if self.pipol.count () == 1 :) I want that this one to be used as inital value (form.fields ['member']. Widget.initial = [self .pipol [0] .id]), but this is not working.
This is what appears when the template is rendered:
<!-- begin pipol-->
<div class="row">
<div class="col s12 input-field">
<select id="id_miembro" name="miembro">
<option value="" selected="selected">---------</option>
<option value="2">***#***.mx</option>
</select>
<label for="id_miembro">Seleccione el usuario</label>
</div>
</div>
<!-- end ./pipol -->
Thanks for your time.
You have to set the initial value to the form.field['miembro'] and not the widget, like you did with form.fields['meta'].
def get_form(self, form_class):
form = super(ProofMSPE, self).get_form(form_class)
form.fields['miembro'].queryset = self.pipol
if self.pipol.count() == 1:
# this line here
form.fields['miembro'].initial = self.pipol[0]
form.fields['meta'].initial = self.meta
form.fields['meta'].widget.attrs['disabled'] = True
return form
Select output would be:
<select id="id_miembro" name="miembro">
<option value="">---------</option>
<option value="2" selected="selected">***#***.mx</option>
</select>

Transfer Value from drop down to a

I need some help ...
I need the location drop down box to determine the appropriate inbox the form should be sent to.
ex if I choose Houston from the drop down box it will send it to the PayrollUSA email.
Im currently using a radio button to make the selection but i would like to automate with the drop down.
Im pretty new to this but im sure theres a if statement that can tie them together...
im using .asp for this.
<input type="radio" name="payroll" value="PayrollUSA#mail.com" checked="checked">US Payroll
<input type="radio" name="payroll" value="PayrollCAN#mail.com">CAN Payroll
<input type="radio" name="payroll" value="PayrollUK#mail.com">UK Payroll
<input type="radio" name="payroll" value="PayrollHK#mail.com">HK Payroll
Drop down selection
<SELECT SIZE="1" NAME="Business_Unit" style="width: 205px;" class="answers">
<option selected >Select</option>
<OPTION>Calgary</OPTION>
<OPTION>Chicago</OPTION>
<OPTION>Hong Kong</OPTION>
<OPTION>Houston</OPTION>
<OPTION>London</OPTION>
<OPTION>Los Angeles</OPTION>
<OPTION>Montreal</OPTION>
<OPTION>New York</OPTION>
<OPTION>New York Corporate</OPTION>
<OPTION>Philadelphia</OPTION>
<OPTION>San Francisco</OPTION>
<OPTION>Toronto</OPTION>
<OPTION>Toronto Corporate</OPTION>
<OPTION>Vancouver</OPTION>
</SELECT>
If you need the option value to be held then try this:
<SELECT SIZE="1" NAME="Business_Unit" style="width: 205px;" class="answers">
<option value="">Select an Option</option>
<option <% if Business_Unit= "PayrollCAN#mail.com" then %> selected <% End if %> value="PayrollCAN#mail.com">Calgary</option>
<option <% if Business_Unit= "PayrollUSA#mail.com" then %> selected <% End if %> value="PayrollUSA#mail.com">Chicago</option>
</select>
etc. for each option and same value may be used for different option displays
I imaging this should just be html based. So your option menu should look like:
<SELECT SIZE="1" NAME="Business_Unit" style="width: 205px;" class="answers">
<option value="-1">Select an Option</option>
<OPTION value="PayrollCAN#mail.com">Calgary</OPTION>
<OPTION value="PayrollUSA#mail.com">Chicago</OPTION>
<OPTION value="PayrollHK#mail.com">Hong Kong</OPTION>
<OPTION value="PayrollUSA#mail.com">Houston</OPTION>
<OPTION value="PayrollUK#mail.com">London</OPTION>
<OPTION value="PayrollUSA#mail.com">Los Angeles</OPTION>
<OPTION value="PayrollCAN#mail.com">Montreal</OPTION>
<OPTION value="PayrollUSA#mail.com">New York</OPTION>
<OPTION value="PayrollUSA#mail.com">New York Corporate</OPTION>
<OPTION value="PayrollUSA#mail.com">Philadelphia</OPTION>
<OPTION value="PayrollUSA#mail.com">San Francisco</OPTION>
<OPTION value="PayrollCAN#mail.com">Toronto</OPTION>
<OPTION value="PayrollCAN#mail.com">Toronto Corporate</OPTION>
<OPTION value="PayrollCAN#mail.com">Vancouver</OPTION>
</SELECT>
You can use the same value multiple times if needed