My form has initial values in it. I use form.as_hidden to hide the values and pass those values through a POST request. However, the hidden values are not passing through. Is there a way through this?
views.py
def car_detail_view(request, id):
if request.method == "POST":
form = CarForm(request.POST)
print(form.is_valid())
if form.is_valid():
car_save = form.instance
get_car = Car.objects.get(number_plate=car_save.number_plate)
get_car.available = False
get_car.save()
return redirect('/')
else:
print(form.errors)
else:
car = Car.objects.get(id=id)
form = CarForm(initial={'brand':car.brand, 'number_plate':car.number_plate, 'price':car.price,
'available':car.available})
args = {
'car':car,
'form':form
}
return render(request, 'map/confirmation.html', args)
confirmation.html
<h1>Confirmation of Booking</h1>
{% block content %}
<p>Brand: {{ car.brand }}</p>
<p>Number Plate: {{ car.number_plate }}</p>
<p>Price: {{ car.price }}</p>
<p> Are you sure you want to book? <p>
<form class="" method="post">
{% csrf_token %}
{{ form.as_hidden }}
<input type="submit" value="Book {{ car.brand }}">
</form>
{% endblock %}
Error
<ul class="errorlist"><li>brand<ul class="errorlist"><li>This field is required.</li></ul></li><li>number_plate<ul class="errorlist"><li>This field is required.</li></ul></li><li>price<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
Django doesn't have a form.as_hidden method. Therefore {{ form.as_hidden }} will render as the empty string '' in your template.
You can use the as_hidden method for individual form fields.
{{ form.number_plate.as_hidden }}
If you use values from hidden fields, you might need to add code to prevent the user altering the field values (e.g. with their browser's developer tools). However, in your case you don't need to get the values from the form, you can fetch them from the database.
def car_detail_view(request, id):
if request.method == "POST":
car = Car.objects.get(id=id)
car.available = False
car.save()
return redirect('/')
else:
car = Car.objects.get(id=id)
args = {
'car':car,
}
return render(request, 'map/confirmation.html', args)
Once you've got this working, you might want to think about what happens if two users try to book the same car at once.
Related
I'm using WTForms and Flask, I am trying to create a form where I can enter information about a recipe, but the product_name SelectField is returning None every time.
The form:
class CreateRecipeForm(Form):
product_name = SelectField(choices=get_craftables_options())
product_quantity = IntegerField(default=1)
job_field = SelectField(choices=['ALC', 'GSM', 'WVR'])
line_item_list = FieldList(FormField(RecipeLineForm), min_entries=6)
save_button = SubmitField()
The view:
#bp.route('/edit/new', methods=('GET', 'POST'))
def create_recipe():
form = CreateRecipeForm()
if request.method == 'POST':
selected_product = Item.query.get(form.product_name.data)
(do stuff here)
The template
{% block content %}
<form method="post">
{{ render_field(form.product_name) }}
{{ render_field(form.product_quantity) }}
{{ render_field_no_label(form.line_item_list) }}
{{ render_field_no_label(form.save_button) }}
</form>
{% endblock %}
I believe your issue lies in declaring the product_name. Make sure the get_craftables_options() is supposed to be a function and is returning a list of items compatible with the choices argument.
product_name = SelectField(choices=get_craftables_options())
I am getting an error with a view that i have and i was wondering if anyone can help me figure out where it is coming from. I am pretty sure it is something small that I am not seeing where it is coming from...
Within the view there will be a form that is displayed for the user to input informaiton, once the form is submitted, it is processed and then redirect to the users home...
Here is the error:
ValueError at /transfer/
The view tab.views.transfers didn't return an HttpResponse object. It returned None instead.
Request Method: POST
Request URL: http://localhost:8000/transfer/
Django Version: 1.8.6
Exception Type: ValueError
Exception Value:
The view tab.views.transfers didn't return an HttpResponse object. It returned None instead.
Here is the views.py
def transfers(request):
if 'username' not in request.session:
return redirect('login')
else:
username = request.session['username']
currentUser = User.objects.get(username = username)
if request.method == 'POST':
form = TransferForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
from_acct = cd['from_acct']
to_acct = cd['to_acct']
amount = cd['amount']
memo = cd['memo']
new_transfer = Transfers.objects.create(
user = currentUser,
from_acct = from_acct,
to_acct = to_acct,
amount = amount,
memo = memo,
frequency = 1,
status = 1,
)
return redirect('home_page')
else:
form = TransferForm()
form.fields['from_acct'].queryset = Accounts.objects.filter(user = currentUser).all()
message = 'please fill out the below form'
parameters = {
'form':form,
'currentUser':currentUser,
'message':message,
}
return render(request, 'tabs/user_balance.html', parameters)
Here is the html file:
{% extends "base.html" %}
{% block content %}
<h1>Transfer Money</h1>
{% if message %}
<p>{{message}}</p>
{% endif %}
<form action="." method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="submit" value="submit">
</form>
{% endblock %}
Here is the forms.py file portion
class TransferForm(forms.ModelForm):
acct_choices = (('tabz', 'Tabz - Username'),
('Wells Fargo', 'Wells Fargo - Username'))
from_acct = forms.TypedChoiceField(
choices=acct_choices, widget=forms.RadioSelect, coerce=int
)
to_acct = forms.TypedChoiceField(
choices=acct_choices, widget=forms.RadioSelect, coerce=int
)
class Meta:
model = Transfers
fields = ['from_acct', 'to_acct', 'amount', 'memo']
labels = {
'from_acct':'from',
'to_acct':'to',
}
from django.http import HttpResponse, HttpResponseRedirect
if request.method == 'POST':
form = TransferForm(request.POST)
if form.is_valid():
...
return HttpResponseRedirect(reverse_lazy('home'))
else:
form.fields['from_acct'].queryset = Accounts.objects.filter(user = currentUser).all()
message = 'please fill out the below form'
parameters = {
'form':form,
'currentUser':currentUser,
'message':message,
}
return render(request, 'tabs/user_balance.html', parameters)
html add form.errors
{% extends "base.html" %}
{% block content %}
<h1>Transfer Money</h1>
{% if message %}
<p>{{message}}</p>
{% endif %}
<form action='your_url/' method="POST">
{% csrf_token %}
{{ field.errors }}
{{ form.as_p }}
<input type="submit" name="submit" value="submit">
</form>
{% endblock %}
Well, this error should be thrown simply because you are giving an invalid form to your view. If you look at the logic of the view, if it is a POST and form is not valid the view does not return anything... well None for python. That's the error you are getting right?
Try to put an else statement with return after return redirect('home_page') and see if this fixes this part.
I want to update a model entry using a form. the problem is that instead of updating the entry it creates a new entry.
def edit(request, c_id):
instance = get_object_or_404(C, id=int(c_id))
if request.POST:
form = CForm(request.POST, instance=instance)
if form.is_valid():
form.save()
return redirect('/a/b', c_id)
else:
form = CForm(instance=instance)
args = {}
args.update(csrf(request))
args['form'] = form
args['c_id'] = c_id
return render_to_response('a/b.html', args)
HTML code:
<form action="/a/edit/{{ c_id }}/" method="post">
{% csrf_token %}
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
<input type="submit" value="Submit"/>
</form>
CForm class code
class CForm(forms.ModelForm):
class Meta:
model = C
fields = ['name', 'code']
You're checking the request for a POST method incorrectly. request.POST isn't a boolean, it contains a dictionary of post variables and is always going to have the CSRF token in it so it will always be "truthy". What you need is request.method.
Instead of:
if request.POST:
Replace it with:
if request.method == "POST":
The form, that is described below, is not valid. And expression {{ search_id_form.errors }} doesn't show anything.
Django template:
<form method="POST">
{% csrf_token %}
{{ search_id_form.idtype.label_tag }}
{{ search_id_form.idtype }}
{{ search_id_form.index.label_tag }}
{{ search_id_form.index }}<br>
<input type="submit" name="id_search_button" value="Submit">
</form>
Python class:
class IDSearchForm(forms.Form):
idtype = forms.ChoiceField(
choices=[('idx', 'Our Database ID'), ('uprot', 'UniProt'), ('ncbi', 'NCBI')],
initial='idx',
widget=forms.RadioSelect,
label="Which identifier to use:"
)
index = forms.CharField(label="Identifier:")
View:
def search(request):
if request.method == 'POST':
# handling other forms ...
# find a toxin by id
if 'id_search_button' in request.POST:
search_id_form = IDSearchForm()
if search_id_form.is_valid():
idtype = search_id_form.cleaned_data['idtype']
index = search_id_form.cleaned_data['index']
return render(request, 'ctxdb/result_ctx.html', {
# here I try to use predefined object to pass to renderer (for debugging)
'ctx': get_object_or_404(CTX, idx='21')
})
# handling other forms ...
# other forms
search_id_form = IDSearchForm()
# other forms
return render(request, 'ctxdb/search.html', {
# other forms
'search_id_form': search_id_form,
# other forms
})
In the view function I handle four different forms on single page. Other forms work correctly. What is the problem here?
When calling .is_valid, you need to pass the data to search_id_form which you are not doing.
Change
search_id_form = IDSearchForm()
to
search_id_form = IDSearchForm(request.POST)
I have the following view,template and form through which i am implementing the formset. I intend to implement multiple formsets in a single view/template but my number of formsets is dynamic based on user input. How can i have multiple dynamic number of formsets in this code?
Can i do this with dictionary element i.e by creating a dictionary of formsets??
My view is as follows:
def show (request):
b = request.session["s1"] # count of no of period ids
c = request.session["s2"] # account number inserted by user
d = request.session["s3"] # year inserted by customer
a = account_period.objects.filter(year=d).values('id')
e = account_period.objects.filter(year=d).values('month')
f = account_period.objects.filter(id = a).values('year')
butt = formset_factory(bu, extra=b)
if request.method == 'POST'
formset = butt(request.POST)
if formset.is_valid():
z = account_tab.objects.get(account_number=c)
pr = date.today()
i=0
for form in formset.forms:
x = form.cleaned_data['value']
y = account_period.objects.get(id=a[i:(i+1)])
try:
uip = budget.objects.get(account_no = c,account_period = a[i:(i+1)])
if uip.budget_amount != x
uip.budget_amount = x
uip.save()
except budget.DoesNotExist:
w = budget(account_no = z, account_period = y, budget_amount = x, created_by_login = 'me')
w.save()
i=i+1
pass
return HttpResponse('thanks')
form is
class bu(forms.Form):
value = forms.CharField()
template is
<html>
<head>
<title>BUDGET</title>
</head>
<body>
<p>BUDGET MANAGEMENTS</p>
<p>Your Account Number is : {{ account_number }}.</p> <p>You Chose {{ period }} {{month}} as period<p>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="." method="post">{% csrf_token %}
{{ formset.management_form }}
<table>
{% for form in formset.forms %}
{{ form }}
{% endfor %}
</table>
<input type="submit" value="Submit">
</form>
</body>
</html>
#
#rohan
my GET method return has many variables which has to be passed into template so i tried to pass the dictionary formsetlist (after appying the changes u suggested) in following 2ways
1)
formset = butt( return render_to_response('budgetfinalform.html', {'account_number': c,'period':d,'month':e,'year':f,'formset': formset},context_instance=RequestContext(request))
2)
ctx ={'formsetlist': formset}
formset = butt( return render_to_response('budgetfinalform.html', {'account_number': c,'period':d,'month':e,'year':f,ctx,context_instance=RequestContext(request))
but obtained "unboundlocalerror : local variable 'formset' referenced before assignment"
I would do something like:
def show (request):
#initial view processing
# fomset_count taken as parameter or user input
formsetlist = []
#create formset list
for i in range(0, formset_count):
formsetlist.append(formset_factory(bu, extra=b))
# other view related code
# for GET method
ctx = { 'formsetlist': formset }
return render_to_response('your_template_name', ctx,
context_instance = RequestContext(request)
)
In template:
<form action="." method="post">{% csrf_token %}
{% for formset in formsetlist %}
{{ formset.management_form }}
<table>
{% for form in formset.forms %}
{{ form }}
{% endfor %}
</table>
{%endfor%}
<input type="submit" value="Submit">