only raise validation error after submitting in Django forms - python

After creating a form and setting required=True the form shows the validation errors immediately when loading the page.
Of course this should only happen after submitting.
How would I be able to make sure the proper errors only show after submitting?
forms.py
class CurrencyConverterForm(forms.Form):
base_currency = forms.ModelChoiceField(queryset=Currency.objects.all(), required=True)
counter_currency = forms.ModelChoiceField(queryset=Currency.objects.all(), required=True)
base_amount = forms.FloatField(required=True)
index.html
<form action="" method="get">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.base_currency.errors }}
<label for="{{ form.base_currency.id_for_label }}">From Currency</label>
{{ form.base_currency }}
</div>
<div class="fieldWrapper">
{{ form.counter_currency.errors }}
<label for="{{ form.counter_currency.id_for_label }}">To Currency</label>
{{ form.counter_currency }}
</div>
<div class="fieldWrapper">
{{ form.base_amount.errors }}
<label for="{{ form.base_amount.id_for_label }}">Amount</label>
{{ form.base_amount }}
</div>
</form>
views.py
def index(request):
counter_amount = ""
if request.method == 'GET':
form = CurrencyConverterForm(request.GET)
if form.is_valid():
# Get the input data from the form
base_currency = form.cleaned_data['base_currency']
counter_currency = form.cleaned_data['counter_currency']
base_amount = form.cleaned_data['base_amount']
# Calculate the counter_amount
counter_amount = get_conversion_amount(base_currency, counter_currency, datetime.now(), base_amount)
# Retrieve the counter amount from the dict
counter_amount = counter_amount['GetConversionAmountResult']
# Maximize the number of decimals to 4
if counter_amount.as_tuple().exponent < -4:
counter_amount = "%.4f" % counter_amount
else:
form = CurrencyConverterForm()
context = {
'form': form,
'counter_amount': counter_amount
}
return render(request, '../templates/client/index.html', context)

The problem is that both requests are GETs: both the initial request to get the form, and the request to submit the form. So there is no point in checking if request.method == 'GET', because it is always true.
Instead, check that there is actually information in the GET dictionary:
if request.GET:
Note that this will not work if you need to show an error on a completely empty submission, though.

Related

Django 3 - Passed variable in views.py not accessible in web form like other vars

Newbie to Django here - I have a list of DB entries that I want to be able to cycle through one at a time and currently I am working on loading the first object by its ID. The form renders fine, but other vars aren't accessible as expected - am I missing something in the code?
views.py
def ticket_edit(request):
updateform = TicketForm(request.POST)
if request.method == 'POST':
if updateform.is_valid():
ticket = Ticket.objects.update(
ticketID=updateform.cleaned_data['ticketID']
)
ticket.save()
return HttpResponseRedirect(".")
else:
print("FORM NOT YET VALID: Awaiting form.is_valid()")
updateform = TicketForm()
#--Get list of ticketIDs---------------
def ticketID_listGet():
tickets = Ticket.objects.all()
ticketIDList = []
for ticket in tickets:
aTicketID = ticket.appTicketID
ticketIDList.append(aTicketID)
return ticketIDList
tList = ticketID_listGet()
tFirst = str(tList[0])
print('TicketIDs: ', tList, tFirst)
return render(request,'authentication/ticket-edit.html',{
"has_error": False,
"updateform": updateform,
"tFirst": tFirst
})
ticket-edit.html
<div class="container" style="border-style:none">
<form action="." method="POST" id="ticket-update-form" style="border-style:none">
{% csrf_token %}
<div class="row">
<div class="col-md-12">
<div class="form-control" style="border-style:none">
{{ updateform.ticketID.label_tag }}
{{ updateform.ticketID }}
{{ tFirst }}
</div>
</div>
</div>
I am not getting errors when using {{ tFirst }}, it's just being ignored as if unrecognized. Ultimately I am trying to determine how to retrieve the existing ticketIDs and the first ticketID as vars and then cycle through them with buttons that set the value in the web form's {{ updateform.ticketID }) widget - am I making this more difficult than necessary?

Prepopulate WTForms radio field with info from view

