How to deselct something when selected previously in FileField Django Form? - django

I have a form which includes filefield to upload some files.
Sometimes what happens is at first, I select one file from browse to upload but then i realize i do not want to upload it anymore.How can i make it empty again??
Is it like that once this field is filled it cannot be reverted back to empty??
Thanks in advance

This can be accomplished with javascript.
Quoting Clear upload file input field with jQuery post from electrictoolbox.com:
function reset_html(id) {
$('#'+id).html($('#'+id).html()); }
$(document).ready(function() {
var file_input_index = 0;
$('input[type=file]').each(function() {
file_input_index++;
$(this).wrap('<div id="file_input_container_'+
file_input_index+'"></div>');
$(this).after('<input type="button" value="Clear"
onclick="reset_html(\'file_input_container_'+
file_input_index+'\')"
/>');
});
});

If you try to post an un-validated form, when you re-render the form, the filefield will be empty.
See this issue for more explanation..
Django Form File Field disappears on form error
The following works for me. Add a clear button to your html
<input type="submit" name = "submit-clear" value="clear file">
Then in your view handle this button using..
if 'submit-clear' in request.POST:
return HttpResponseRedirect('')
This should clear any filefields but will also remove any other settings the user has made, if you want to preserve other settings and just remove the filefield, then ensure the form does not validate somehow so that it renders again.

Related

Django form post request without rendering

I have django form, then for each field I set initial value. How can I make POST request in my view.py (like after pressing submit button) without rendering the form. I just need to send these initial values as POST request to another url.
You can create the form in HTML and set display:none is style attributee of each field. It will hide the form from front-end and when you click on submit button it will send all data in POST request.
<form method='post'>
<input name='field_name' style='display:none' value='abc'>
<input type='submit' value='submit'>
</form>
Above code will show only submit button on front-end and by clicking on it, it will send value of input field in POST request.

html - redirect to new url after form submission (django site)

I am trying to make a button redirect the user to a new url after they submit a form. This is how it is right now, and it works properly and all the data gets sent to the django database.
<form method='POST' action='' class="col-md-6 col-md-offset-7" style="background-color: lightgreen; border-radius: 10px">
However, when I change the action to
action="{% url 'ridesharing:request-success' %}",
the redirect works, but the data does not go to my django database.
What is going on here?
You seem to have some confusion here. The action of the form is where the browser will send the data. Obviously, if you don't point that at the view which actually processes the data, then it won't be saved.
To redirect after a post, your view should return a redirect.
When you declare a form with an empty action attribute:
<form method='POST' action=''>
the POST data will be sent to the same URL. This is useful because if there is some error in the form, it's easy to re-display it with all fields filled with values entered by the user. Then, when the form becomes valid, a redirect is done to the confirmation page.
When you declare your form that way:
<form method='POST' action='{% url 'ridesharing:request-success' %}'>
The data entered by the user in the form will be sent to the view request-success. But this view probably only render the template of the confirmation page. If you want to correctly handle data from the form, you have to set action attribute of your <form> to the same view, or easier, keep it empty.
I do not understand why Daniel Roseman's post isnt accepted as the answer. It helped me when I wanted to redirect a create form to its update form.
Basically in the view of the app I defined the get_success_url to reverse_lazy to the data-update.
def get_success_url(self):
return reverse_lazy('app_name:data-update')
Just replace the 'app_name:data-update' with the appropriate url.

Don't include blank fields in GET request emitted by Django form

On my Django-powered site, I have a search page with several optional fields. The search page is a Django form, and my view function is the typical:
def search(request):
form = SearchForm(request.GET or None)
if form.is_valid():
return form.display_results(request)
return render(request, 'search.html', {'form': form})
Form.display_results() uses the fields that are provided to query the DB and render a response. My search.html includes:
<form action="/search/" method="get">{% csrf_token %}
<!-- Render the form fields -->
<input type="submit" value="Search" />
<input type="reset" value="Reset form" />
</form>
Since most searches will have several blank fields, I'd like not to include them in the GET request emitted by the submit button on search.html. Current searches look something like:
http://mysite/search/?csrfmiddlewaretoken=blah&optional_field1=&optional_field2=&optional_field3=oohIWantThisOne
And I'd like them to look like:
http://mysite/search/?csrfmiddlewaretoken=blah&optional_field3=oohIWantThisOne
Of course, I have a several more fields. This would be nice to have because it would make search URLs more easily human-parsable and sharable.
You could use jQuery with an button trigger. Give the form and submit button ids.
$("#button_id").click(function(){
$("input").each(function(){
if($(this).val() == '') {
$(this).remove();
}
});
$("#form_id").submit();
});
That (or something similar) should remove all the empty fields before the submit.
You could also POST the form. Then build the search url and redirect with empty values removed.
See Hide empty fields from GET form by Bill Erickson:
jQuery(document).ready(function($){
// Remove empty fields from GET forms
// Author: Bill Erickson
// URL: http://www.billerickson.net/code/hide-empty-fields-get-form/
// Change 'form' to class or ID of your specific form
$("form").submit(function() {
$(this).find(":input").filter(function(){ return !this.value; }).attr("disabled", "disabled");
return true; // ensure form still submits
});
// Un-disable form fields when page loads, in case they click back after submission
$("form").find(":input").prop("disabled", false);
}
disclaimer: This is a very old question, and the only one I could find that matches the problem I ran into. It's entirely possible that my solution didn't exist at the time, and an even better way has since been added.
I'm using Django 3.2. I didn't want to use js/jQuery, nor did I want to use a POST form, so here's what I came up with. In a nutshell, it just checks the GET data to see if there are any default values present, and simply redirects to a URL that doesn't have them.
In your view:
from django.shortcuts import redirect
def myView(request):
if not is_clean_form(request.GET):
return redirect(whatever_url_path + clean_url_parameters(request.GET))
else:
# whatever your view does normally
Helper functions (consider making these static methods of your Form class, to keep all that type of stuff together):
from urllib.parse import urlencode
# fields and their default value (eg. empty string)
default_form_values = [
("some_field_name", ""),
# ...
]
def is_clean_form(form_dict):
for field, default_value in default_form_values:
if field in form_dict and form_dict[field] == default_value:
return False
return True
def clean_url_parameters(form_dict):
return "/?" + urlencode([
(field, form_dict[field]) for (field, default_value) in default_form_values
if field in form_dict and form_dict[field] != default_value
])

Using forms only for validation

Say you already have a complex HTML form, possible from a designer, front end dev, etc. Is it common practice to not use dynamic forms (based on a Django form) for complicated forms?
I want to do something like this:
1.) Create custom HTML form.
2.) Catch form data through POST request, put it in an object/dictionary.
3.) Do some manipulations with that data to get it in a format acceptable by a Django form.
4.) Pass the manipulated data in to a form object, validate it, etc...
What is a clear solution to this problem? Should I be using Django's dynamic forms for everything? If not - how do I implement the above?
EDIT:
Part of my question has to do with using the forms ONLY for validation. I don't think I made this clear. Here is what I'm trying to do:
template.html
<form method="post">
{% csrf_token %}
<input class="foo" name="bar" type="text" value=""/>
<!-- Some more fields, not rendered through Django form -->
<button type="submit">Create Object</button>
</form>
As you can see, other than the csrf_token there is no Django code here. What I am trying to do in my view is catch the data in the POST in my view, make some changes to the data, then try to bind the new data to a form (not sure if it's possible):
views.py
def my_view(request):
# Some GET code
if request.method == 'POST':
form = ImportedForm(request.POST)
form.data['foo'] = "newValue"
# Now after changing the data, validate it...
If the form and model match nicely then I'll take advantage of the ModelForm functionality.
But most of the time it is not so tidy so, most typically, I do things in about this order:
create a django form with all the field definitions
create django GET view to serve the empty form
create an html template which serves the default html/form
test the blank form
create the POST routine to call validation and reserve the validated (erroneous) form
modify the django form to validate the fields
modify the html form to serve the error messages
test the validation and error messages
modify the POST routine to handle a valid form and do whatever it should do as a result (might involve a redirect and 'thanks' view/template)
Test the whole lot
let the designer loose on the templates
In truth the designer will be involved at some points earlier along the way but in theory I just get it all to work as a "white" then add all the fancy stuff after. That includes javascript validation (ie after all the above).
I ended up doing something like this. It is ugly, and may not be the proper way to do it, but it works...
if request.method == 'POST':
try:
# Create dictionary from POST data
data = {
'foo': request.POST['foo'],
'foobar': request.POST['foobar'],
}
except:
# Handle exceptions
form = ImportedForm(data)
if form.is_valid:
# Continue to validate and save

Django: custom content in admin form

For one of my models, I want to show extra content in the change_form. Basically, my model looks like this:
class News(models.Model):
...
class NewsFromSource(models.Model):
news = models.ForeignKey(News)
...
I want to add a 'search' button that, when clicked, triggers a web service request to an external news source, pulls down the available content, and lists all the news pieces contained. The user can then select one of the pieces to "attach" to the News currently edited in the admin interface (i.e. create a new NewsFromSource based on the content downloaded through the web service).
I am done with the web service. What is the best approach to implementing the search-button, list display for the results (I have a view and template that work, need to get those into the form somehow) and the saving part?
What I ended up doing is the following:
1)
I created a view for fetching search results, which boils down to this:
#/myproject/admin/views.py
#never_cache
def news_search(request):
#...query web service
if 'q' in request.POST:
search_term = request.POST['q']
else:
search_term = ''
news = NewsSearch()
news.search(search_term)
return render_to_response( 'news_search_results.html',
{ 'q': search_term,
'news': news.result_list,
'page': page,
'page_left': news.page_left,
'page_right': news.page_right}
)
2) I mapped the view:
#/myapp/urls.py
...
url(r'^myapp/news/search/$', views.news_search),
3) I extended change_form.html for the news model with the following code:
#/myproject/templates/admin/myapp/news/change_form.html
{% extends "admin/change_form.html" %}
{% block after_field_sets %}
...
{% csrf_token %}
<input type="text" name="q" id="news-search-term">
<div id="news-search-results"></div>
...
function submitSearchForm() {
$.post("/myapp/news/search/",
{ 'q': $('#news-search-term').val(),
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val() },
function(data){
$('#news-search-results').html(data);
}
);
}
{{ block.super }}
{% endblock %}
4) I created an html template for displaying the results (news_search_results.html, see 1)
So basically I am sending an AJAX request from the admin page to a custom view to retrieve results from the webservice which then are displayed in a div.
Each element in the results list has a button that sends another request that stores the element with the news id as a ForeignKey.
I have no idea whether this is particularly against Django principles. But it seems to work alright.
Suggestions on doing this in a more "Djangonian" way are welcome.
We'll assume you have a related News model. Add that field to raw_id_fields of the modeladmin we're going to hack, then:
Overload the change_form template for this model, extend admin/change_form.html in admin/yourapp/yourmodel/change_form.html
Add javascript in that template to:
Hide the input and magnifier icon from the news raw id field form raw, you can do that in css too
Add something like a span with a button style in that form row that will open a popup when it is clicked
The popup it should open should be your working view/template with a form to select the news
When the user selects a news, the popup should do an ajax post request to get the news id, and close itself
the value is set to the raw id field input that is hidden, this is pretty tough but fear not someone (disclamer: I) published an article with the whole technical details, also found another one but I didn't test it
It's going to be quite some work. Patience and perseverance will be your best qualities for this mission B)