Django TemporaryUploadedFile not rendered if form is invalid - django

I have a form that contains FileField as one of its fields. Each field in the form is rendered using as_crispy_field.
Issue:
If I entered all the inputs (including the file), and the form got re-rendered because it is invalid, it shows the same values of all inputs except the file input value. However, I can see the TemporaryUploadedFile value using {{ form.my_file.value }}

Related

Django as_crispy_field doesn't render the TemporaryUploadedFile data

I have a Django formset that receives the POST request data once submitted, and it saves it (including the uploading file) normally to my database, but if the form is invalid, the page renders again with the same values but missing the selected uploaded file.
I am passing the data to the formset as:
fs = MyFormset(request.POST, request.FILES, .......)
and I am rendering the fields of each form one by one. So, the file field data is:
<div class="col-md-10">
{{ form.included_documents|as_crispy_field }}
</div>
When I submit a new form but it fails in one of the validation criteria, it returns with no file chosen although there was a file chosen. But, if I have a saved form, it renders the uploaded file normally.
Failed Tested Workaround:
According to this Github issue answer, I tested it and it parsed the file input with a better look, but it still fails with parsing the TemporaryUploadedFile.
To make sure that I have the value in my form, I added the below, and it showed the value correctly in the span element not the crispy field element:
<div class="col-md-10">
{{ form.included_documents|as_crispy_field }}
<span>{{ form.included_documents.value }}</span>
</div>
What am I missing here to render the TemporaryUploadedFile in crispy field?

Django: The page shows "(<django.forms.fields.BooleanField object at ...>)" at variable location in a template

I was trying include a checkbox on my template, but it showed me some text on the browser instead.
I have a form (forms.py) that contains boolean field, e.g:
Class MyForm(forms.Form):
my_checkbox = forms.BooleanField(required=False, label='my_checkbox'),
and I have the following in my templates/my_app/my_form_template.py:
<form id="form" method="post">
{{ form.my_checkbox }}
<form>
In the browser after running the server, I've got:
(<django.forms.fields.BooleanField object at 0x0000014BE3CF9208>,)
The CharField and ChoiceField work perfectly except BooleanField. What is a way to represent a checkbox on the template?
I've tried {{ form }} in the template and it shows the checkbox, but I wish to custom the attributes of the checkbox.
There is a comma at the end of the field that causes an error. Removing it would fix the problem.

Dynamically Delete form from model formset django

