How to update multiple objects by one html request? - python-3.7

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)

Related

Using Django, how do I set a ModelForm field value dynamically in the template?

I'm trying to utilize a checkbox field to create a model instance for a user selected favorite. The last piece I need in order for this to work properly is to set the default value in one of the form fields equal to the value in a loop. Would I do this with the initialize argument, in the views.py file, in the form itself, or in the template? Here is the associated code:
Apologies for the HTML class tags
models.py
class ReportDirectory(models.Model):
report_name = models.CharField(max_length=300, unique=True, blank=False)
report_desc = models.TextField()
report_type = models.CharField(max_length=300)
report_loc = models.TextField()
slug = models.SlugField(unique=True, max_length=300)
last_update = models.DateTimeField(null=True)
main_tags = models.CharField(max_length=300)
# Renames the item in the admin folder
def __str__(self):
return self.report_name
class Favorite(models.Model):
directory_user = models.ForeignKey(User, on_delete=models.CASCADE)
user_report = models.ForeignKey(ReportDirectory, on_delete=models.CASCADE)
favorited = models.BooleanField(default=False)
def __str__(self):
return str(self.directory_user)+" - "+str(self.user_report)
forms.py
from django import forms
from .models import Favorite
class FavoriteForm(forms.ModelForm):
class Meta:
model = Favorite
fields = '__all__'
widgets = {
'favorited': forms.CheckboxInput(attrs={
'type':'checkbox',
'name':'checkbox',
'onchange':'submit()'
})
}
views.py
from django.shortcuts import render,redirect
from django.views import generic
from .models import ReportDirectory, Favorite
from django.contrib.auth.models import User
from .forms import FavoriteForm
def report_directory(request):
favorite = Favorite.objects.filter(directory_user=request.user.id, favorited=True)
reports = ReportDirectory.objects.exclude(favorite__directory_user=request.user.id, favorite__favorited=True)
favform = FavoriteForm(initial={'directory_user':request.user},)
context = {
'reports':reports,
'favorite':favorite,
'favform':favform
}
if request.method == 'POST':
form = FavoriteForm(request.POST)
if form.is_valid():
form.save()
return redirect('/report_directory')
return render(request, 'counter/report_directory.html',context)
html
<thead>
<tr>
<th class="gls-table-expand">Favorite</th>
<th onclick="sortTable(1)" class="gls-table-expand">Report Type</th>
<th onclick="sortTable(2)" class="gls-table-expand">Report Name</th>
<th class="gls-table-expand">Report Description</th>
<th onclick="sortTable(3)" class="gls-table-expand">Last Updated</th>
<th class="gls-table-expand">Main Tags</th>
<th onclick="sortTable(4)" class="gls-table-expand">View Count</th>
</tr>
</thead>
<tbody id="myTable">
{% for r in reports.all %}
<tr report-name="{{ r.report_name }}">
<td>
<form method="POST">
{% csrf_token %}
{{ favform.favorited }}
</form>
</td>
<td><span><img img width="20" height="20"
{% if r.report_type == 'Tableau' %}
src=" {% static 'images/tableau_icon.svg' %}"
{% elif r.report_type == 'Excel' %}
src=" {% static 'images/excel_icon.svg' %}"
{% elif r.report_type == 'Box' %}
src=" {% static 'images/excel_icon.svg' %}"
{% elif r.report_type == 'Internal Report' %}
src=" {% static 'images/www_icon.svg' %}"
{% endif %}
></span> {{ r.report_type }}</td>
<td>{{ r.report_name }}</td>
<td>{{ r.summary }}</td>
<td><p class="gls-text-meta gls-margin-remove-top">{{ r.last_update_format }}</p></td>
<td>{{ r.main_tags }}</td>
<td>{% get_hit_count for r %}</td>
</tr>
{% endfor %}
</tbody>
I found a solution to dynamically iterate through the template and complete the ForeignKey (selection) field. I needed to set the for iterator equal to the selection option
<form method="POST" id="{{ r.report_name }}">
{% csrf_token %}
<p hidden>
{{ favform.directory_user }}
<select name="user_report" required="" id="id_user_report">
<option value="{{ r.id }}" selected></option>
</select>
</p>
{{ favform.favorited }}
</form>
I feel like I'm working against Django forms, however, and not with the infrastructure...

Check only one checkbox and uncheck previous checked checkbox

