Passing objects from template to view using Django - javascript

I am trying to figure out the architecture for the following app:
The user is presented with a table.
Each table cell has several fields the user will be filling in.
There is a general submit button: when clicked on all the input data (along with some calculated data per cell based on the input values) should pass to a Django view.
Here are the following questions:
Can I organize the data structure as a set of objects in a way that each object will correspond to a table cell, whereas the Master object, that will eventually be passed to the Django view, will be a set of those objects?
If so, how to pass the Master object from a template to view using Django?
Thanks.

1. Is it possible to create an object in HTML/JS whose members will contain data from the fields?
You can't create an object in html/JS, but you can build your code up to display or request data from an object in Django.
Say for example, you have a model Foo
class Foo(models.Model):
GENDER = (
('F', 'Female'),
('M', 'Male'),
)
name = models.CharField(max_length=150)
gender = models.CharField(max_length=1, choices=GENDER)
And your template looks like this
<body>
<form action="?" method="post">
<table>
<tr>
<td>Name</td>
<td><input type="text" name="name" maxlength="150" /></td>
</tr>
<tr>
<td>Gender</td>
<td>
<select name="gender">
<option value="F">Female</option>
<option value="M">Male</option>
</select>
</td>
</tr>
</table>
<input type="submit">
</form>
</body>
If you fill in the fields and click submit, then you can handle the data in your view.
def add_foo(request):
if request.method == "POST": # Check if the form is submitted
foo = Foo() # instantiate a new object Foo, don't forget you need to import it first
foo.name = request.POST['name']
foo.gender = request.POST['gender']
foo.save() # You need to save the object, for it to be stored in the database
#Now you can redirect to another page
return HttpResponseRedirect('/success/')
else: #The form wasn't submitted, show the template above
return render(request, 'path/to/template.html')
That last bit also answered question 2, i think. Hope this helps.

Related

Easiest way to update mysql table via html form

