I am trying to create an app where a user can manage a database of "Lost property" items. To do so I have a main page where all the items are displayed and I have a button per row to be clicked when the item is returned to the owner.
That button is submitting a form that should contain the ID value of the element that has been clicked so I trying to get something like
<input id="id_id" name="id" type="hidden" value="{{lostitem.id}}">
But I don't know how to pass that value to my form ! Here is my template :
{% for lostitem in lostitems %}
<tr>
<td>{{lostitem.id}}</td>
<td>{{lostitem.description}}</td>
<td>
<form class="give-back-item-form" method="POST">
{% csrf_token %}
{{formGiveBackItem.as_p}}
<button type="submit" class="button btn btn-xs btn-success buttonItems">
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
</button>
<!-- TRYING TO ADD A HIDDEN INPUT WITH THE ID AS VALUE -->
</form>
</td>
</tr>
{% endfor %}
Here is my form from forms.py
class GiveBackItemForm(forms.ModelForm):
id = forms.CharField(widget=forms.HiddenInput())
class Meta:
model = ItemLost
fields = ('id',)
And here is where I'm trying to get my $_POST['id'] and to update my object (I couldn't test this part as I'm not getting any POST information at the moment) :
from .forms import GiveBackItemForm
"""Defining our views"""
def item_list(request):
formGiveBackItem = GiveBackItemForm()
"""Ordering objects by date of creation"""
lostitems = ItemLost.objects.filter(added_date__lte=timezone.now()).order_by('added_date')
if request.method == "POST":
"""Giving back an item"""
itemToGive = ItemLost.objects.get(pk=request.POST.get('id'))
itemToGive.giveBackItem
"""Returning our ordered objects to the view"""
"""Request = everything we receive from the user (in a form for example)"""
return render(request, 'lostitem/item_list.html', {'lostitems': lostitems, 'formGiveBackItem' : formGiveBackItem})
Thanks for any help or remark about the code ! I'm just getting started and it was really hard to find anything helpful about my problem
EDIT : I managed to make it work by still using the Django ModelForm and the view to handle my form
Here is my code in my view :
def item_list(request):
"""Ordering objects by date of creation"""
lostitems = ItemLost.objects.filter(added_date__lte=timezone.now()).order_by('added_date')
"""To get data from the form"""
give_back_item_form = GiveBackItemForm(request.POST or None)
# check if form is valid
if give_back_item_form.is_valid():
itemToGive = ItemLost.objects.get(pk=give_back_item_form.cleaned_data['id'])
itemToGive.returned_date=timezone.now()
itemToGive.save()
# your rest of the code here
"""Returning our ordered objects to the view"""
"""Request = everything we receive from the user (in a form for example)"""
return render(request, 'lostitem/item_list.html', {'lostitems': lostitems, 'give_back_item_form' : give_back_item_form})
And here is the code for my template !
<form class="give-back-item-form" method="POST">
{% csrf_token %}
<input type="hidden" name="id" value="{{ lostitem.id }}">
<button type="submit" class="button btn btn-xs btn-success buttonItems">
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"> </span>
</button>
</form>
Thank you all for your answers it lead me to the right solution !
If all you want to do is post back the id of an associated ItemLost object so that you can invoke a method on it (e.g., giveBackItem()), there's no need to use a ModelForm at all. Just use a normal HTML <form>, and manually put the hidden field in it:
<form class="give-back-item-form" method="POST">
{% csrf_token %}
<button type="submit" value="Give Back">
<input type="hidden" name="id" value="{{lostitem.id}}">
</form>
So your complete template would become:
{% for lostitem in lostitems %}
<tr>
<td>{{lostitem.id}}</td>
<td>{{lostitem.description}}</td>
<td>
<form class="give-back-item-form" method="POST">
{% csrf_token %}
<button type="submit" class="button btn btn-xs btn-success buttonItems">
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
</button>
<input type="hidden" name="id" value="{{lostitem.id}}">
</form>
</td>
</tr>
{% endfor %}
Related
I am having a problem with Django forms. I am currently using the request.POST to validate the POST within views.
I want to send inputed-data(radio type) from my template with the same name.
In my template.py:
<form method="post" action="{% url 'app:AnsSubmission' %}">
{% csrf_token %}
{% for i in Exam %}
<div class="form-group col-xl-12">
<label>{{ i.question }}</label>
<div class="radio">
<label><input type="radio" class="mx-2" name="givenAns" array_column="{{ i.pk }} value="True" required>True</label>
</div>
<div class="radio">
<label><input type="radio" class="mx-2" name="givenAns" array_column="{{ i.pk }} value="False" required>False</label>
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
And willing to fetch these data in views.py like:
givenAns_list = request.POST.getlist('givenAns')
for i in givenAns_list:
this_givenAns = givenAns_list[i]
But the problem here is this radio type input field doesn't take value for the same name(not as a list I wish). If I select answer of 2nd question, the 1st one's selection is unselected.
Please suggest how can I fix this?
Search.py
{% block search %}
<form action="#" method="post">
<div class="container">
<br>
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" name="bankname" type="submit" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Name
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
{% for key , value in data_dict.items %}
<a class="dropdown-item" value=key name="name" href="{% url 'details' %}">{{ key}} </a>
{% endfor %}
</div>
</div>
</form>
{%endblock%}
the number of items in data_dict is not always same , so some times it has 2 or 3 or even 10 different names which leads to 10 items in the drop down.
I need to show details of the name clicked in the drop down in details .html
Views.py
def details(request ):
request.GET('name')
data_dict = request.session.get("data_dict")
context = {"data_dict" : data_dict}
return render(request , "details.html", context )
i want the value of the tab clicked in the drop-down in my view so i can display the details accordingly from my data_dict
you are on the right track. However, I believe there is some JavaScript code missing where you try to set the value of the Submit button?
You should know that when you submit a form, the only a Boolean value get submitted with the name of the button that has been clicked. So to this work correctly you will need to add multiple submit buttons with different names.
Following your example, something like this should work:
<form method="POST">
{% for key, value in data_dict.items %}
<button type="submit" name="{{ key }}">Save</button>
{% endfor %}
</form>
def my_view(request, **kwargs):
button_clicked = None
for key, value in data_dict.items():
if request.POST.get(key, False):
button_clicked = key, value
print(button_clicked)
I hope that helps a bit, let me know if you have any further questions.
Best -Joe
I have a read-only textbox which preloaded value from database which upon a button click sends it's value to a method present in backend to perform DELETE query of sql. The problem is occuring when I am click on the button the method is invoked but the request.method condition is not invoked. It is directly going to the end return statement of the method.
#app.route('/home/delete_reminder/<string:id_val>',methods=['GET','POST'])
#is_logged_in
def delete_reminder(id_val):
if request.method=='POST':
desc = request.form['description']
x = desc.split(',')
cur = mysql.connection.cursor()
cur.execute('DELETE FROM set_reminder WHERE DATE=%s,SUBJECT=%s,DESCRIPTION=%s',[x[0],x[1],x[2]])
cur.execute('DELETE FROM recur WHERE RECUR_NEXT=%s',[id_val])
flash('Reminder Deleted','danger')
mysql.connection.commit()
cur.close()
return redirect(url_for('search_reminder_to_delete'))
This is my backend code.
<form method="POST">
{% for data in value %}
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
Delete Reminder
{% endfor %}
</form>
This is the html part.
Your button isn't a button, it's a link. You aren't submitting your form.
If you want to fo that then you need to make you form tag:
<form method="POST" action="/home/delete_reminder/{{data.RECUR_NEXT}}">
and switch your button to be a real button that submits the form:
<div class="button">
<button type="submit" class="btn btn-warning">Send your message</button>
</div>
EDIT: Seeing that you want to have multiple possible routes for your form based on the loop.
You could try and use the formaction attribute, although it isn't going to be supported by every browser version.
<form method="POST">
{% for data in value %}
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
<div class="button">
<button formaction="/home/delete_reminder/{{data.RECUR_NEXT}}" class="btn btn-warning" type="submit" class="btn btn-warning">Delete Reminder</button>
</div>
{% endfor %}
However this will still result in your description field that is passed to the request having every single description from the whole form in a list or possibly just the last one as a single value (I can't quite remember the behaviour of multiple inputs with the same name), which I don't think is what you're expecting to happen.
It may just be easiest to create a separate form for each link in a loop to be honest:
{% for data in value %}
<form method="POST" action="/home/delete_reminder/{{data.RECUR_NEXT}}">
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
<div class="button">
<button class="btn btn-warning" type="submit" class="btn btn-warning">Delete Reminder</button>
</div>
</form>
{% endfor %}
my django template is not submitting data! i know it is very basic thing but there is something i cannot realize here! my Model is:
class project(models.Model):
Project_Name = models.CharField(max_length=50)
And my ModelForm is:
class create_project(forms.ModelForm):
class Meta:
model = project
fields = ['Project_Name']
views.py
def project_create_view(request):
form = create_project(request.POST or None)
msg = ''
if form.is_valid():
form.save()
msg = 'Data Submitted'
form = create_project()
return render(request, 'create_project.html', {'form':form, 'msg':msg})
And my template is:
<form action="" method="POST">
{% csrf_token %}
<table border="1">
<tr>
<td>
<div>
<label for="id_Project_Name">Project Name</label>
<input type="text" name="Project_Name" id="id_Project_Name">
</div>
</td>
</tr>
</table>
<input type="submit" value="Submit">
</form>
My context dict is 'form', i tried so many ways searched online but no luck, can anyone help?...
I haven't pasted all the project as the case is similar for the rest fields.
In your html,
<form method="POST" action="#keep it blank or add action as per your requirement" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<span> {{field.errors}} </span>
<div> {{field}} </div> #you can add label or placeholder as per your requirement
{% endfor %}
<input type="submit" value="Submit">
</form>
You have not added enctype in your html.
Note : You can modify your views.
i managed to solve it this way after taking support from one of my experienced friends:
<td>
<div>
<label for="{{form.Project_Name.name}}">Project Name</label>
<input type="text" name="Project_Name" id="{{form.Project_Name.name}}">
</div>
</td>
I want the user to be able to add or remove fields in the website, I am using flask and fields.FieldList
I know how to do that directly with javascript only clone the field section of the DOM and rename the attributes like name, id etc... is there an easy way to do it with flask/ flask forms? I want to achieve something like in the picture (doesn't have to be in that layout, I really don't care the layout since I can move it later on)
and then been able to pass it to the back end and been recognize by the flask forms.
thanks in advance, I appreciate it =)
This are my forms:
class AddressForm(FlaskForm):
addr = fields.StringField("address")
class MainForm(FlaskForm):
addressees = fields.FieldList(fields.FormField(AddressForm), min_entries=1, validators=[DataRequired()])
This is my view:
def addressees_create():
if request.method == 'POST':
form = MainForm()
if form.validate():
print("is validate")
else:
print("was not validate")
if form.validate_on_submit():
print("the form was validated on submit")
else:
print("was not validated on submit")
print(form.data)
addressees = form.data["addressees"]
for address in addressees:
print("\t"+str(address))
return render_template("my/template.html",form=form)
else:
form = MainForm()
return render_template("my/template.html", form=form)
This is the template:
<div>
{% for item in form.addressees %}
{{ item.hidden_tag() }}
{{ item.addr }}
{% endfor %}
<div style="color: red;">
{% for error in form.addressees.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
</div>
I also had this problem. Here is my solution
class CreatePollForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
options = FieldList(StringField())
submit = SubmitField('Create')
<ul id="options">
<li>
<label for="options-0">Options-0</label>
<input id="options-0" name="options-0" type="text" value="">
</li>
<li>
<label for="options-1">
Options-1
</label>
<input id="options-1" name="options-1" type="text" value="">
</li>
<li>
<label for="options-2">Options-2</label>
<input id="options-2" name="options-2" type="text" value="">
</li>
<li>
<label for="options-3">Options-3</label>
<input id="options-3" name="options-3" type="text" value="">
</li>
<li>
<label for="options-4">Options-4</label>
<input id="options-4" name="options-4" type="text" value="">
</li>
</ul>
You can refer to this data like this:
form = CreatePollForm()
print(form.options.data)