Django form errors are not showing up - python

I have looked all over stackoverflow and the Internet about this so I will just show my code.
views.py
def UserSell(request,username):
theuser=User.objects.get(username=username)
thegigform=GigForm()
#if the user is submitting a form
if request.method=='POST':
#bind form with form inputs and image
gigform=GigForm(request.POST,request.FILES)
if gigform.is_valid():
gigform.title=gigform.cleaned_data['title']
gigform.description=gigform.cleaned_data['description']
gigform.more_info=gigform.cleaned_data['more_info']
gigform.time_for_completion=gigform.cleaned_data['time_for_completion']
gigform.gig_image=gigform.cleaned_data['gig_image']
finalgigform=gigform.save(commit=False)
finalgigform.from_user=theuser
finalgigform.save()
return HttpResponseRedirect('done')
thegigform=GigForm()
context=RequestContext(request)
return render_to_response('sell.html',{'theuser':theuser,'thegigform':thegigform},context_instance=context)
template
<form action="{% url sell user.username %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<fieldset>
<legend><h2>Sell A Gig</h2></legend>
{% for f in thegigform %}
<div class="formWrapper">
{{f.errors}}
{{f.label_tag}}: {{f}}
{{f.help_text}}
</div>
{% endfor %}
</fieldset>
<input type="submit" value="Sell Now!" />
This code seems to follow normal django form protocol so please tell me why my django template doesnt show the errors. Thanks

It looks like you are missing an else block.
if gigform.valid() returns false, you are overwriting the variable "thegigform". Try restructuring your code like this:
if request.method=='POST':
#bind form with form inputs and image
thegigform=GigForm(request.POST,request.FILES)
if thegigform.is_valid():
thegigform.title=gigform.cleaned_data['title']
thegigform.description=gigform.cleaned_data['description']
thegigform.more_info=gigform.cleaned_data['more_info']
thegigform.time_for_completion=gigform.cleaned_data['time_for_completion']
thegigform.gig_image=gigform.cleaned_data['gig_image']
finalgigform=gigform.save(commit=False)
finalgigform.from_user=theuser
finalgigform.save()
return HttpResponseRedirect('done')
else:
thegigform=GigForm()
context=RequestContext(request)
return render_to_response('sell.html',{'theuser':theuser,'thegigform':thegigform},context_instance=context)

Related

Can I build my form without using Django form?

