Creating a simple django form - python

I am new to django and and I'm trying to use forms.I want to create a form with two CharFields. Here is where I am so far -
forms.py
from django import forms
class NameForm(forms.Form):
key = forms.CharField(label='Enter Key:', max_length=2)
value = forms.CharField(label='Enter Value:', max_length=4)
template.html
<form action="/new-page/" method="GET">
{{ form }}
<input type="submit" value="Submit" />
</form>
What I want is to take the data in this form and simply use that data in my function myfunc
views.py
def myfunc(request,id):
key = request.GET.get('key')
value = request.GET.get('value')
where id is the id of the page where the form appears like so url/places/1/
I want the action to send the id and the key,value pair to the function to use on submit.Validation is not required. Can someone help me understand the concept here.

Your views.py should look like:
def myfunc(request, id):
form = NameForm(request.GET or None)
if form.is_valid():
key = form.cleaned_data['key']
value = form.cleaned_data['value']
# do something with key and value

Related

How to get multiple elements from a form using request.form.get

I have a form inside an html file, this form is creating new input fields in which the user is supposed to type some info. Later, i wanna pass all those values into my python main file (application.py)and do somethings with them. The problem is that i don't know how to pass several values into python. Normally i would use this
request.form.get("username")
which returns me the value of the input field named "username" inside my html file. Now, i have several input fields which are generated when the user pushes a button:
$("#add_dream").click(function(){
$("#"+x).append('<button type="submit" style="height:30px;" class="delete"
id="ix">Remove</button>')
document.getElementById("ix").setAttribute("id","delbuttdream"+j)
}
This is not the whole code, but it may help to understand what i'm saying. This new fields can be created an deleted as many times as the user wants to, so the name of the fields or their ids don't follow a straight order (1,2,3,4...). I wanna know if there's anyway in which i can call from python using request.form.get all the elements of the same clase or with certain id and not only one of them by name
Example form:
Items in random order</br>
<form method="POST">
<input name="item4" value="val4"/></br>
<input name="item2" value="val2"/></br>
<input name="item1" value="val1"/></br>
<input name="item3" value="val3"/></br>
<button type="submit">OK</button>
</form>
request.form behaves like dictionary and you can use request.form.items() to get all keys and values and filter them.
for key, val in request.form.items():
#print(key,val)
if key.startswith("item"):
print(key, val)
or request.form.keys() to get only keys to filter and sort them.
keys = request.form.keys()
keys = [key for key in keys if key.startswith("item")]
keys = sorted(keys)
for key in keys:
#print(key, request.form[key])
print(key, request.form.get(key))
Minimal working code:
from flask import Flask, request, render_template_string
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
print('--- original order ---')
for key, val in request.form.items():
if key.startswith("item"):
print(key, val)
print('--- sorted ---')
keys = request.form.keys()
keys = [key for key in keys if key.startswith("item")]
keys = sorted(keys)
for key in keys:
#print(key, request.form[key])
print(key, request.form.get(key))
return render_template_string('''Items in random order</br>
<form method="POST">
<input name="item4" value="val4"/></br>
<input name="item2" value="val2"/></br>
<input name="item1" value="val1"/></br>
<input name="item3" value="val3"/></br>
<button type="submit">OK</button>
</form>
''')
if __name__ == '__main__':
app.run(debug=True)
If there are multiple keys, and the keys are the same, it will return only the first item.
If you need a list with these values, use simply .getlist().
Example:
request.form.getlist('keyname'))

Django hide field from forms and add automatically field

I want to add to the cart the actual product I'm in (product_detail.html).
So in the product_unit, is just needed to specify the quantity of the product.
Anyway I can't make the unit_product, automatically add the actual product I'm in.
forms.py
class Product_unitForm(forms.ModelForm):
class Meta:
model = Product_unit
fields = [
'product',
'quantity',
]
widgets = {'product': forms.HiddenInput()}
I hide the product from the template, because it is just the actual product, no need to specify.
views.py
def product_detail(request, id_category=None,id_product=None):
actual_product = Product.objects.get(id = id_product)
#Has an actual customer
#FORM
form_product_unit = Product_unitForm(request.POST or None)
form_product_unit.fields['product'] = actual_product # I try to add the product this way
if form_product_unit.is_valid():
instance_product_unit = form.save(commit=False)
instance_product_unit.product.save()
last_order = Order.objects.last()
is_buying = False
if(last_order.status == "en curso"):
is_buying = True
context = {
"Product" : actual_product,
"Is_buying" : is_buying,
#FORMS
"form_product_unit" : form_product_unit,
}
return render(request, "shopping/product_detail.html", context)
I want to manually from the views, add the product field of product_unit to the actual product it has (actual_product)
template
<img src="{{Product.image.url}}"/>
<h1>{{Product.title}}</h1>
<form method="POST" action="">{% csrf_token %}
{{ form_product_unit.as_p }}
<input type="submit" value="Add" />
</form>
In your views.py file I think you just need to make two changes
def product_detail(request, id_category=None,id_product=None):
actual_product = Product.objects.get(id = id_product)
form_product_unit = Product_unitForm(data=request.POST or None,
initial={'product': actual_product})
And also remove the line form_product_unit.fields['product'] = actual_product. You might need to play around with the initial dictionary a bit to get it to bind the correct value to the field but that's the general idea. The related section in the docs is https://docs.djangoproject.com/en/1.9/ref/forms/api/#dynamic-initial-values

Get value of a form input by ID python/flask

How do you get the actual value of the input id after you send it in Flask?
form:
<form action="" method="post">
<input id = "number_one" type="text" name="comment">
<input type="submit" value = "comment">
</form>
like, what I am trying to say is when the form is sent (i.e. when you do this):
request.form.get("comment")
the value of the text field is passed. What I can't figure out is how to get the value of the id.
So, when the form is sent we could then tell from which form the info was coming from, because each form has a unique id. In this case the id is number_one.
So, how do we go about getting the actual literal value of the id and not the text input?
You can't. The id value is not part of the form data set sent by the browser.
If you need to identify the field, you'll have to either add the id to the input element name, or if the id is generated by Javascript code, perhaps store the information in an extra hidden field.
Adding the id to the name could be done with a delimiter perhaps:
<input id = "number_one" type="text" name="comment.number_one">
which would require you to loop over all form keys:
for key is request.form:
if key.startswith('comment.'):
id_ = key.partition('.')[-1]
value = request.form[key]
There is a one way to identify the fields and also multiple forms together....
use this
<input value = "1" type="hidden" name="my_id">
so at your view file you can retrieve this value.
my_id = request.form.get("my_id","")
print my_id
your output will be
1
you can also do this...
my_id = request.form.get("my_id","")
if my_id == "1":
** for example **
value = request.form.get("any_parameter_of_form","")

Django fill up ChoiceField - Select html options

I am facing problem filling my select options using django forms. Even though I define choices, I don't see any choices.
My form in .py file:
class SignupForm(forms.Form):
countrySignup = forms.ChoiceField( required = True,
widget = forms.Select( choices = ('United States', 'Jordan') ))
my html template has the following:
<p>
<label for="countrySignup" class="youcountry" data-icon="">Your Country </label> </br>
{{ signupForm.countrySignup }}
{{ signupForm.countrySignup.errors }}
</p>
and of course my view has the following code to pass the variable to template:
def myView(request):
#
# create the unbinded forms for registration
#
if request.method == 'GET':
signupForm = regForms.SignupForm()
return render(request,
"login.html",
{'loginForm': loginForm,
'signupForm' : signupForm })
What am I missing because I don't see any options in my select , it remains empty
I missed the documentation that choices needs to be a list of tuples with 2 elements each.
choices:
An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this field. This argument accepts the same formats as the choices argument to a model field. See the model field reference documentation on choices for more details.**
this solved it:
countrySignup = forms.ChoiceField( choices = [('PS', 'Palestine'),
('JD', 'Jordan')] )

Saving the order of items

My model:
class Category(models.Model):
name = models.CharField(max_length=50, unique=True)
order = models.SmallIntegerField()
My template:
{% for c in categories %}
{{ c }} -- <input type="text" name="order[{{ c.id }}]" value="{{ c.order }}">
Submit Button
{% endfor %}
My view:
def category_order(request):
print request.POST
print request.POST.getlist('order[]')
Output:
<QueryDict: {u'order[3]': [u'1'], u'order[1]': [u'1'], u'order[5]': [u'2'], u'order[4]': [u'33'], u'order[2]': [u'2'], u'order[6]': [u'3'], u'csrfmiddlewaretoken': [u'4XjehEwMdNK032342JkYJvBJabunKB'], u'order-btn': [u'order']}>
[]
So my question is how can I loop over every order[N] and get the category ID and its new order value to save it to the database?
Using dict comprehension:
orders = {name.split('[')[1].split(']')[0]: request.POST[name]
for name in request.POST if name.startswith('order[')}
# `orders` is not a dictionary maps `id`s to `order`s.
# Do something with `orders`.
Or using simple for loop:
for name in request.POST:
if not name.startswith('order['): continue
id_ = name.split('[')[1].split(']')[0]
order = request.POST[name]
# Do something with `id_`, `order`
If you are looking at having ordered objects, there is a library, django-ordered-model , that can take care of that. That includes a good, drag-and-drop admin view. For example:
from django.db import models
from ordered_model.models import OrderedModel
class Category(OrderedModel):
name = models.CharField(max_length=50, unique=True)
class Meta(OrderedModel.Meta):
pass

Categories

Resources