Using flask and WTForms. I am trying to combine my edit and create forms for posts. When a user clicks edit, the view checks if there is a post id passed, if there is it grabs the current info for that post and populates the form in the template. I can get this to work for every field but the 'main_post' field which is radio buttons.
View:
#app.route('/posts-update' , methods=['POST','GET'])
#login_required
def posts_update():
form = forms.Post()
if request.method == 'POST' and request.form['id']:
post = Post.query.filter_by(id=request.form['id']).first()
form.title.data = post.title
form.body.data = post.body
# Works for all but main_post
form.main_post.data = post.main_post
# Also tried this and it didn't work
# form = forms.Post(obj=post)
else:
post = False
# form = forms.Post()
return render_template('post_update.html', post=post, form=form)
Form:
#post create and update
class Post(Form):
title = StringField('Title', validators=[DataRequired()])
body = TextAreaField('Body', validators=[DataRequired()])
main_post = RadioField('Make Main Post', choices=[('1', 'yes'), ('0', 'no')], validators=[DataRequired()])
Template:
<input type="hidden" name="id" {% if post.id %}value="{{ post.id }}"{% endif %}>
{{ form.title.label }} : {{ form.title }} <br/>
{{ form.body.label }} : {{ form.body }} <br/>
{{ form.main_post.label }} : {{ form.main_post }} <br/>
<button class="button postfix" type="submit">{% if post == False %}Add{% else %}Update{% endif %}</button>
A similar question was asked and answered here How to dynamically set default value in WTForms RadioField?
You should be able to do this by setting the default value and then running form.process().
form.main_post.default = post.main_post
form.process()

Django - Form is not saving the modifications

I'm creating a page where my users can edit their articles but there is one problem, my form is not saving the modifications when I submit my form. Let's have a look:
views.py
def edit(request, id=None, template_name='article_edit.html'):
if id:
article = get_object_or_404(Article, id=id)
if article.user != request.user:
return HttpResponseForbidden()
else:
article = Article(user=request.user)
if request.POST:
form = ArticleForm(request.POST, instance=article)
if form.is_valid():
save_it = form.save()
save_it.save()
form.save_m2m()
return HttpResponseRedirect("/")
else:
form = ArticleForm(instance=article)
context = {'form': form}
populateContext(request, context)
return render(request, template_name, context)
line 3 to 8 : Is to check if it's your own articles there is no problem with that.
line 10 to 18 : There is a problem between these lines, my form is not saving when I submit my form
forms.py (ModelForm)
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
exclude = ['date', 'rating', 'user']
form = ArticleForm()
(Line 4 : I'm excluding the date, the ratings and the username when saved so that the user can not change these informations.)
I don't have any problem in my template.html and the urls.py don't bother with that I checked over 10 times :)
Any help would be great, I'm blocked on this problem since over 1 month...
******* EDIT *******
Models.py
class Article(models.Model):
user = models.ForeignKey(User)
titre = models.CharField(max_length=100, unique=True)
summary = RichTextField(null=True, max_length=140)
contenu = RichTextField(null=True)
date = models.DateTimeField(auto_now_add=True, auto_now=False, verbose_name="Date de parution")
image = models.ImageField(upload_to='article', default='article/amazarashi.jpeg')
rating = RatingField(can_change_vote=True)
tags = TaggableManager(through=TaggedItem, blank=True)
def __str__(self):
return self.titre
Template.html
{% block body %}
{% if user.is_authenticated %}
<p>Authentificated as <strong>{{ user.username }}</strong></p>
{% else %}
<p>NOT Authentificated</p>
{% endif %}
<h1>Edit this {{ article.titre }}</h1>
<br>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-8">
<form enctype='multipart/form-data' action="{% url "article.views.index" %}" method="post" class="form" autocomplete="off" autocorrect="off">
{% csrf_token %}
<div class="form-group">TITRE
{{ form.titre.errors }}
{{ form.titre }}
</div>
<div class="form-group">SUMMARY
{{ form.media }}
{{ form.summary.errors }}
{{ form.summary }}
</div>
<div class="form-group">CONTENU
{{ form.media }}
{{ form.contenu.errors }}
{{ form.contenu }}
</div>
<div class="form-group">
{{ form.image.errors }}
{{ form.image }}
</div>
<div class="form-group">TAGS
{{ form.tags.errors }}
{{ form.tags }}
</div>
<input type="submit" class="btn btn-default" value="Submit"/>
</div>
</form>
{% endblock %}
According to your error message.. Modify your form in templates:
<form enctype='multipart/form-data' ...>
Add request.FILES to your Form creation:
if request.POST:
form = ArticleForm(request.POST, request.FILES, instance=article)
UPDATE:
You have strange url tag parameter. Are you sure you have defined your url like: ('...', your_view, name='article.views.index')? I am in doubt cause url tag takes url name as parameter but not view path and nobody usually uses url names like this.

django context form not rendered after form invalid