I have a web page where users can dynamically add and delete forms, to django formsets.
I have read Dynamically adding a form to a Django formset with Ajax, based on which I can add the forms to a formset dynamically. Now I want to delete the formset dynamically. I have looked at Dynamically Delete inline formsets in Django
The way I want to do it is when user clicks on delete, I have an ajax function that deletes the form instance record from the database. When my ajax function returns I keep the same total_form_count and initial_form_count and just the hide the form html so that even the deleted record is submitted in my POST.
Initially the formset renders its form elements as:
#form0
<input id="id_formprefix-0-id" type ="hidden "value="something" name="formprefix-0-id">
<input id="id_formprefix-0-field" value="something" type="text" name="formprefix-0-field">
#form1
<input id="id_formprefix-1-id" type ="hidden "value="something" name="formprefix-1-id">
<input id="id_formprefix-1-field" value="something" type="text" name="formprefix-1-field">
#form2
<input id="id_formprefix-2-id" type ="hidden "value="something" name="formprefix-2-id">
<input id="id_formprefix-2-field" value="something" type="text" name="formprefix-2-field">
Now suppose I dynamically delete form 0, using ajax, after my record is deleted, I do not change the form counts, so the total_form_count and initial_form_count are 3.
( If i reduce the total_form_count and initial_form_count in this case to 2, when I populate the formset in my view using POST data, it is expected to be ordered as form0 and form1. But in my case the valid forms are form1 and form2)
Now in my view, I am do something like the following to save my form.
myformset = modelformset_factory(ObjectElement,form=Object_Form, extra=0, can_delete=True)
for form in myformset.forms:
print(form.instance.id) #this does not print id of deleted record, but of the first existing record in the database.
print(form.instance.attribute)# this prints the correct element, which was submitted by POST even for a deleted record.
try:
objectInstance = ObjectElement.objects.get(id = form.instance.id)
objectInstance.save()
except ObjectElement.DoesNotExist:
print("Do not save as the record has already been deleted")
When I save my formset without deleting any record the saving works ok and the correct form.instance.id is printed.
However if I delete a form instance using ajax, and then try to save my formset, the
print(form.instance.id) for the deleted record seems to print the first available id in the database, but not the id that was submitted by post. (As the record is deleted , the id is not present in the database, but should it print what was submitted to it via POST right? )
If I do it without the try/catch loop I get the following error by form.errors:
<ul class="errorlist"><li>id<ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul></li></ul>
which seems to indicate that it is not accepting the correct form ID form the submitted post for the deleted record.
Any body has any idea as to what I am missing here? Or a better way to do this.
How to we go about dynamically deleting forms from formsets, as it seems that the order of the forms should be sequential..
Thanks in Advance!! Any help is appreciated.
For those who stumble across this issue this could be a possible solution
I am able to dynamically delete my form from formset as follows.
So the initial form html looks like
#form0
<input id="id_formprefix-0-id" type ="hidden "value="something" name="formprefix-0-id">
<input id="id_formprefix-0-field" value="something" type="text" name="formprefix-0-field">
#form1
<input id="id_formprefix-1-id" type ="hidden "value="something" name="formprefix-1-id">
<input id="id_formprefix-1-field" value="something" type="text" name="formprefix-1-field">
#form2
<input id="id_formprefix-2-id" type ="hidden "value="something" name="formprefix-2-id">
<input id="id_formprefix-2-field" value="something" type="text" name="formprefix-2-field">
Now suppose I delete form0 and form1 records from my database using ajax.
When I submit the form, the formset will not validate, because it expects the forms to be in order, and I only have form 2 remaining in the data base ( I deleted the top two). Formset errors with "Select a valid choice" as described in the question.
So after I delete the forms dynamically, when my ajax returns, I do not change the total_form_count,(https://docs.djangoproject.com/en/1.4/topics/forms/formsets/#understanding-the-managementform) but mark the form as deleted in my html, and just hide the form. Now when the formset is submitted using POST, it also submits the deleted form, but marked as deleted (https://docs.djangoproject.com/en/1.4/topics/forms/formsets/#can-delete)
Now in the view, I first filter out the forms that have been deleted, and only process the forms that still remain as follows
marked_for_delete = formset.deleted_forms
for form in formset.forms:
#Filtering out the deleted records, as the formset will not validate, for deleted records
# if we use form.instance.id or form.initial['id'] below it does not work.
#for some reason it returns the id of the first available record in the data base.
#form['id'].value(), gives us the id of the deleted element we are looking for
if form['id'].value() not in [deleted_record['id'].value() for deleted_record in marked_for_delete]:
if form.is_valid():
pass
# save the form
else:
pass
# error message

form.as_table in django

form = EmailForm()
return render_to_response('books/send_mail.html', {'email_form': form})
When i am using form.as_table in my template, all the fields are getting rendered in the same line : (Email: Subject: Message: ).
How can i render these form fields in seperate lines using as_table. I dont want to use as_p or as_ul, because they do not have proper alignment.
Did you wrap your form in table tags?
You can also use form.as_table to output table rows (you'll need to provide your own tags)

Django: How to access modelform field data in templates

I have a page which displays a form that a logged-in user can use to edit their profile.
The first time the user loads the corresponding view, with a GET request, the form should display the values of the users existing profile record.
Because I'd like to have granular control over the markup used for the form fields, I'd like to retrieve the field values only, and manually write the necessary input element markup inserting the retrieved field values as the input elements' 'value' attribute (rather than have django render the entire input elements).
So far I've been trying to use directives like {{ form.myfield.data }} in my template to access the field data, but this is returning "None", instead of the profile details as i expected.
If the user has just posted a valid form though, the form fields do contain the expected profile details.
I hope someone can help me understand what i'm doing wrong here:
Here's my view:
#login_required
def edit(request):
# get logged-in user's profile
obj=Profile.objects.get(user=request.user)
if request.method == 'POST': # If the form has been submitted...
form = ProfileForm(request.POST, request.FILES, instance=obj)
if form.is_valid(): # All validation rules pass
form.save()
request.flash['success'] = "Your profile has been updated." # Puts a string to the flash scope
else:
request.flash['error'] = 'Please correct the problems below and try again' # Puts a string to the flash scope
else:
# if no form was submitted
# derive the form data from the logged-in users existing profile
form = ProfileForm(instance=obj)
return render_to_response('app_profile/edit.html',
{
'form': form,
'user': request.user,
'ancestor_urls': ['app_profile.views.edit',],
},context_instance=RequestContext(request)
)
And here's an excerpt from the corresponding template. This input element deals with a field called 'display_name'.
<input type="text"
class="textInput large {% if form.display_name.errors %}error{% endif %}"
maxlength="50"
size="35"
value="{{ form.display_name.data }}"
id="id_display_name"
name="display_name">
The way to do what you want to do is to write custom form widgets, instead of doing that in the template.
You can either create an entirely custom widget, or you can just add/change the attributes on the form level when you init the ModelForm
I guess you can solve some of your problems without making a custom widget using the widgets attrs argument: http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.attrs, also you have some styling options using the input's id!