Django forms: checkboxes are displayed without value - django

I'm unable to save my form (a ModelForm) properly, since django displays checkboxes without a value (I would expect value="true" on every fields, both checked than unchecked... but that's not the case).
When I submit the form, no data is received in the POST!
The following is a piece o my template:
<div>
{{form.displayAge.label_tag}}
{{form.displayAge}}
{{form.displayAge.errors}}
</div>
{{form.displayAge}} is rendered in this way:
<input checked="checked" type="checkbox" name="displayAge" id="id_displayAge">
BUT... since it has no value, checking/unchecking the checkbox is helpless! What should I do?
I would like to avoid typing form fields by hand!

No, there is no need for a value field. If the checkbox is checked, the browser will submit "on" as the value by default if none is supplied.
If you're not getting this value in your view, something else is wrong. Note that since you're using Django forms, you shouldn't be checking request.POST manually anyway: use form.cleaned_data.

Related

Form Validation On Frontend or Backend Django

I have an HTML form with a date field:
<input type="date" class="form-control" placeholder="Date" name="date" autocomplete="off" required>
Before submitted the form, I want to ensure that the date that was entered is greater than the current date. If it is older, then I want to show a custom form validation to say something like, "You must enter a date past today.".
Do you suggest I do this validation on the backend or the frontend? Thanks!!
I think you're better off doing in within django forms. The reason is, if you do it in the front-end, you'll have to repeat the code when applying this property elsewhere.

display any value from django views to html form input

I'm working on Django app and i have only one page in my templates directory named "index", everything is working well but i faced a problem when i wanted to display the result which will be passed by Django views to my HTML page. I want the value to be displayed on my input field instead of printing it on the browser. I searched a lot but i couldn't found anything related to this.
I have three fields:
key field.
Plaintext field.
Ciphertext field.
and one button for encryption & decryption.
I need when i click on the button, the result will be displayed on my Ciphertext field not on the browser because i already did that before.
Can you help me?
Thanks..
One of the multiple ways is to,
render the template from view.
pass the values for "key field" and "plain text filed" into the context variable (ex: return render(request, context={'key_filed': key_field_value, 'plain_text_field': plain_text_field_value} ).
Use these values in "value=" field of < input > tag. (ex: < inpu type='text' value={{ key_filed }} > and < inpu type='text' value={{ plain_text_field }} >)

How to render default values in django-ajax_select field

I am using ajax_select for my m2m and foreign key fields, its working fine but it is not rendering default value of that field, it is rending empty value ("|").
I am not using ajax_select in my admin panel, so when I open that form in admin panel, fields are having default values already. That means their is no problem in default values but in ajax_select field.
What it is rending now :
<input type="hidden" name="colours" id="id_colours" value="|" data-ajax-select="autocompleteselectmultiple" data-plugin-options="{"source": "/ajax_select/ajax_lookup/colours", "html": true}" data-changed="true">
What I wanted is:
<input type="hidden" name="colours" id="id_colours" value="|8|" data-ajax-select="autocompleteselectmultiple" data-plugin-options="{"source": "/ajax_select/ajax_lookup/colours", "html": true}" data-changed="true">
If at least default value initialized in name=colour, I can show help text that default value is White.
As I searched at documentation of ajax_select but nothing found related to it, does anyone know how to render default values in ajax_select field.
Is this problem occurring with me only or ajax_select doesn't have this default value feature ?
This can be achieved by overriding the get_form() method as :
def get_form(self,form_class=None):
form = super().get_form(form_class)
form['colours'].initial = '8'
return form
Now default value is set manually and also working in ajax_select.

Hiding ModelMultipleChoiceField on template for custom input

I want the user to select a number of elements belonging to a certain model. I don't want to use the default 'ctrl+click' input of django forms, but create a table of checkboxes myself.
For that reason I hide the ModelMultipleChoiceField by defining the widget:
field = forms.ModelMultipleChoiceField(..., widget=forms.MultipleHiddenInput())
Then I add the form element into the template as follows:
<form method="POST" class="locklist-form" id="locklist-form">{% csrf_token %}
{{ form.field }}
</form>
At this step, I expect the select-option elements to be added to HTML page (as hidden), so that I can reach to element options and modify them with javascript. However, it doesn't add anything to the HTML page.
I use this approach with other type of form fieds. For a TextField HTML page have a hidden element as shown:
Why doesn't it work with ModelMultipleChoiceField? How can I modify the choices of this field with Javascript?
Edit:
MultipleHiddenInput renders only if with initial data is a similar question. But applying it doesn't lead to the expected solution. In this question, it is expected to render the following as hidden:
But following the MultipleHiddenInput renders only if with initial data, when I modify the form constructor as:
form = MyForm(initial={'field':MyModel.objects.all()})
Rendered element is as follows:
It maybe useful, but not exactly the expected one. I need to mark a few options as selected, among a list of objects.
I have done it using Javascript, instead of depending on Django's capabilities. I add the form with ModelMultipleChoiceField directly to the template (not hidden). Then I run a Javascript script, when the page is loaded:
var field = document.getElementById('id_field');
selecter.setAttribute('class', 'hidden');
CSS definition of hidden class is as follows:
.hidden{
display: none;
}
This gets me to the desired situation. ModelMultipleChoiceField is rendered hidden as follows:
At this point, I can modify certain items through Javascript:
document.getElementById('id_field').options[index].selected = boolValue;

Get the clicked submit button in a django form in a generic way

I have a finite state machine (django-fsm) which allows an object to go from a source state into one of several target states. I can add all the actions in a dictionary like:
ACTIONS { 'button_1': action1,
'button_2': action2,
...
}
This translates in a form with a submit button for each state.
{% for n,m in object.get_available_current_state_transitions %}
<input type="submit" class="btn" value="{{ n|get_action|capfirst }}"
name="button_{{n}}" />
{%endfor%}
<input type="submit" class="btn primary" value="Save">
<a class="btn" onclick="javascript:history.go(-1)">Cancel</a>
This usually results in more than 3 buttons.
Clicking a button results in a specific action, defined in my case in the model class.
Now, I know I can get the clicked button in the request.POST dictionary, but this would result in a cascade if like:
if 'button_1' in request.POST:
action_1()
elif 'button_2' in request.POST:
...
Is there any way to get the button pressed separately (ideally from the request object) in a variable so I can have something like
ACTIONS[clicked_button_name](...)
? In other words, is there any way to obtain the clicked button outside the POST dictionary?
PS: I've looked other replies on the "multiple buttons" question, but all offer request.POST as answer.
If all of the actions and strings are already in your view, why don't you just iterate over that actions dict?
for key, value in ACTIONS.items():
if key in request.POST:
value()
Just make your button names very unlikely to be used as a regular form field name.
A few alternatives: use javascript to handle the submission and have it set a single form field such as "action".
Use more unique keys and filter through request.POST.keys() with a regex pattern or string comparison.
action = [x for x in request.POST.keys() if 'FAIRLY_UNIQUE_BUTTON_PREFIX' in x]
if action:
ACTIONS[action]()
I don't think so directly, but a couple workarounds could be:
Send your buttons to different urlconfs with some variable (like a three letter arg). All of these confs point to the same view taking this three letter arg as an argument, which then knows what to do. This might still result in a cascade if else though.
Or, send them to different views all together.
You could try doing something ajaxy. The data will still be in a post dict, but you will have more control over how the post dict is structured.
I'm also assuming GET isn't an option for any of these (yet that still results in if else structures.)