I wanted that when I change my selection in my checkbox the only selected checkbox will be selected and the previous selected checkbox will be uncheck.
My code is working but i really wanted to select only one checkbox.
In my view.
<center><table></center>
<tr>
<th><center>
List of Names</center></th>
<th colspan="3">
Actions
</th></tr>
<tr ng-repeat="role in roles">
<td>
<label>
<ion-checkbox ng-model="isChecked" ng-
change="format(isChecked,role,$index)"
ng-init="isChecked=false"><div class="wew">
{{role}}
</div></ion-checkbox>
</label>
</td>
<td>
<button ng-hide="!isChecked" ng-click="present()">P </button> </td>
<td>
<button ng-hide="!isChecked" ng-click="late()">L</button></td>
<td><button ng-hide="!isChecked" ng-click="absentss()">A</button></td>
<td><button ng-hide="!isChecked" ng-click="delete()">D</button></td>
</tr> </table>
And I think in my controller is the part where i need to change my codes to achieved the correct result.
$scope.isChecked = false;
$scope.selected = [];
$scope.format = function (isChecked, role, index) {
if (isChecked==true) {
$scope.selected.push(role);
}
else {
var _index = $scope.selected.indexOf(role);
$scope.selected.splice(_index, 1);
}
var students = $scope.selected;
console.log(students);
for( var s=0; s<students.length; s++) {
$scope.stud = [
students[s]
]
};
Thank you in advanced! I hope that someone can help in this matter.
Checkboxes are for multiple selections within a group.
Use radio buttons instead.
Example With AngularJs
This is way you can also implement.
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
angular.module('app', []).controller('appc', ['$scope',
function($scope) {
$scope.selected = 'other'; //default selection
}
]);
</script>
</head>
<body ng-app="app" ng-controller="appc">
<label>SELECTED: {{selected}}</label>
<div>
<input type="checkbox" ng-checked="selected=='male'" ng-true-value="'male'" ng-model="selected">Male
<br>
<input type="checkbox" ng-checked="selected=='female'" ng-true-value="'female'" ng-model="selected">Female
<br>
<input type="checkbox" ng-checked="selected=='other'" ng-true-value="'other'" ng-model="selected">Other
</div>
</body>
</html>

web2py: multiple forms on one page

I am trying to make a form which shows all products from a group in a list. They can be given a quantity and added to a quote. Which is then stored in the database.
None of the automagical form options are working for me. So I've made each row showing information for a given product with the Quantity box and an add item button it's own form. But the loop which makes each form is doing something strange.
Controller:
products = db(db.product.group_id == productgroupnumber).select()
forms=[]
for product in products:
form = FORM(TABLE(TR(TD(product.productname),
TD((product.purchasecost or 0)),
TD((product.monthlycost or 0)),
TD(INPUT(_type='number', _name='quantity')),
TD(INPUT(_type='submit', _value=T('Add to Offer')))
)
)
)
forms.append(form)
session.quotedproducts = []
if form.accepts(request, session, keepvalues = True):
product = db(db.product.id == product_id).select().first()
offeritem = [product_id, request.vars.quantity, product.purchasecost, product.monthlycost]
session.quotedproducts.append(offeritem)
response.flash = T("Item added to offer")`
For 2 rows. The View has the below 2 forms, with only one hidden div with the formkey and formname. So I can't name the forms in order to process them properly:
<form action="#" enctype="multipart/form-data" method="post">
<table>
<tr>
<td>Block of 10 Phone Numbers</td>
<td>19.0</td>
<td>0</td>
<td><input name="quantity" type="number" /></td>
<td><input type="submit" value="Add to Offer" /></td>
</tr>
</table>
</form>
<form action="#" enctype="multipart/form-data" method="post">
<table>
<tr>
<td>100 Block of Phone Numbers</td>
<td>149.0</td>
<td>0</td>
<td><input name="quantity" type="number" /></td>
<td><input type="submit" value="Add to Offer" /></td>
</tr>
</table>
<!--Why is there only one of these??-->
<div style="display:none;">
<input name="_formkey" type="hidden" value="b99bea37-f107-47f0-9b1b-9033c15e1193" />
<input name="_formname" type="hidden" value="default" />
</div>
</form>
How do I give the forms individual names (preferably product.id)?
I tried adding the formname argument:
form.accepts(request, session, formname=product.id)
But this only names one form and the other is still named 'Default'.
In your code, you create multiple forms in the for loop, but after exiting the loop, you call form.accepts(). At that point, the value of form is the last form created in the loop, so only that form is processed.
Note, when a form is initially created, the form.accepts (or the preferred form.process) method adds the _formname and _formkey hidden fields to the form (these are used for CSRF protection). When that same method is called after form submission, it additionally handles form validation. So, given your workflow, you must process all the forms both at creation and submission. Maybe something like this:
products = db(db.product.group_id == productgroupnumber).select()
forms = []
for product in products:
quantity_name = 'quantity_%s' % product.id
form = FORM(TABLE(TR(TD(product.productname),
TD((product.purchasecost or 0)),
TD((product.monthlycost or 0)),
TD(INPUT(_type='number', _name=quantity_name)),
TD(INPUT(_type='submit', _value=T('Add to Offer')))
)
)
)
if form.process(formname=product.id, keepvalues=True).accepted:
offeritem = [product.id, form.vars[quantity_name],
product.purchasecost, product.monthlycost]
session.quotedproducts.append(offeritem)
response.flash = T("Item added to offer")
forms.append(form)

Unable to return to the desired URL or view of the JSP

<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/jquery.validate.min.js"></script>
<script>
function setHiddenVal(){
var goAhead = true;
var myVal="I am hidden value";
document.getElementById("secretValue").value = myVal;
if (goAhead == true) {
document.forms["register-form"].submit();
}
}
</script>
</head>
<body>
<!--Main Container Starts here-->
<div class="main_container">
<div class="header">
<div class="right_panel">
<h2 align="center"><u>User Master</u></h2>
<div class="top-form">
<div>
**<form:form action="/usermaster" modelAttribute="CustomerForm" id="register-form" method="POST">**
<table cellspacing="0" cellpadding="0" border="" class="form1">
<tr>
<td class="label">Name:</td>
<td>
<form:input path="firstname"/>
</td>
</tr>
<tr>
<td class="label">Password:</td>
<td>
<form:input path="password"/>
</td>
</tr>
</tbody>
</table>
<div>
<table>
<tr>
<td> </td>
<td>
<input type="button" class="btn blue px16" value="Search" />
<input type="button" name="submit" id="btnsubmit" value="Submit" onclick="setHiddenVal();"/>
<input type="button" class="btn blue px16" value="Clear" />
<input type="button" class="btn blue px16" value="Change Password" />
<input type="button" class="btn blue px16" value="Manage User Notification Profile" />
</td>
</tr>
</table>
</div>
</form:form>
</div>
</div>
<div class="clear"></div>
</div>
</div>
</div>
</body>
</html>
so above one is my code for jsp and below is the code of controller
#RequestMapping(value={"/usermaster" }, method = RequestMethod.POST)
public final String addUserMaster(#ModelAttribute("CustomerForm") CustomerForm pricing, Map<String, Object> map,
Model model, HttpServletRequest request) {
System.out.println("the first name is "+pricing.getFirstname());
System.out.println("the password is "+pricing.getPassword());
return "usermaster";
}
#RequestMapping(value={"/showusermaster" }, method = RequestMethod.GET)
public String showPage(ModelMap model){
model.addAttribute("CustomerForm", new CustomerForm());
return "usermaster";
}
But my page gets open up using a popup with the url:
C:\Users\ganganshu.s\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5\YW6383E8\usermaster
so it should open like
http://localhost:8080/enbee/usermaster
Could you please tell me what should I put in the form action.. as I think some mistake is there in the form action does in spring MVC we put the action like in the case I mentioned above.
Spring confg file is given below :
<mvc:interceptors>
<bean class="com.enbee.admin.interceptor.AuthenticationInterceptor" />
<!-- Declare a view resolver-->
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" p:order="1" />
and the jsp name is usermaster.jsp
and in the sidemenu.jsp I have changed to this :
<li>User Master</li>
Change the method parameter of RequestMapping annotation to RequestMethod.POST:
#RequestMapping(value="/usermaster", method = RequestMethod.POST)
public final String addUserMaster(...){
...
}
so that when you submit your form to the URL /usermaster using method="POST" this method will get executed.
You also need to have a method (mapped to an URL) that will show this page to the user. You can use a method as below for this:
#RequestMapping(value = "/showusermaster", method = RequestMethod.GET)
public String showPage(ModelMap model){
model.addAttribute("CustomerForm", new CustomerForm());
return "usermaster";
}
With this method in place, the URL
http://localhost:8080/enbee/showusermaster
will show the usermaster.jsp page to the user. Now when you submit this form, the above addUserMaster method will be invoked.
You don't have to create new jsp file. The url /showusermaster will return the usermaster.jsp to the user, where the user can add form values and submit the form:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
...
<c:url var="submitUrl" value="/usermaster">
<form:form id="form" action="${submitUrl}" modelAttribute="CustomerForm" method="POST">
Now when the user clicks on the submit button, this form will be submitted to /usermaster URL and will be handled by addUserMaster method.
Try to specify the content type returned by your controller method, adding produces = "text/html" param to your #RequestMapping annotation.

Variable 'name' in a django template form

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])