I need to update values in a mysql table. This has to be checked by hand and I cannot give the person permission to phpmyadmin.
So I want to create a html table which displays the mysql table. It has more columns but for simplicity let's say we have:
name age gender
jake 23 M
jenny 45 M
bob 12 M
Now I want to display this on an html page in a table or something so this aligns nicely and we can go through the data and i.e. change the gender of Jenny from M to F.
I either want one of 2 things:
1) whenever a value in a row is changed make an Ajax request to the server with all variables of that row so a mysql update can be done.
2) the entire table will be put in a form and at the bottom of the page is a submit button which sends all the data in a way that it can be put in a dictionary or dataframe in Python to loop over all the rows so the mysql table can be updated. (I asked this here but didn't receive any answers)
I now tried this but it doesn't call the function:
In the header of html:
$('.formclass').change(function() {
console.log("testing");
});
I then do a request to the server to fill the table the python code is:
table1 = {mysql query data}
data = """
<table border = 5 bordercolor = red align = center>
"""
for i,row in table1.iterrows():
sstr = """
<tr>
<form action="/test.py" class='formclass'>
<td><input type="text" name="id" value="{0}" readonly/></td>
<td>name: {1} </td>
<td colspan = 4><input type="radio" name="gender" value="M" checked>Male<input type="radio" name="gender" value="F">Female</td>
</form>
</tr>
""".format(row['id'],row['name'])
data = data + sstr
data = data + """</table>"""
print(data)
However it doesn't even log in the console. And then I also need the data from the row still.
What I see in the html is that the form elements are put in another place so the table cells are not in the form anymore.
You can use Views as a best practice for SELECT.

javascript not displaying in jsp page

I wrote a code for retrieving data from database table and displaying it. The entire table is passed as arraylist through servlet to jsp page. Inside the jsp.. first only name is displayed in dropdown box. The objective was to choose a name from dropdown , and rest of the data corresponding to the name is displayed after the name is chosen. Arraylist has been passed correctly. Dropdown is working fine.
but javascript code to display the rest is not working. please help.code below iv shown only for one field. ie,for id.
output page with dropdown
<body>
<form action="Servletname" method="post" name="searchdatabase">
<%int i=0;
ArrayList<Cust> newlist=(ArrayList<Cust>) request.getAttribute("CusList");
if(newlist.size()>0){
%>
<table>
<tr>
<td> name :</td>
<td>
<select id="selectUsers" name="users" onChange='Choice();'>
<option> </option>
<%for(Cust c:newlist){ %>
<option value="<%=c.getCustId()%>"> <%=c.getName() %></option>
<%}%>
</select>
</td></tr>
<tr>
<td> id :</td>
<td>
<input type="text" id="ids" name="id" >
</td></tr>
</table>
</form>
<script type="text/javascript">
function Choice() {
//x = document.getElementById("users");
y = document.getElementById("selectUsers");
x=y.selectedIndex;
Cust c1= newlist.get(y.selectedIndex);
document.getElementById("ids").value =c.getCustId();
}
</script>
<%} %>
</body>
There are a few problems with your code.
First of all, scriptlets are deprecated and should be avoided. Use JSTL instead.
Secondly, your JavaScript code has no visibility of any of the variables used in your Java code. The Java is executed on the server, then some text (the HTML response) is sent to the browser. If it contains JavaScript, the browser runs the JavaScript.
I've rewritten what you're trying to achieve using JSTL instead of scriptlets for flow control and changing the JavaScript to get what you seem to be attempting:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<body>
<form action="Servletname" method="post" name="searchdatabase">
<c:if test="${not empty CusList}">
<table>
<tr>
<td> name :</td>
<td>
<select id="selectUsers" name="users" onChange='Choice();'>
<option> </option>
<c:forEach items="${CusList}" var="c">
<option value="${c.custId}"> <c:out value="${c.name}" /></option>
</c:forEach>
</select>
</td></tr>
<tr>
<td> id :</td>
<td>
<input type="text" id="ids" name="id" value="${CusList[0].custId}" >
</td></tr>
</table>
<!-- Note that I've moved the closing form tag and put it outside of this c:if block
because putting it here means it will only be output if your List is not empty -->
<script type="text/javascript">
function Choice() {
var y = document.getElementById("selectUsers");
var x = y.selectedIndex;
document.getElementById("ids").value = y.children[x].value;
}
</script>
</c:if>
</form><!-- outside of c:if because the opening tag is also outside of c:if -->
</body>
Edit:
I've just reread the question and realised that I haven't addressed your additional need of populating other inputs with other attributes of the customer.
As I said above, JavaScript has no visibility of data which is on the server, including your List of Customer objects. There are a few options available to you, but these are the two I would recommend:
Use HTML5 Data Attributes
HTML5 introduced data-* attributes for elements which can be accessed via your scripts. For example, you could do something like this:
<c:forEach items="${CusList}" var="c">
<option
value="${c.custId}"
data-surname="<c:out value="${c.surname}" />"
data-tel="<c:out value="${c.tel}" />"><!-- etc -->
<c:out value="${c.name}" />
</option>
</c:forEach>
Then in the JavaScript:
function Choice() {
var y = document.getElementById("selectUsers");
var x = y.selectedIndex;
var opt = y.children[x];
document.getElementById("ids").value = opt.value;
document.getElementById("surname").value = opt.dataset.surname;
document.getElementById("tel").value = opt.dataset.tel;
// etc
}
The downside of this approach is that if you have a large list with a high number of attributes you want to make available, that's a lot of text in the response.
Use AJAX
You could make an AJAX call in response to the select change and have the server return the customer data encoded in JSON format. The JavaScript would then decode the JSON and populate the elements with the correct values.
You'd need to research how to do this (there are plenty of tutorials available) but the steps in response to your select changing would be:
Disable the select box to prevent another change before you get the AJAX response from the server
Show some sort of throbber to indicate to the user that the data is being loaded
Make an AJAX request indicating the ID of the selected customer
The server responds with a JSON-encoded version of the corresponding customer object.
Update the inputs using the JSON data.
Hide the throbber and re-enable the select element.
The downside of this approach is that you'll need to learn how to properly use AJAX, including adding code to deal with errors (e.g., if the user loses network connectivity and you get no response from server to your AJAX request, you need to show an error message and have some sort of "retry" mechanism).

Django formset equivalent in angular.js

Django has formsets, where multiple forms can be used in one big form. So let's say one can add in a e.g. library formset mulitple books (providing the author and title) using repetitions of the same book form.
How to achieve the same functionality with Angular.js and Django Rest Framework? I'm new to Angular.js and Django Rest Framework and need some guidance how to be able to dynamically add more forms(e.g. for a book) for a given model in one big form (e.g. my library) and save them in Django Backend.
You can achieve this in 2 steps:
On Frontend
Create a <form> on your page that will structure the data entered by the user as you need. Inside that <form> element, you'll need to use the ngForm for multiple forms' validation to behave correctly (here is a nice explanation of how ngForm works). A hypothetical code snippet would look like:
<form name="libraryForm">
<div ng-repeat="book in vm.newBooksToAdd">
<!-- ngForm directive allows to create forms within the parent form -->
<ng-form name="bookForm">
<div>
<label>Book title</label>
<input ng-model="book.title" type="text" name="title" required>
</div>
<div>
<label>Author</label>
<input ng-model="book.author" type="text" name="author" required>
</div>
</ng-form>
</div>
</form>
In your controller, you can initialize the list of books to add as vm.newBooksToAdd = []; and whenever you want to add a new form to your list of forms for new books, just vm.newBooksToAdd.push({}) an empty object. Thus, you will send to the backend an array of objects representing books you want to create.
On Backend
Now here you'll need to overwrite the .create() method of your view to allow creating many instances at once, because by default it expects a single object. Your view might look like this:
class LibraryViewSet(views.ModelViewSet):
...
def create(self, request):
serializer = self.get_serializer(data=request.data, many=True) # notice the `many` keywork argument here
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
return Response(serializer.data, status=status.HTTP_201_CREATED)
Note: If you would like to allow both a single instance creation and creation in bulk, you'll need to adjust your .create() method to check for the data type of request.data.
Note 2: There is a django-rest-framework-bulk library that achieves what you want on the backend, but I didn't try it, so cannot say anything bad or good about it.
Good luck!

Get javascript calulations to post as form data and display in php page

I am somewhat familiar with JavaScript and php and very familiar with HTML but have limited experience in getting them to work together. I have looked at many examples and am either not understanding or other posts do not specifically address my situation. I am trying to accomplish two things at the time of form submission. One is to retrieve the information from a div populated by innerHTML to post with the form and the other is to generate a unique number for the transaction at form posting and then display.
I have an HTML form that displays a generated list, each of which has a check box beside it. When a check box is selected I am using onclick="calTotal()" to calculate and display the total of all boxes checked. Code listed below.
The display script works perfectly and displays a value such as Total $125.00. What I need to do is post that total value when I post the form. The only value being passed at this time is the last check box value. Should that total be assigned within the JavaScript or should it be assigned within an input field?
The second part of my question is with the value of my algorithm that creates a unique transaction number. I want to generate that number upon submission of the form but then need to have it display on the php page. I have tested my algorithm separately and know it works correctly when I hard code the values in. I need to take values from the form and use them to calculate the transaction number. Once calculated it needs to be passed to the php page. Again I am not completely sure where to assign the value so that it passes to the next page.
Anything that will get me pointed in the right direction is appreciated.
<script type="text/javascript">
function calTotal() {
var ch, i=0;
var total=0;
while(ch=document.getElementsByName("amt")[i++]) {
if (ch.checked)
{
total=total+Number(ch.value);
}
}
var div=document.getElementById('divTotal');
total="$"+total.toFixed(2);
div.innerHTML= "Total: " +total;
return total;
}
function calTrans(x,y,z)
{
do calculations here
// concatenate into Trans number
var transNum=rm.concat(em,tm,am);
return transNum;
}
</script>
<form id="frmcheckout" action="out.php" method="post" onsubmit=calTrans()>
<table cellspacing="25">
<tbody>
<tr>
<th>Selection</th>
<th>Title</th>
<th>Cost</th>
</tr>
<tr>
<td>
<input type="checkbox" name="amt" value="$cost" onclick="calTotal()"></td>
<td>$Title</td>
<td>$cost</td>
</tr>
#end
</tbody>
</table>
<table>
<tbody>
<tr>
<td colspan="2">
E-mail address:<input type="text" name="email" value="E-mail required">
</td>
</tr>
<tr>
<td>
<div id="divTotal"></div>
</td>
<td>
<input type="submit" value="Submit";>
</td>
</tr>
</tbody>
</table>
</form>
Have you tried using hidden fields? e.g.
<input type="hidden" name="total" id="total" value="" >
You can use the same method for your unique transaction id. Then you can populate the hidden fields when you populate your "divTotal" div. e.g
document.getElementById("total").value = total;
This way when the form is submitted, the value will be passed to the script as "total" (in my example above). You can get values in php like this:
<?php
$total = $_POST["total"];
$amount = $_POST["amount"];
$email = $_POST["email"];
$transactionId = generateTransId(<<someparams>>);//YOUR FUNCTION TO CREATE TRANS ID
?>
Then to display your transaction id or output it anywhere on your php page, this is one example:
<div id="transId"><?php echo $transactionId; ?></div>

Update textfield based on combobox selection using JQuery - accessing list problem

I have a Spring MVC application, use JSP+JQuery for view, and what I need is to, based on combo box selection (which gets me an index of element in list) to populate text field.
listProduct - list of products that is in the model
<form:form method="POST" commandName="productForm" name="insertRacun">
<table>
<tr>
<td class="ui-widget">Product:</td>
<td><form:select path="productListId" id="productCombobox">
<form:options items="${listProduct}"itemLabel="name" itemValue="productId"/>
</form:select>
</td>
<td class="ui-widget">Product price:</td>
<td><form:input path="priceList"
class="ui-widget ui-widget-content" id="priceInput" />
</td>
<script type="text/javascript">
var comboIndex = $("#productCombobox").val();
$("#priceInput").val(${listProduct[comboIndex].price})
});
</script>
My question is: When i put number in listProduct[] i.e. listProduct[0] it works just fine and price field gets populated, but when i want put "comboIndex" in brackets, it does nothing.
If there is another solution (not using JQuery), please post it
You are mixing client and server side code. You cannot pass a JS variable to your server code, as your server code is parsed before the page has been served up to the client.
You will need to pass the price corresponding to a particular product ID to the client by other means.
The relevant code (probably in a change event handler) should reference productCombobox selectedIndex instead:
var comboIndex = $("#productCombobox").attr("selectedIndex"); //
$("#priceInput").val(${listProduct[comboIndex].price});

Categories

Resources