I have created select tag with four option values(1,2,3,4).When I select 4 and press submit it changes back to 1.Select option contains quantity of the product needed for the user.So how to retain option value after pressing submit button.I tried like this,after I press submit button value changes back to 1.Is there any way to overcome this problem?
My template file,
<label for="quantity">Quantity</label>
<select id="quantity" name="quantity">
<option value="1" {% if quantity == '1' %}selected{% endif %}>1</option>
<option value="2" {% if quantity == '2' %}selected{% endif %}>2</option>
<option value="3" {% if quantity == '3' %}selected{% endif %}>3</option>
<option value="4" {% if quantity == '4' %}selected{% endif %}>4</option>
</select>
<input type="submit" value="Buy"/>
UPDATE:
forms.py,
class SortForm(forms.Form):
RELEVANCE_CHOICES = (
(1,'1'),(2, '2'),(3,'3'), (4,'4'),(5,'5'),
)
sort = forms.ChoiceField(choices = RELEVANCE_CHOICES,label='Quantity')
views.py,
from .forms import SortForm
#csrf_protect
def buy_book(request,pk):
form = SortForm(request.POST or None)
my_products = Add_prod.objects.filter(pk=pk)
#Add_prod is the model class name
context = {"products":my_products}
if request.POST.get('quantity'):
for i in my_products:
rate= i.price
#price is the column name in the model class
u_quantity = request.POST.get('quantity')
Quantity=int(u_quantity)
total = rate*Quantity
context = {
"products":my_products,
"Total":total,
"form": form
}
return render(request,"buy_book.html",context)
In the template file I added this line,
{{form.as_p}}
Now I am getting blank output.I think the form is not recognising in the template.
The problem here that your template is just showing data, it doesn't know anything about state. So if you want to achieve this kind of behavior you need to supply all required data from backend. Also as #solarissmoke mentioned you should use django forms.
for exmaple(Pseudo code below)
def my_view(request):
if request.method == 'POST':
form = MyForm(request.data)
if form.is_valid():
form.save()
redirect(reverse('myview'))
else:
form = MyForm(instance) # <- instance is object with previously saved data
return render(request, 'my_template.html' , {'form': form})
Second Part
def buy_book(request,pk):
form = SortForm(request.POST or None)
my_products = Add_prod.objects.filter(pk=pk)
#Add_prod is the model class name
context = {"products":my_products}
if request.POST.get('quantity'):
for i in my_products:
rate= i.price
#price is the column name in the model class
u_quantity = request.POST.get('quantity')
Quantity=int(u_quantity)
total = rate*Quantity
context = {
"products":my_products,
"Total":total,
"form": form # <- here is problem
}
return render(request,"buy_book.html",context)
You are adding form to context inside if request.method == 'POST'. It should like this
def buy_book(request,pk):
form = SortForm(request.POST or None)
my_products = Add_prod.objects.filter(pk=pk)
#Add_prod is the model class name
context = {"products":my_products, 'form': form} # <- here
if request.POST.get('quantity'):
for i in my_products:
rate= i.price
#price is the column name in the model class
u_quantity = request.POST.get('quantity')
Quantity=int(u_quantity)
total = rate*Quantity
context = {
"products":my_products,
"Total":total,
}
return render(request,"buy_book.html",context)
In your view, you only ever add the form to the context data if there is a quantity in the post data, you should add this to the context regardless since it is required for your view.
You should also actually use the form, so instead of checking the post data, check the form for validity and then use its cleaned data.
def buy_book(request,pk):
form = SortForm(request.POST or None)
my_products = Add_prod.objects.filter(pk=pk)
#Add_prod is the model class name
context = {"products":my_products,
'form': form}
if form.is_valid():
for i in my_products:
rate= i.price
#price is the column name in the model class
u_quantity = form.cleaned_data.get('sort', 0)
Quantity=int(u_quantity)
total = rate*Quantity
context['total'] = total
return render(request,"buy_book.html",context)
'int' object is not iterable
Probably because your sort field isn't a list of tuples
choices = [(i, i) for i in range(1,6)]
Related
How to realize checking 'name' for current user in forms.py in ValidationError('Same name already added, change name').
views.py
#login_required
def main_page(request):
form = URL_listForm(request.POST)
if request.method == "POST":
if form.is_valid():
name = form.cleaned_data['name']
if URL_list.objects.filter(user=request.user, name=name).exists():
return HttpResponse('Same name already added, change name')
new_post = form.save(commit=False)
new_post.user = request.user
new_post.save()
return HttpResponse("Data added")
return render(request, 'link/main.html', {'form': form})
If you want validate in database
#-------ADDED CODE
data_tmp = """SELECT count(*) from jobtest WHERE link = %s""", (line)
data_tmp = cur.fetchall()
#-------END ADDED CODE
if (data_tmp == 0 ) :
Not exist
add form with name
<input type="text" id="projectName" size="40" placeholder="Spot your project files">
<input type="button" id="spotButton" value="Spot">
when press post button and action to api you can get value in input field using request.form['Name']
if you want send data from server code to html
return render_template('index.html', data=userinfo)
and render as
{% userinfo %}
I have two select classes that I am trying to create in an unbound form. The data selections are only relevant to the presentation that is created in the view, so are throwaways and do not need to be saved in a model.
The challenge I have is that I can pass in the field listings ok, but how do I set "default" checked / selected values so that the form becomes 'bound'?
views.py
def cards(request):
sort_name = []
sort_name.append("Alphabetic Order")
sort_name.append("Most Popular")
sort_name.append("Least Popular")
sort_name.append("Highest Win Rate")
sort_name.append("Lowest Win Rate")
sort_id = range(len(sort_name))
sort_list = list(zip(sort_id, sort_name))
<more code to make filt_list and zip it>
if request.method == 'POST':
form = cardStatsForm(request.POST, sortList=sort_list, filtList=filt_list)
if form.is_valid():
do something
else:
do something else
else:
form = cardStatsForm(filter_list, sort_list)
forms.py
class cardStatsForm(forms.Form):
def __init__(self, filterList, sortList, *args, **kwargs):
super(cardStatsForm, self).__init__(*args, **kwargs)
self.fields['filts'].choices = filterList
self.fields['filts'].label = "Select player rankings for inclusion in statistics:"
self.fields['sorts'].choices = sortList
self.fields['sorts'].label = "Choose a sort order:"
filts = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=(), required=True)
sorts = forms.ChoiceField(choices=(), required=True)
The difficulty I am having is the the form fails the "is_valid" test since it is not bound, and I have the "required=true" setting (so that the user must select a checkbox / select a value), but I cannot enforce the logic since it seems the form is never 'bound'.
You can use django forms validation or pass defult value in your views.py. It will return unbound forms if value doesn't match with your default value.
let show you how to do it in your views.py:
error_message = None
default_value = "jhone"
if form.is_valid():
name = request.POST['name']
defult_name = jhone
if defult_name != name:
error_message = 'Name must be jhone'
if not error_message:
form.save() #it will only save forms if default value match
else:
do something else
context = {'error_message':error_message,
'default_value': default_value,
'form':form,
} #pass the context in your html template for showing default value and error message
in your .html
{{error_message}}
<input type=text name='name' {%if form.is_bound %} value="{{default_value}} {%endif%}">
I was able to correct my issue by adding "inital=0" and modifying my form call as outlined below:
forms.py
filts = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=(), initial=0, required=True)
sorts = forms.ChoiceField(choices=(), initial=0, required=True)
views.py
if request.method == 'POST':
form = cardStatsForm(data=request.POST, sortList=sort_list, filterList=filter_list)
else:
form = cardStatsForm(filter_list, sort_list)
I'm entering a duplicate value (already saved in another instance of the same model) in my form to test the unique=True attribute. form.is_valid() returns 'False', as expected, but I don't receive any prompt in the template. Shouldn't I get prompted something like "obj with this value already exists"? The page simply reloads... What am I missing?
forms.py
def update_route(request, pk):
instance = Route.objects.get(id=pk)
if request.method == "POST":
form = RouteForm(request.POST)
if form.is_valid():
data = form.cleaned_data
instance.name = data['name']
instance.priority = data['priority']
instance.url = data['url']
return redirect('campaigns:routes_list')
form = RouteForm(instance=instance)
context= {
'form': form,
}
return render(request, "campaigns/route_form.html", context)
models.py
class Route(models.Model):
name = models.CharField(max_length=48)
priority = models.SmallIntegerField(choices=PRIORITY_LEVEL, default=0, unique=True)
url = models.URLField()
Template
<form method="post" action="">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit">
</form>
Your update_route() view handles the condition in which the submitted form is valid (form.is_valid()), but not the condition in which the form is invalid.
The errors you are looking for are stored in the form object that you created with RouteForm(request.POST). The errors are generated when the is_valid() method is called.
This form object needs to be added to the context dict and rerendered to the user for the errors to surface. But your code currently overwrites that object with form = RouteForm(instance=instance), so the POST data and the related errors disappear.
One solution could be to handle it in the conditional statement:
if form.is_valid():
...
else:
context = {'form': form}
return render(request, "campaigns/route_form.html", context)
Another solution could be to create a conditional statement for GET requests, for example:
elif request.method == 'GET':
form = RouteForm(instance=instance)
I want to show an initial value in the form. At runtime no errors occurs, the field stays empty. Why isn't it showing the value?
views.py:
def mieteinheit(request, wohnungsgruppenname):
if request.method == 'POST':
#...
else:
form = WohnungseinheitenForm(request.POST or None,initial={'ort':'Hof'})
template = loader.get_template('Immo/user/mieteinheit.html')
context = {"wohnungsgruppenname":wohnungsgruppenname,"form": form}
return HttpResponse(template.render(context,request))
.html-File:
<input class="form-control" id="{{ form.ort.auto_id }}" name="ort" type="text" >
Form.py:
class WohnungseinheitenForm(forms.ModelForm):
ort = forms.CharField(required=True,max_length=100)
In forms.py, add initial property to the ort field.
ort = forms.CharField(required=True,max_length=100,initial='Hof')
Given the following models:
class Graph(models.Model):
owner = models.ForeignKey(User)
def __unicode__(self):
return u'%d' % self.id
class Point(models.Model):
graph = models.ForeignKey(Graph)
date = models.DateField(primary_key = True)
abs = models.FloatField(null = True)
avg = models.FloatField(null = True)
def __unicode__(self):
return u'%s' % self.date
I am trying to create a form for editing lists of Points.
The HTML input tags require additional attributes to be set, so I am using the following custom form:
class PointForm(forms.ModelForm):
graph = forms.ModelChoiceField(queryset = Graph.objects.all(),
widget = forms.HiddenInput())
date = forms.DateField(widget = forms.HiddenInput(), label = 'date')
abs = forms.FloatField(widget = forms.TextInput(
attrs = {'class': 'abs-field'}),
required = False)
class Meta:
model = Point
fields = ('graph', 'date', 'abs') # Other fields are not edited.
def pretty_date(self):
return self.data.strftime('%B')
At this point I do not know how to pass instances of the Point class to a FormSet:
def edit(request):
PointFormSet = forms.formsets.formset_factory(PointForm, extra = 0)
if request.method == 'POST':
return
# Receive 3 points to edit from the database.
graph, res = Graph.objects.get_or_create(id = 1)
one_day = datetime.timedelta(days = 1)
today = datetime.date.today()
do_edit = []
for date in [today - (x * one_day) for x in range(3)]:
point, res = Point.objects.get_or_create(graph = graph, date = date)
do_edit.append(point)
formset = PointFormSet(????) # How is this initialized with the points?
I found a hack that somewhat works, but it leads to errors later on when trying to process the resulting POST data:
do_edit = []
for date in [today - (x * one_day) for x in range(3)]:
point, res = Point.objects.get_or_create(graph = graph, date = date)
data = point.__dict__.copy()
data['graph'] = graph
do_edit.append(data)
formset = PointFormSet(initial = do_edit)
How is this done correctly?
For the reference, my template looks like this:
<form action="" method="post">
{{ formset.management_form }}
<table>
<tbody>
{% for form in formset.forms %}
<tr>
<td>{{ form.graph }} {{ form.date }} {{ form.pretty_date }}:</td>
<td width="100%">{{ form.abs }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
The trick is to use a "ModelFormset" instead of just a formset since they allow initialization with a queryset. The docs are here, what you do is provide a form=* when creating the model formset and queryset=* when your instantiating the formset. The form=* arguement is not well documented (had to dig around in the code a little to make sure it is actually there).
def edit(request):
PointFormSet = modelformset_factory(Point, form = PointForm)
qset = Point.objects.all() #or however your getting your Points to modify
formset = PointFormset(queryset = qset)
if request.method == 'POST':
#deal with posting the data
formset = PointFormset(request.POST)
if formset.is_valid():
#if it is not valid then the "errors" will fall through and be returned
formset.save()
return #to your redirect
context_dict = {'formset':formset,
#other context info
}
return render_to_response('your_template.html', context_dict)
So the code walks through easily. If the request is a GET then the instantiated form is returned to the user. If the request is a POST and the form is not .is_valid() then the errors "fall through" and are returned in the same template. If the request is a POST and the data is valid then the formset is saved.
Hope that helps.
-Will
If you only have one possible value which you want to set, or perhaps a closed of values, it is possible to set them after the user POSTS the data to your server using commit=False
Please consider the following code:
class UserReferralView(View):
ReferralFormSet = modelformset_factory(ReferralCode,
form=ReferralTokenForm, extra=1)
def get(self, request):
pass
def post(self, request):
referral_formset = UserUpdateView.ReferralFormSet(request.POST)
if referral_formset.is_valid():
instances = referral_formset.save(commit=False)
for instance in instances:
instance.user = request.user
instance.save()
return redirect(reverse('referrals.success_view'))
else:
return redirect(reverse('referrals.failure_view'))