Add editable choices in django - python

I am trying to add a editable choicefield in django like the picture, already do some research on this. Unfortunately, the solution like django-autocomplete doesn't quite fulfill my needs. The autocomplete looks fine, but if do so, I need create a django modal to generate the choices through a url view request, but in my case, it doesn't necessary to do that, I just need put these 3 choices for ip address in the dropdown list, and choose one of them then edit it or submit.
The solutions I found, but they are not very well fit my need:
Django admin: Change selected box of related fields to autocomplete
Django editable dropdown field

If you want to use just those three entries the quickest way is to use a datalist, it just needs to be added into your HTML somewhere.
<div id="page-wrapper">
<label for="ip">Network address</label>
<input type="text" id="ip" list="ip-datalist">
<datalist id="ip-datalist">
<option>192.168.0.0/24</option>
<option>10.0.0.0/24</option>
<option>172.16.0.0/24</option>
</datalist>
</div>

If your options are likely to never change, you could hardcode them into your html like the answer above. If you're generating your dropdown using a form however it would be better to do something like this:
class MyForm(forms.Form):
ip_list = ((1, '192.168.0.0/24'), (2, '10.0.0.0/24'),
(3, '172.16.0.0/24'), )
network_address = forms.ChoiceField(label='Network Address',
choices=ip_list)
...
Once you render the form object in your template it ends up producing html like this:
<label for="id_network_address">Network Address:</label>
<select id="id_network_address" name="network_address">
<option value="1">192.168.0.0/24</option>
<option value="2">10.0.0.0/24</option>
<option value="3">172.16.0.0/24</option>
</select>
This way it is easier to change the ip_list in future if you need to, plus its keeps all your code in one place. This is explained in the docs here.

Related

How to display a dropdown list in Django form?

