I have a simple form that enables selecting an option (radio button). Upon selection the form automatically submits itself (using the onchange attribute):
class MyForm(forms.Form):
choices=forms.ChoiceField( widget=forms.RadioSelect(attrs={'onchange': 'this.form.submit();'}), choices=[(k,k) for k in options],label="choose one")
This is great, only problem is I still have the "submit" button at the bottom of the form when it's rendered. Is it possible, without creating a template, to somehow make the form render without a submit button?
From Django doc:
The form only outputs its own fields;
it is up to you to provide the
surrounding tags and the submit
button.
It means that you probably have the submit button in you template - remove it if you don't need it.
Related
I am trying to create a Django form in which the user will have two options
Save the form (temporarily)
Submit the form
What I am trying to do is to allow the users to save the form temporarily and after they have all the data they can come back, edit the form and make the final submission.
The problem is that the form validation will not allow partially filled form to be saved.
Is there any way I can ignore validations when "Save" is pressed whereas perform all the validations when "Submit" is pressed?
I do not want to have 2 views. I want the same view with two buttons "Save" and "Submit" if Save is pressed some of the validations will be ignored (i.e. required field left empty due to the fact that the user might not currently have the information). But if the "Submit" is pressed, all the date should be validated.
Please note that all the validations takes place backend with Django.
Thanks
Context
I have a model, let's call it Application.
class Application(models.Model):
# various fields here
status = status = models.CharField(
max_length=100,
choices=APPLICATION_STATUSES,
default=PENDING_STATUS[0],
)
assigned_operator = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.PROTECT,
editable=True,
null=True,
)
This model has some fields, but the ones we care here are the status, which is simply a choice field, and the assigned_operator field, which defines a 1-1 relationship with a User instance. This model also has its corresponding ApplicationAdmin view defined.
Description
The requirement is that when trying to edit an Application, from the admin view, the default workflow, where you make whatever changes you want and then simply save the form, should be replaced with the following workflow:
The application form is readonly unless the user is the assigned_operator of the application, in which case the application is editable.
When the user is not the application's assigned_operator the actions at the bottom will be 1 button:
"Assign to myself" - When clicked the Application model is updated to reference the current user as its assigned_operator and the page refreshes
When the user is the application's assigned_operator the actions at the bottom will be 3 buttons:
"Save changes" - Does what default "Save" button does
"Reject" - When clicked changes the status field of the application to the appropriate one
"Accept" - When clicked changes the status field of the application to the appropriate one
The problem
Well, the problem is that I am pretty new with django and I am pretty lost here.
What I know:
How to make the fields of the form editable or read only based on the assigned_operator value. I think I just have to set up a get_readonly_fields and do my checks there. Correct me if wrong.
I can replace the current list of form actions with some custom buttons by adding a change_form_template = "path/to/change_form.html" field to the ApplicationAdmin. An example change_form.html that I have now:
{% extends 'admin/change_form.html' %}
{% block submit_buttons_bottom %}
<div>
<input type="submit" value="Assign to me" class="default" name="????">
</div>
{% endblock %}
What I don't know
How to conditionally show either the "Assign to myself" or the group-of-3-buttons, depending on the assigned_operator value of the Application model.
How to connect those new custom buttons to interact with the models and do stuff on them, when they are clicked
In general how the change_form.html part, which is just a template as far as I know, can know things from the currently displayed model instance and the current user.
While code examples are welcome, I do not ask you to give me the implementation. Clear directives/instructions will do just fine, I just need some guidance
Thanks
UPDATE
I figured how to pass info to the template, by using the change_view method of the ModelAdmin. So now I can conditionally display the appropriate buttons.
UPDATE 2
Just figured out how to also do something to a model once a button is clicked. We can use either response_change or change_view for that (not sure which one is the more "correct" option, but both work. Difference is that change_view runs before the view is even rendered, while response_change runs after the form has been saved and the model updated)
How to conditionally show either the "Assign to myself" or the group-of-3-buttons, depending on the assigned_operator value of the Application model.
By overriding the change_view method of the ModelAdmin in our custom Admin view we can pass extra context to our html templates, as showcased in the docs here. So now we can conditionally display the appropriate buttons, by adding an {% if context_value %} in the template.
How to connect those new custom buttons to interact with the models and do stuff on them, when they are clicked
We can use either response_change or change_view for that on our Admin view. In there we can listen for the value of our button's name in the request.POST values (for example _save etc) and act accordingly
(not sure which one is the more "correct" option to use, the response_change or the change_view but both work. Difference is that change_view runs before the view is even rendered, while response_change runs after the form has been saved and the model updated)
In general how the change_form.html part, which is just a template as far as I know, can know things from the currently displayed model instance and the current user.
A combination of passing it context from the Admin view and listening for button names from the template in the request.POST
Using django forms/formsets how do I construct a template that a user can toggle each rendered form in the formset to only display half of the form?
For example each form has a true and a false set of inputs and the user will only want to see one set of inputs at a time (to avoid overloading the user and the view). The user would click on an image with an onclick to toggle between entering data for the true or false set of inputs.
I can see how to do this without django forms but with them I'm a bit confused. Specifically, each field will have its own id that I would need to know in order to toggle the input type from text to hidden.
class ExampleForm(forms.ModelForm):
class Meta:
model = Example
fields = (
'true_input01',
'true_input02',
'true_input03',
'true_input04',
'false_input01',
'false_input02',
'false_input03',
'false_input04',
)
OK, so I wasn't able to come up with an answer to this problem but I did find a work around, which is to toggle the display of a row.
<tr id={{ form.instance.tag_id }}F style="display:table-row">
I have implemented a crispy form and crispy form helper to render a form. The form contains a drop down selection menu and a file submission button. However I want to deactivate the file submission button when the selection "File not required" is made in the drop down menu.
However I want all this to be done before the form submission button is pressed (i.e. before invoking POST method).
I'm trying to avoid any Jquery and AJAX implementations. Is there any Django way of doing this using Django Forms, views or Django Crispy Forms.
Crispy forms has HTML object for its layout class. Is there any way of doing above mentioned in using HTML objects or any other objects of layout class.
Below is the chunk of Django Form that is rendered in its respective template.
self.fields[field_name] = forms.ChoiceField(choices=choices, label='')
file_name = str(customer_Id)
self.fields[file_name] = forms.FileField(label=_("Attach PDF"), required=True)
self.helper.layout.append(Layout(
HTML('<tr><td>{}</td><td>{}</td><td>'.format(customerId, name)),
field_name,
HTML('</td><td>'),
file_name,
HTML('</td></tr>'),
))
self.helper.layout.append(Layout(HTML('</tbody></table>')))
In the index view I have a list of my models and "Create new" button. When user clicks on the button a modal form should be presented with one field: name of the model - the only field that required to create a model. When the user enters the name and click submit button the model get saved and edit view is displayed as a normal page ( with all fields from model available for editing).
How to achieve this? I have tried to build a new object in the index action:
def index
#my_models = MyModel.all
#new_model = MyModel.build
end
but that did not work (I was getting missing template error although without #new_model the index was displayed without problems)
Another question is how to render the form? Should I put the form into new.html.erb file
and then include <%= render 'new' %> in the body of the modal? (I am using Bootstrap 3.1 to create the modal itself)?
You can simply use
#my_model = MyModel.new
and call
<%= render 'form' %>
which uses #my_model.