I have a doctor detail view in which I have passed form as context:
class HospitalDoctorDetailView(DetailView):
context = {}
model = HospitalDoctor
template_name = "hospital_doctor_detail.html"
context_object_name = 'doctor'
def get_context_data(self, **kwargs):
context = super(HospitalDoctorDetailView, self).get_context_data(**kwargs)
context['appointment_form'] = AppointmentForm1
return context
And I have used this form in the template named hospital_doctor_detail.html:
<form action="/appointment/{{doctor.id}}/{{doctor.hospital.id}}/" method="post">{% csrf_token %}
First Name:<br/>
{{ form.first_name.errors }}
{{ appointment_form.first_name }}<br/>
Middle Nmae:<br/>
{{ form.middle_name.errors }}
{{ appointment_form.middle_name }}<br/>
Last Name:<br/>
{{ form.last_name.errors }}
{{appointment_form.last_name}}<br/>
Age:<br/>
{{ form.age.errors }}
{{ appointment_form.age }}<br/>
Date:<br/>
{{ form.appointment_date.errors }}
{{ appointment_form.appointment_date }}<br/>
<br/>
<input type="submit" value="Take Appointment" style="background-color:#EFEFEF; border:1px solid #000;" />
</form>
My form AppointmentForm1 is a model form. To submit a form I have written a view:
def TakeAppointmentView(request, pk, hpk):
doctor = HospitalDoctor.objects.get(pk=pk)
hospital = Hospital.objects.get(pk=hpk)
if request.method == "POST":
form = AppointmentForm1(request.POST)
if form.is_valid():
app = DoctorAppointment()
app.user = request.user
app.doctor = doctor
app.hospital = hospital
app.first_name = form.cleaned_data['first_name']
app.middle_name = form.cleaned_data['middle_name']
app.last_name = form.cleaned_data['last_name']
app.age = form.cleaned_data['age']
app.appointment_date = form.cleaned_data['appointment_date']
app.save()
messages.success(request, "Thank you for taking appointment")
return redirect("doctor_detail", pk)
#return redirect("/home/")
else:
return render_to_response("hospital_doctor_detail.html", {"appointment_form":form}, context_instance=RequestContext(request))
else:
form = AppointmentForm1()
return render_to_response("hospital_doctor_detail.html", {"appointment_form":form}, context_instance=RequestContext(request))
If the form is valid appointment is taken successfully but if the form is invalid I want to redirect it to the same doctor detail view.
Here I am getting an error that if the form is invalid it is redirecting to the doctor detail view with the error message but form is not displayed??
Whats wrong in here??
You're returning your form to your template as {"application_form": form}.
You're template doesn't know anything about any variables called form.
Instead of using:
{{ form.first_name.errors }}
Try using the following for each of your error messages:
{{ application_form.first_name.errors }}

Showing a empty GET form without raising any error on Django

I'm trying to set an home page one my project that show a search form (with GET method).
The problem is that it raises an error at the moment I load the very page since the default request method is GET. Of course I can change the form's method to POST but that would not be the correct way, so I was wondering if there was any condition that I can set to avoid this issue and still be able to check any errors.
I'm working on Django 1.5 and Python 2.7
This if the form class:
class Search(forms.Form):
middleschool = 'MS'
highschool = 'HS'
university = 'U'
blank = '-'
school_choices = ((middleschool, 'Middle School'),
(highschool, 'High school'),
(university, 'University'),
(blank, 'Not defined'),)
title = forms.CharField(label='Keyworld')
subject = forms.ModelChoiceField(queryset=Subject.objects.order_by('?'),
required=False, label='Whitch subject you want to search?')
school = forms.ChoiceField(choices = school_choices, required=False,
label='What level of material are you searching?')
price = forms.BooleanField(required=False)
This is the relative view:
def home(request):
if request.method == 'GET':
form = Search(request.GET)
if form.is_valid():
cd = form.cleaned_data
ftitle = cd['title']
fsubject = cd['subject']
fschool = cd['school']
fprice = cd['price']
if fprice:
forms = File.objects.filter(name__contains='ftitle', subject='fsubject', school='fschool', price = '0,0')
return render(request, 'search.html', {'form': form})
else:
forms = File.objects.filter(name__contains='ftitle', subject='fsubject', school='fschool')
return render(request, 'search.html', {'form': form})
else:
form = Search()
return render(request, 'home.html', {'form': form})
This is the HTML:
{% block content %}
<hr>
<div id='search'>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="/search/" method="get">
<div class="field">{{ form.title.errors }}<label for="keyworld">Keyworld:</label>{{ form.title }}</div>
<div class="field"><label for="subject">Subject:</label>{{ form.subject }}</div>
<div class="field"><label for="school">Level:</label>{{ form.school }}</div>
<div class="field"><label for="price">Price yes or no:</label>{{ form.price }}</div>
<input type="submit" value="Search">
<input type="reset" value="Reset">
</form>
</div>
<hr>
{% endblock %}
You simply have to add or None, like this:
form = SearchForm(request.GET or None)
Rather than checking the request method, you could check whether request.GET is empty:
if request.GET:
form = SearchForm(request.GET)

Categories

Resources