I have an issue with the display of a dropdown list, which is a field part of a Django form. Instead of a normal dropdown list, it appears like a kind of multiple select choice box (at least, it's high as this kind of object, as you will see in below screenshots), with the feature of a dropdown (the small arrow that opens the choice list).
I do not understand why it looks like this and how to solve this.
Edit
I pushed my current version into production, for tests and demo purposes, and surprisingly, it works, the dropdown displays properly (and still ugly in local environment)
If anyone has an explanation/solution for that, he is welcome
As far as possible I use standard objects (I'm not very comfortable with CSS) and, in this case, I did not manage to update anything (event setting height had no impact, maybe there is something wrong in this part too)
And I can understand my question is not perfect, but please explain me what's wrong to allow me to add missing information (and I still do not understand why we cannot thanks in advance people who will read and try to solve problems here, but it's another question... that will probably be edited without any explanation or comment)
Related model field is defined like this:
class Company(models.Model):
"""
Company informations
- Detailed information for display purposes in the application
but also used in documents built and sent by the application
- Mail information to be able to send emails
"""
company_name = models.CharField("nom", max_length=200)
comp_slug = models.SlugField("slug")
rules = [("MAJ", "Majorité"), ("PROP", "Proportionnelle")] # Default management rule
rule = models.CharField(
"mode de scrutin", max_length=5, choices=rules, default="MAJ"
)
The form has no dedicated rules, even if tried to add some (kept as comment in the code below):
class CompanyForm(forms.ModelForm):
company_name = forms.CharField(label="Société", disabled=True)
# rules = [("MAJ", "Majorité"), ("PROP", "Proportionnelle")]
# rule = forms.ChoiceField(label="Mode de scrutin", choices=rules)
class Meta:
model = Company
exclude = []
Here is the view:
#user_passes_test(lambda u: u.is_superuser or u.usercomp.is_admin)
def adm_options(request, comp_slug):
'''
Manage Company options
'''
company = Company.get_company(comp_slug)
comp_form = CompanyForm(request.POST or None, instance=company)
if request.method == "POST":
if comp_form.is_valid():
comp_form.save()
return render(request, "polls/adm_options.html", locals())
And the part of HTML code:
<div class="row border mt-4">
<div class="col-sm-12">
<h5>Préférences de l'application</h5>
<div class="row">
<div class="col-sm-5 mt-2">
{{comp_form.use_groups}} <label for="{{comp_form.use_groups.label}}">{{comp_form.use_groups.label}}
</div>
<div class="col-sm-7 mt-2">
<p><label for="{{comp_form.rule.label}}">{{comp_form.rule.label}}</label> : {{comp_form.rule}}</p>
<p>{{comp_form.upd_rule}} <label for="{{comp_form.use_groups.label}}">{{comp_form.upd_rule.label}}</p>
</div>
</div>
</div>
</div>
The concern is the format of the field:
When the user click on the arrow, here is the display (there are only 2 options):
What did I wrong?
How can I change this (in views or HTML/CSS)?
In your Company model you have only used two choices:
rules = [("MAJ", "Majorité"), ("PROP", "Proportionnelle")]
When rendering this model form in HTML there should be only two options. If you want may options you should modify your model.

Disabling boolean fields in Flask WTForms

I know this is possible (because I have done it before!) but I cant find the correct syntax anywhere on the web including in the WTForms manual and in posts on here.
I want to disable a boolean field in a form.
In the template I have tried to add (disabled = "disabled") and (disabled = True) e.g.
<div class="col-md-6">{{ wtf.form_field(form.news)(disabled="disabled")}}</div>
and...
<div class="col-md-6">{{ wtf.form_field(form.news(disabled="disabled"))}}</div>
In the form definition in my Python code I have tried to add disabled = True e.g.
news = BooleanField(label=u"Search news", description="description", validators=[], disabled = True)
Every way I have tried throws an error.
The field would be called with disabled to the form field. Here's some example code:
import wtforms
class MyForm(wtforms.Form):
my_field = wtforms.StringField()
f = MyForm()
print(f.my_field(disabled='disabled').__html__())
Output:
<input disabled="disabled" id="my_field" name="my_field" type="text" value="">
If that's not working for you, I suspect the definition of wtf.form_field is perhaps at fault. I assume that's a macro you have.

I have fixed select option list in HTML/CSS. I am trying to link it django char field.But Not finding a way through

Following is Django Form Field i have defined.
source_currency = forms.CharField(max_length=5)
Following is Select/Option HTML
<select name="fancySelect" for="{{ form.source_currency.id_for_label }}" class="makeMeFancy" id="drop1">
<!-- Notice the HTML5 data attributes -->
<option value="BTC" selected="selected" data-skip="1" data-icon="assets/images/large/bitcoin.png" data-html-text="BTC<i&gt">BTC<span class="select_coin_button_arrow">▾</span></option>
<option value="BTC" data-icon="assets/images/small/bitcoin.png" data-html-text="BTC<i&gt" >BTC</option>
<option value="ETH" data-icon="assets/images/small/ether.png" data-html-text="ETH<i>">ETH</option>
How They can be linked so that on submit These values are passed as string?
Use ChoiceField instead CharField, it will automatically pass selected value as string.
source_currency = forms.ChoiceField(
label=_("Source Currency"),
help_text=_("..."),
widget=forms.Select(attrs={'class': 'makeMeFancy'}),
choices=((1, _("BTC")), (2, _("ETH")),),
initial=1
)
UPDATE
Alternatively, If you want to connect your existing integration with backend.
Note: value of name attribute of select tag should be source_currency
not fancySelect

DJANGO: Add "select all" choice option to ModelMultipleChoiceField?

Is there a way to add additional choices to a ModelMultipleChoiceField? Specifically, I want to add a "Select All" option instead of an End-User having to select all of the choices individually.
Current Model Form:
class QueryForm(forms.Form):
book = forms.ModelMultipleChoiceField(queryset=Book.objects.all())
I want something like this:
class QueryForm(forms.Form):
book = forms.ModelMultipleChoiceField(choices=(('Select All', 'Select All'),(Book.objects.all()))
How can I add the Select All option to Model Multiple Choice Field?
Is this in the Django admin or in your own form? If it's the admin, the easiest solution is to simply add the field to ModelAdmin.filter_horizontal or ModelAdmin.filter_vertical. The special field that the Django admin will use has a "Choose All" option builtin.
If it's your own form, JS is your best bet as #AdamKG recommends. Given the following:
<div class="field">
<select multiple="multiple" name="my_field">
<option value="something">Something</option>
...
</select>
Select All
</div>
This bit of jQuery should do the trick:
$('.select-all').click(function(){
$('option', $(this).parent()).attr('selected', 'selected');
});
You will need to convert your ModelMultipleChoiceField to a MultipleChoiceField that gets its choices from the related model in __init__(). Add a "Select All" option with a sentinel (e.g. "all") instead of the PK that you will get from the actual models. Then just detect this in the POST view and set things appropriately.

dynamic forms in django with ajax/dajax

I have this simple form with a queryset to display job objects and allow the user to select one. Now, i would like to have a group of two radio buttons that would allow the user to select a 'filtering option'. If the user selects a group filter with the radio buttons, i would a drop down to appear that allows them to select which group they would like to filter on. I want to do this without having to reload the page, so i'm attempting to use dajax.
I was able to find an example on the dajax website that does something similiar, however, i was not able to get it to work. The radio buttons appear and the drop down appears(empty). When i click on the "Group" radio button, the drop-down should populate with all my Group objects, but it doesnt.
I've been stuck on this for awhile, so any help would be greatly appreciated.
forms.py
filters = (('0', 'Group'),
('1', 'Host'),
)
class JobSelectForm(forms.Form):
def __init__(self, *args, **kwargs):
super(JobSelectForm, self).__init__(*args, **kwargs)
self.fields['jobs'].widget.attrs["size"] = 20
jobs = forms.ModelChoiceField(queryset=Job.objects.all().order_by('name'), empty_label=None,)
filter = forms.ChoiceField(choices=filters,
widget=forms.RadioSelect(attrs={'onchange': "Dajaxice.tdportal.updatefilter(Dajax.process,{'option':this.value})", 'name':'combo1', 'id':'combo1', },
renderer=HorizRadioRenderer),
ajax.py
def updatefilter(request, option):
dajax = Dajax()
options = [Group.objects.all(),
Host.objects.all(),
]
out = ""
for o in options[int(option)]:
out = "%s<option value='#'>%s" % (out,o,)
dajax.assign('#combo2','innerHTML',out)
return dajax.json()
dajaxice_functions.register(updatefilter)
template
{{selectForm.filter.label}}: {{selectForm.filter}}
<br>
<select name="combo2" id="combo2" onchange="" size="1"></select>
<br><br>
<form method="post" action="/tdportal/jobs/">{% csrf_token %}
{{selectForm.jobs}}
<br><br>
<input type="submit" value="Edit" /> <input type="button" name="new" value="New" />
</form>
You need to add your dajaxice function to the select onchange to reference your function in the template.
Something like:
<select name="combo2" id="combo2" onchange="Dajaxice.your_project.your_appname.updatefilter(Dajax.process,{'option':this.value}" size="1"></select>
(Replace your_project with your project name, your_app with your appname).
Also make sure in your template you have all the necessary headers (and that they actually are there; e.g., if you view the source that you can click to them).
Be sure to debug using google chrome inspector (Ctrl-Shift-I) or firebug (in firefox).
EDIT: I now noticed that you have something similar that's in your form. How does it render in the HTML when you view the source? Is it improperly escaped?
I think you forgot a % sign (value='#') and a closing </option> in here:
out = "%s<option value='%s'>%s</option>" % (out,o,o)

Categories

Resources