I'm using Django and I just did a big form Using HTML5 and bootstrap. Can I still send the form via the post method to django if I'm not using it to generate the form? Should I definitely redo my form using Django?
NOTE: There may be a better way of doing this, if there is I'd really like to know, this is just how I have done it in the past.
You will still need a forms.py file in your app.
In forms.py:
from django import forms
class MyForm(forms.Form):
# FORM FIELDS HERE
Then put the form in the context dictionary for your view:
def myView(request):
if request.method == "POST":
# FORM PROCESSING HERE
else:
myform = MyForm() #create empty form
return render(request, "template.html", {"myform": myForm}
Now in your template you can add:
<form id="myForm" name="myFormName" method="post" action=".">
{% csrf_token %}
{% for field in myform %}
{{ field.as_hidden }}
{% endfor %}
</form>
This will add your django form to the page without displaying it. All of your form inputs are given the id id_fieldName where fieldName is the field name you defined in the forms.py file.
Now when the user clicks your "submit" button (which I am assuming is a bootstrap button given the rest of your form is). You can use Jquery to input the bootstrap field values into those of the hidden form.
Something like:
$("#mySubmitButton").click(function() {
$("#id_djangoFormField").val($("#myBootstrapFormField").val());
$("#myForm").submit();
}
);
This will submit the django form with the inputs from bootstrap. This can be processed in the view as normal using cleaned_data["fieldName"].
A bit late I post the solution I found for including a form in a modal in a class based detail view. Dunno if it's really orthodox but it works.
I don't use any Form Class or Model. (Django 3.9)
Within the template, I send a field value of my object in a hidden div. If this value is missing for a special action (because for the most of actions on the object, it's not required), a modal pops asking for updating the given field. This modal is triggered with JS that check the presence (or not) of the required value.
In the modal, I display a list of radio choices buttons in an ordinary form inviting the user to update the field. The form's action leads to a view that will update the given field.
modal.html
<form action="{% url 'update-sku-column' object.pk %}" method="post">
{% csrf_token %}
{% if csv_headers %}
<div class="m-3 ps-3">
{% for header in csv_headers %}
{% for csv_sample in csv_samples %}
{% if forloop.counter0 == forloop.parentloop.counter0 %}
<div class="form-check">
<input class="form-check-input" type="radio" name="chosen-field" value="{{ forloop.counter0 }}">
<label class="form-check-label" for="{{ forloop.counter0 }}">
<span class="ms-3">{{ header }} </span>: <span class="ms-1 text-secondary">{{ csv_sample }}</span>
</label>
</div>
{% endif %}
{% endfor %}
{% endfor %}
</div>
{% endif %}
<div class="modal-footer">
<button type="submit" class="btn btn-success">Enregistrer</button>
</div>
</form>
urls.py
[...]
path('flow/<int:pk>/update-sku-column',
set_sku_column, name='update-sku-column'),
[...]
views.py
#login_required
def set_sku_column(request, pk):
if request.method == 'POST':
column = request.POST['chosen-field']
flow = Flow.objects.get(pk=pk)
flow.fl_ref_index = column
flow.save()
return redirect('mappings-list', pk=pk)
[...]
Even if I can imagine it's not the best way, it works.
don't forget the {% csrf_token %}otherwise it won't

How to show confirmation modal in Flask app after form submission?

I'm trying to show a confirmation/success message to the user in my Flask app, but I can't figure out how to display it in a modal.
#app.route("/", methods=["POST"]
def sendForm():
form = ContactForm(request.form)
if request.method == 'POST':
if form.validate():
# do stuff with form data
return render_template("contact.html", form=form)
else:
# display error message
else:
return render_template("index.html")
The part where I return the contact.html template is where I need help, I think. Because that page is basically refreshed and shown again after the POST request successfully completes. Need to display a confirm message to the user in a modal instead.
On the front-end, my form is looks like this:
<form method="POST" action="{{ url_for('sendForm') }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
{{ render_field(form.email) }}
{{ render_field(form.name) }}
<input id="submit-form" type="submit" value="Send">
</form>
I would do some form of this...
Pass a boolean in your render_template:
submission_successful = True #or False. you can determine this.
render_template("contact.html", form=form, submission_successful=submission_successful))
Then in your template place an if statement
{% if submission_successful %}
// modal elements here
{% endif %}

Validate Form Based on Hidden Input's Template Value - Is It Possible?

I have a form that in layman's terms, has a bunch of buttons (that act like checkboxes) with values. Users can select a handful of buttons.
The buttons push their values (via a JQuery function) into a hidden input which I'm using to gather the values.
I would like to make sure that the "values=" attribute of each hidden input isn't null or "" when the user presses the submit form.
Ex: Make sure that the input does NOT equal this:
<input autocomplete="off" id="id_valuePlatform" name="valuePlatform" type="hidden"> or
<input autocomplete="off" id="id_valuePlatform" name="valuePlatform" type="hidden" value="">
Here's the forms.py:
class getGames(forms.Form):
valuePlatform = forms.CharField(required=True, error_messages={'required': 'You need to tell us your platform(s)!'}, widget=forms.HiddenInput(attrs={'autocomplete': 'off'}))
Template:
<form method= "POST" autocomplete="off"> {% csrf_token %}
{{ form.non_field_errors }}
<div class="container">
{% if form.valuePlatform.errors %}
<ol>
{% for error in form.valuePlatform.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}
</div>
{{ form.valuePlatform }}
</div>
</div>
</form>
Views.py:
from .forms import getGames
def find(request):
form = getGames()
context = {"form": form}
if form.is_valid():
print form.cleaned_data['valuePlatform']
Is this even possible, or would I have to pass the data to Django via a Ajax POST?
Changed views.py to this, after looking at # Alasdair's examples in the documentation:
from .forms import getGames
def find(request):
form = getGames(request.POST or None)
context = {"form": form}
if request.method == 'POST':
if form.is_valid():
print form.cleaned_data['valuePlatform']

Display form input with Django

So basically I want to make a simple form I can enter text and the after I hit submit, see the text.
Here is my forms.py:
class Search(forms.Form):
search = forms.CharField()
Here is my views.py:
def search(request):
context = RequestContext(request)
if request.method == 'POST':
search = Search(data=request.POST)
if search.is_valid():
ticker = search.save()
ticker.save()
success = True
else:
print search.errors
else:
search = Search()
return render_to_response('ui/search.html', {"search":search}, context)
Here is the html form that you use to type in (I'm using bootstrap for styling purposes):
<form class="navbar-form navbar-right" role="search" action="/search/" method="post" name="tick">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" placeholder="Enter stock symbol">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
And finally, I want the text entered in the form to be displayed on "search.html" which looks like this currently:
{% extends 'ui/base.html' %}
{% block title %} search {% endblock %}
{% block body_block %}
<br>
<p>test</p>
{{ form.search.data }} <!--I'm pretty sure this is not correct -->
{% endblock %}
Anyone know how I can do this? Thanks.
Your form name is search.
To render the value with modern django, you need to call the value method of the field, therefore your template should look like the following:
{{ search.search.value }}
Your template is wrong, as you suspect.
It is looking for a context variable named "form", but you have given it a context dictionary with a key named "search".
Also, "data" is the argument that you use to build up your Search object (correctly), but when you want to extract the user's input from it, you should use the field names instead, and you need to call value() on them in order to get the bound value. So, to get the contents of the text field called search, you should use search.search.value.
Try changing the line
{{ form.search.data }}
to
{{ search.search.value }}

Submitting multiple forms in Django

I'm not sure if i'm going about this completely the wrong way, but in my html template i have a for loop that i want to present multiple forms, and one submit button to submit the data from all forms:
{% for i in Attribute_list %}
<form action="/Project/create/" method=post>{% csrf_token %}
{{ i }}:
<input type=text name={{ i }}><br>
<hr>
{% endfor %}
<input type=submit>
The problem with this is it only submits the last form.
The other problem i'm running into is getting the data back from the view. Since i'm naming the form the variable "i", i don't know how to "get" this data in my views.py:
def create_config(request):
if request.method == 'POST':
data_list = []
for data in request.POST.getlist():
data_list.append(data)
can You check this?
<form action="/Project/create/" method="post">
{% csrf_token %}
{% for i in Attribute_list %}
{{ i }}: <input type="text" name="{{ i }}"><br>
<hr>
{% endfor %}
<input type="submit">
</form>
As I understand without JS regardless how many forms You create only one POST request will be made.
In oyur example HTML is not valid so It can behave different ways in different browsers. But as soon as You have not closed form last one should be submitted.
As for second part
def create_config(request):
if request.method == 'POST':
data_list = []
for data in request.POST.getlist():
data_list.append(data)
I think You should use your Attribute_list. Or You can just iterate over all `POST' variables obtained.
def create_config(request):
if request.method == 'POST':
data_list = []
for key in request.POST:
data_list.append(request.POST[key]) # or .extend(request.POST.getlist(key)

Categories