Variable 'name' in a django template form - forms

I have the following template, which has both an "add" and "delete" button:
<tr>
<td>Position</td>
<td>{{ form.position }}<input type="submit" value="add" , name='add'/></td>
</tr>
<tr>
<td> </td>
<td>
{% for position in positions %}
{{ position}}<input type="submit" value="Delete", name="delete-position.{{ position }}"/>
{% endfor %}
</td>
</tr>
How would I construct the views.py function to find the name value of the Delete submit button? I currently have:
try:
request.POST['add']
positions.append(request.POST['position'])
return render_to_response('registration/getting_started_info1.html', {'form': form, 'positions': positions}, context_instance = RequestContext(request))
except:
if 'delete-position' in request.POST:
positions.remove(### how to get name of Delete submit? ###)
return render_to_response('registration/getting_started_info1.html', {'form': form, 'positions': positions}, context_instance = RequestContext(request))
Also, is there a better way to construct the view/template so I can use an if...else instead of a try...except ?

First, you should probably do this:
if request.method == "POST":
if 'add' in request.POST.keys():
positions.append(...)
return render_to_response(...)
else:
for k, v in request.POST.items():
if k.startswith('delete-position'):
positions.remove(k)
return render_to_response(...)
That should help with what you're asking... however, I'm not sure if it's the easiest method to do what you're trying to do.

Save the positions in the session.

Your try-catch is kind of weird. You should probably be submitting delete requests to a different view.
But as to how you can get the delete-position vars, it's easy:
def delete(request):
if request.method == "POST":
for key in request.POST.keys():
if key.startswith('delete-position'):
positions.remove(request.POST[key])

Related

How to update multiple objects by one html request?

I have a problem and can't find a decision.
I need to update a value for several objects by one form. If I did it one by one, without submit button it works fine. But I want to do it by click to one button.
My HTML form:
<form method="post" action="{% url 'installmentreport-update' %}">
{% for installmentreport in installment.installmentreport_set.all %}
<tr>
<td class="align-middle" style="text-align:center">{{installmentreport.title}}</td>
<td class="align-middle" style="text-align:center">
{% csrf_token %}
<input type="number" name='spent' value={{installmentreport.spent}} placeholder={{installmentreport.spent}} size="8">
<input type="hidden" name='id' value={{installment.id}}></td>
<input type="hidden" name='pk' value={{installmentreport.id}}>
</tr>
{% endfor %}
<td></td>
<td class="align-middle" style="text-align:center"><input type="submit" class="btn btn-warning" name="submit" value="Update"></form>
Views:
class InstallmentReportUpdate(LoginRequiredMixin,PermissionRequiredMixin,UpdateView):
model = InstallmentReport
permission_required = 'catalog.can_change_program'
fields = ['spent']
def get_object(self):
pks = self.request.POST.getlist('pk')
for pk in pks:
return InstallmentReport.objects.get(pk=pk)
def form_valid(self, form):
if self.request.method == 'POST':
spents = self.request.POST.getlist('spent')
if form.is_valid():
for spent in spents:
instance = form.save(commit=False)
form.instance.spent = spent
instance.save()
return super().form_valid(form)
def get_success_url(self):
id = self.request.POST.get('id')
return reverse('installment-detail-owner', args=[str(id)])
I use Python3.7 and Django2.2
I did it!
Views:
def get_object(self):
pks=self.request.POST.getlist('pk')
spents = self.request.POST.getlist('spent')
for pk, spent in zip(pks,spents):
print(pk)
print(spent)
InstallmentReport.objects.filter(pk=pk).update(spent=spent)
return InstallmentReport.objects.get(pk=pk)

I can not recover the values ​of my checkbox in my controller

I'm working on a symfony project, I created a checkbox in twig, I want to get checked values ​​in my Controller but I still get a null, I do not know what the problem is please help:
My Action:
public function sendSmsAction(Request $request) {
if ($request->isMethod('get')) {
$ids = $request->query->get('id');
var_dump($ids);
die();
}
return $this->render('CeUtilisateurBundle:Utilisateur:sms.html.twig')
}
My Form in twig:
<form
method="GET"
action="{{path('ce_utilisateur_send_sms') }}"
id="lbad_form_sms"
name="users"
>
{% if listUsers is not empty %}
{% for usr in listUsers %}
<input
id="userchecked"
name="{{usr.id}}"
type="checkbox"
value="{{ usr.telephone }}"
/>
<span>{{ usr.username }}</span>
</form>
Aside from other issues in your example, in order to get those values you need to change the HTML part that displays checkboxes and give them different IDs, proper values and the same name:
<input id="telephone{{ usr.id }}" name="telephone[]" type="checkbox" value="{{ usr.telephone }}"/>
Notice that the name property is the same for every checkbox and has [] at the end - this allows to pass multiple values for one property.
Next to that I would suggest to use a POST request to submit the form, instead of the GET you are using. If you do so, you can get the selected phone numbers in the controller like that:
$telephones = $request->request->get('telephone');
If you want to submit the form with a GET request, then use query instead of the request:
$telephones = $request->query->get('telephone');
First, you're missing closing tags in twig for your if and for, but I assume they just got lost during copying.
Second, you give all your input elements the same id "userchecked". Each HTML element should have a unique ID, e.g. by appending your user ID.
Something similar happens with the name attribute. If you give multiple form elements the same name, only the last one will be submitted.
So your form should look something like this:
<form
method="GET"
action="{{path('ce_utilisateur_send_sms') }}"
id="lbad_form_sms"
name="users"
>
{% if listUsers is not empty %}
{% for usr in listUsers %}
<input
id="{{"userchecked_" ~ usr.id}}"
name="{{"checked_" ~ usr.id}}"
type="checkbox"
value="{{ usr.telephone }}"
/>
<span>{{ usr.username }}</span>
{% endfor %}
{% endif %}
<input type="submit" value="Envoyer un sms!"/>
</form>
To fix your controller, you have to get the input by the name field. Since it is dynamically created, it's easiest to just get all parameters and loop over them.
public function sendSmsAction(Request $request) {
if ($request->isMethod('get')) {
$parameters = $request->query->all();
foreach ($parameters as $name => $value) {
var_dump("$name: $value");
}
die();
}
return $this->render('CeUtilisateurBundle:Utilisateur:sms.html.twig')
}
Note that there will be no submitted parameter for an empty checkbox.

Bottle.py - split string array (CSV)

I have a small web demo pulling data from into a CSV file, which I want to display on a web page. I plan to use Bottle.py, but I cannot split the string into an array. There will be multiple lines in the CSV file, which I will read in split and then create a table.
from bottle import run, debug, template, get, redirect, request, response, static_file, route, os, sys
LOG_FILENAME = "data.csv"
#route('/hello/<name>')
def index(name):
readfiledata()
print(reader)
array = reader.split(',')
return template('<b>Hello {{name}}</b>!', name=reader)
Maybe something like this (using csv module from the Standard Library):
import csv
from bottle import route, jinja2_template
#route('/csv')
def show_csv():
with open('data.csv') as fo:
csv_reader = csv.reader(fo)
table = [row for row in csv_reader]
return jinja2_template('templ.html', table=table)
templ.html (I'm using Jinja2 templates which I prefer over Bottle's built-in templating language):
<table style="width:100%">
<tr>
{# Table header #}
<th>Foo</th>
<th>Bar</th>
<th>Baz</th>
</tr>
{% for row in table %}
<tr>
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>

LIFTWEB: How to render a simple table clicking a button?

I would like to display an HTML table clicking on a button.
This is what I've tried so far:
My SCALA code:
object Snippet {
def render = {
def showTable() = {
val table = <table border="1">
<caption>My Table</caption>
<thead>
<tr>
<td>Entry</td>
<td>Value1</td>
<td>Value2</td>
</tr>
</thead>
<tbody>
<tr>
<td>PREV</td>
<td>1</td>
<td>10</td>
</tr>
<tr>
<td>CURR</td>
<td>2</td>
<td>20</td>
</tr>
<tr>
<td>NEXT</td>
<td>3</td>
<td>30</td>
</tr>
</tbody>
</table>
SetHtml("table_div",table)
}
"#getTable" #> SHtml.button("Get Table", () => null, "onclick" -> "$('#msg_div').html('<span>Getting table...</span>')") &
"name=proc" #> SHtml.hidden(showTable)
}
}
And my HTML:
<div class="lift:Snippet.render">
<form>
<input type="hidden" name="proc"/>
<button id="getTable" value="Get Table" class="btn btn-inverse">Get Table</button>
</form>
<div id="msg_div"></div>
<div id="table_div"></div>
</div>
Nothing is displayed clicking the button.. Do you see what is the problem?
Or someone could tell me another way to do that?
I am not sure what you are looking to accomplish with the hidden input. Why not just do something like:
"#getTable" #> SHtml.ajaxButton("Get Table", showTable)
If you are looking to display a waiting indicator, Lift has a mechanism for setting the ajax loading animation. In Boot.scala:
//Show the spinny image when an Ajax call starts
LiftRules.ajaxStart =
Full(() => LiftRules.jsArtifacts.show("ajax-loader").cmd)
// Make the spinny image go away when it ends
LiftRules.ajaxEnd =
Full(() => LiftRules.jsArtifacts.hide("ajax-loader").cmd)
You can use any JsCmd instead to call your own function. I'd probably opt for that.
Totally agree with jcern. A slightly different way could also be:
"#getTable [onclick]" #> SHtml.ajaxInvoke(showTable)
(this way you won't override the original button name)
Also note that you don't even need to use the <form> tag -- you can delete it.

Why is FilteringSelect in declarative dijit form causing invalid submit?

Help me understand this.
Isn't dijit.form.FilteringSelect (extended from ValidationTextBox) supposed to have property required = false by default?
Why is it that simply including a FilteringSelect in a declarative form like so below automatically results in dijit.form.Form.isValid() == false?
Even manually setting the filteringselect's required prop to false results in an invalid form submit. I feel like there's something I'm missing here.
I'm Using dojo toolkit version 1.6.1.
<!-- form.html -->
<form id="form" dojoType="dijit.form.Form">
<table>
<tr>
<td id="friend">
<select name="friend" id="friend-input" dojotype="dijit.form.FilteringSelect"></select>
</td>
</tr>
<tr>
<td>
<input type="submit" id="submit-input" value="Submit" label="Submit" dojotype="dijit.form.Button">
</td>
</tr>
</table>
</form>
/* form.js */
dojo.require("dijit.form.Button");
dojo.require("dijit.form.FilteringSelect");
dojo.require("dijit.form.Form");
dojo.ready(function() {
var form = dijit.byId("form");
var friendInput = dijit.byId("friend-input");
friendInput.required = false;
dojo.connect(form, "onSubmit", function(event) {
event.preventDefault();
if (form.isValid()) {
alert("Ready to submit data: " + dojo.toJson(form.get("value")));
} else {
alert("Form is not valid.");
}
});
});
Like Frode mentioned, we need to set the required to false.
But, lots of fields might be used. Not a good idea to set 'required' for each, in the dojo.ready section.
<select name="friend" id="friend-input"
dojotype="dijit.form.FilteringSelect" required="false"></select>
The better way is to mention it as attribute in the html itself. Let me give an example why it is better.
If the field is included in a tab, and if the tab is refreshed on certain actions, the html will be arsed again. So, in that scenario, the required will be true again for that field. So, therefore, provide it in the html declaration of the widget itself to avoid these scenarios.