I want to send data from HTML page to function in views.py.
I tried some codes JS … but I am not good with.
so I am going to do by the hard way.
my HTML has a table with for loop.
> <div class="row">
> <div class="col-md-7">
> <h3>Contract Items Details</h3>
> <div class="card card-body">
> <table id="table_id" class="table-wrapper table-sm">
> <thead class="thead-light"><tr>
> <th>Item Description</th>
> <th>Quantity</th>
> <th>Disc %</th>
> <th></th>
> </tr></thead>
> <tbody>
> <tr >
> {% for Field in AllItemes %}
> <td>{{Field.id}}</td>
>
> <form method="POST" id="formOne" enctype= multipart/form-data>
> {% csrf_token %}
> <div class="form-inline">
> <td><input class="form-control mr-1" placeholder="2" name="select_date1" type="number" min="0" pattern="\d*"/></td>
> <td><input class="form-control mr-1" placeholder="0" name="select_date2" type="number" min="0" pattern="\d*"/></td>
>
> <td><a href="{% url 'TESTDATA' the_invoice.id Field.id %}" class="btn btn-info btn-sm">Add</a></td>
> </div>
> </form>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
as is shown in images
and my function in views.py is:
def TESTDATA(request, id_itm, id_itm2):
print(id_itm, id_itm2)
PlotNum = request.POST.get('select_date1')
print(PlotNum)
PlotNum = request.POST.get("select_date2")
print(PlotNum)
return redirect('Invoic_billing', id_itm)
so I don’t receive the data when the Add button is in for loop?
any suggestion?
All My best.
When you have multiple instances of the same form in a page, you want to use Django’s formsets facility.
KenWhitesell:
same
it is not what I want, my point is that if the POST submit is inside a loop it will not work.
and also it takes only 2 values inside the input but I want to take the item index too.
If that snippet above is the complete template, you’re missing the endfor
directive for your for
loop.
Also, you’re generating multiple HTML forms in that loop, all with the same id
attribute.
1 Like
Hi smailt,
I think it might be useful for if you determine if the correct POST values are being sent by the client to the server. You can do that by opening the browser’s dev tools, submitting the form, then on the network panel inspect the POST’s body. If it’s not being included there, then we know it’s an HTML issue. If it is being included, then something is going on between the Django server receiving the request and your view handling it.
-Tim
KenWhitesell:
all with the same id
a
Yes, thanks I corrected the HTML. and yes I have multiple POSTs and Ids. how to deal with such cases?
Also, it’s not valid HTML to embed a complete form within a table.
Take a step back an describe what your form is supposed to do - then maybe we can offer some suggestions.
Again, it appears to me that each row in your table is a (can be a) separate Django form - in which case formsets are an appropriate tool. One of the outstanding questions is what exactly do you want to have happen on the click of the ‘Add’ button? Is it triggering some type of AJAX call via JavaScript? Or are you looking for a full page refresh every time one of those buttons are pushed?
First, I don’t mind if it refreshe each time when I press ADD.
I just want to take the Item.id, Quantity and Disc and execute a function.
the AllItemes data is simply stored in modele table and presented in the table as shown.
I tried the separated form before but the same problems multupl forms and POSTs. doesn’t work.
I tried
<form method="POST" id="formOne" enctype= multipart/form-data>
also the same works only with one separate inputs not with for loop and rows.
Thanks
As @CodenameTim pointed out previously, one of the things to check is to verify that your form is sending the right data - if it’s sending anything at all.
Beyond that, I think we’re at the stage where we’d need to see the complete view(s) involved and the current template that you are rendering.
1 Like
smailt
July 8, 2021, 4:17pm
10
That is all my code
#Model
class Invoice_billing(models.Model):
Invoce_Nbr = models.ForeignKey(Invoices, on_delete=models.CASCADE) # should be Actived
Item_Ctra = models.ForeignKey(contrat_items, on_delete=models.CASCADE) # should be Actived
Unites = models.DecimalField(max_digits=15, decimal_places=2,null=True)
Discu = models.DecimalField(max_digits=4, decimal_places=2,null=True)
post_date = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User,on_delete=models.CASCADE)
def __str__(self):
return self.Invoce_Nbr.Invoce_Nbr
def get_absolute_url(self):
return reverse('Contrat_detail')
class Meta:
ordering = ('-post_date',)
unique_together=[['Invoce_Nbr', 'Item_Ctra']]
#Form
class Invoice_billing_F(forms.ModelForm):
Unites = forms.DecimalField(required =False)
Discu = forms.DecimalField(required =False)
class Meta:
model= Invoice_billing
fields=('Unites','Discu')
#views.py
def Invoic_billing(request, id_itm):
the_invoice = Invoices.objects.get(id=id_itm)
AllItemes = contrat_items.objects.filter(Ctra_Nbr_id=the_invoice.Cntrat_Nbr_id)
Invoice_amount = Invoice_billing.objects.filter(Invoce_Nbr_id=id_itm)
Total_price=0
tablista=[]
for price in Invoice_amount:
if price.Discu:
Discu_is = (100-price.Discu)/100
else:
Discu_is= 1
unitqant= (price.Unites*price.Item_Ctra.Price*Discu_is)
list1= [id_itm, price.id , price.Item_Ctra , price.Unites, price.Discu, price.Item_Ctra.Price, unitqant]
Total_price += unitqant
tablista += [list1]
form_error = False
form_error_det = False
form = Invoice_billing_F
form2= Invoice_billing_F()
if request.method == 'POST':
if request.POST.get("form_ability") == "Add":
form2 =form(request.POST)
print(form2)
if form2.is_valid():
form2.instance.Item_Ctra_id = the_invoice.id
form2.instance.Invoce_Nbr_id= id_itm
form2.instance.author = request.user
form2.save()
return redirect('Invoic_billing', id_itm)
else:
form_error = 'Check your inputs'
# this section is not important
elif request.POST.get("form_del") == "delItem":
print("Add item")
Form_Item2 =Form_Item(request.POST)
if Form_Item2.is_valid():
Form_Item2.instance.author = request.user
Form_Item2.save()
return redirect('Eqpts_Track')
else:
form_error_det = 'Check your item name'
context={
'title':'Invoice',
'the_invoice':the_invoice,
'AllItemes':AllItemes,
'Total_price':Total_price,
'Invoice_amount':Invoice_amount,
'tablista':tablista,
'form':form,
}
return render(request,'Home/Scheduling/Invoices/Invoices_billing.html',context)
#HTML
{% block content %}
{% load crispy_forms_tags %}
{% load auth_extras %}
{% load static %}
<div class="container">
<h3 class="bg-secondary text-center text-light">Total items of the Contrat</h3>
<div class="w3-panel w3-border w3-light-grey w3-round-large ">
<div class="row">
<div class="col-md-7">
<h3>Contract Items Details</h3>
<div class="card card-body">
<table id="table_id" class="table-wrapper table-sm">
<thead class="thead-light"><tr>
<th>Item Description</th>
<th>Quantity</th>
<th>Disc %</th>
<th></th>
</tr></thead>
<tbody>
<tr >
{% for Field in AllItemes %}
<td>P.{{Field.page}}, {{Field.Item_Ctra}} {{Field.Item_Code}} {{Field.othr_Code}}</td>
<form method="POST" id="formOne" enctype= multipart/form-data>
{% csrf_token %}
<div class="form-inline">
<td>{{ form.Unites|as_crispy_field }}</td>
<td>{{ form.Discu |as_crispy_field }}</td>
<td> <input class="btn btn-success mb-6" name="form_uplod" type="submit" value="Add"></td>
</div>
</form>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="col-md-5">
<h3>Billing Details</h3>
<div class="card card-body">
<table id="table_id2" class="table-wrapper table-sm">
<thead class="thead-light"><tr>
<th>Item</th>
<th>Qts</th>
<th>Price.U</th>
<th>Disc</th>
<th>Total</th>
<th>remove</th>
</tr></thead>
<tr >
{% for bills in tablista %}
<td>{{bills.2}}</td>
<td>{{bills.3}}</td>
<td>{{bills.5}}</td>
<td>{{bills.4}}</td>
<td>{{bills.6}}</td>
<td>
<form action="{% url 'dashboard' %}" method="post">
{% csrf_token %}
<button class="btn btn-sm" type="submit" name='Del_btn' value={{UserID.id}}><i class="fas fa-trash" style="font-size:16px;color:red"></i></button>
</form></td>
</tr>
{% endfor %}
</table>
</div>
<div class="card card-body">
<div class="row"><div class="col-md-6"> Total invoice</div>
<div class="col-md-6"> {{Total_price}}</div></div>
<hr>
<div class="row"><div class="col-md-6"></div>
<div class="col-md-6"> {{the_invoice.Total_amount}}</div></div>
</div></div></div></div><br></div>
{% endblock content %}
{% block js %}
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/jszip-2.5.0/dt-1.10.18/af-2.3.0/b-1.5.2/b-colvis-1.5.2/b-flash-1.5.2/b-html5-1.5.2/b-print-1.5.2/cr-1.5.0/fh-3.1.4/r-2.2.2/datatables.min.css"/>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js"></script>
<script src="{% static 'Home/js/datatables.min.js' %}"></script>
<script>
$(document).ready( function () {
$('#table_id').DataTable({});
});
</script>
{% endblock %}
Ok, at a minimum, you still have the form embedded within an HTML table.
You’re also not rendering form fields, you’re rendering input
elements directly.
Your Add buttons are links (anchor tags) and not submit
buttons. They’re not going to post any data.
The former is going to prevent anything else you try from working properly, the latter can be made to work, but it’s really doing thing the hard way.
1 Like
smailt
July 8, 2021, 4:29pm
12
I corrected it now in html.
{% csrf_token %}
{{ form.Unites|as_crispy_field }}
{{ form.Discu |as_crispy_field }}
and in the viewa.py
if request.method == 'POST':
if request.POST.get("form_ability") == "Add":
form2 =form(request.POST)
if form2.is_valid():
form2.instance.Item_Ctra_id = ????? # here is the new problem?
form2.instance.Invoce_Nbr_id= id_itm
form2.instance.author = request.user
form2.save()
return redirect('Invoic_billing', id_itm)
it works good but. the only thing is
how I get the {{Field.id}}
which is the Item_Ctra in the model, from the HTML page?
could I set a default value of crispy from? for example:
{{ form.Item_Ctra|}}= {{Field.id}}
smailt
July 8, 2021, 6:16pm
13
Now I think this issue posted a year ago will help me to solve this problem.
https://stackoverflow.com/questions/62497111/set-a-value-to-crispy-form-input
if I can set a default value to a crispy field input I will solve this problem.
If you’re not instantiating the form with the instance, I’d probably end up rendering a hidden input:
<input type="hidden" name="field_id" value="{{ Field.id }} />
<input class="btn btn-success mb-6" name="form_upload" type="submit" value="Add">
Then add that to be a field on the form that’s not part of the model.
class Invoice_billing_F(forms.ModelForm):
field_id = forms.IntegerField()
...
Unites = forms.DecimalField(required =False)
Discu = forms.DecimalField(required =False)
class Meta:
model= Invoice_billing
fields=('Unites','Discu')
1 Like
One thing to note about that approach is that you have to validate that the request being performed is allowed to be performed with that field id. Since you’re now choosing the instance to update based on the form data, a malicious user could change that to be any value. You will need to prevent that case from causing problems.
smailt
July 8, 2021, 8:01pm
16
I did as you said:
class Invoice_billing_F(forms.ModelForm):
Item_Ctra = forms.IntegerField()
Unites = forms.DecimalField(required =False)
Discu = forms.DecimalField(required =False)
class Meta:
model= Invoice_billing
fields=('Unites','Discu')
and this the HTML form:
<form method="POST" id="formOne" enctype= multipart/form-data>
{% csrf_token %}
<div class="form-inline">
<input type="hidden" name="Item_Ctra_id" value={{Field.id}} />
<td default= {{Field.id}}>{{ form.Unites|as_crispy_field }}</td>
<td>{{ form.Discu |as_crispy_field }}</td>
<td> <input class="btn btn-success mb-6" name="form_ability" type="submit" value="Add"></td>
</div>
</form>
and the views.py is
if request.method == 'POST':
if request.POST.get("form_ability") == "Add":
form2 =form(request.POST)
print(form2)
if form2.is_valid():
#form2.instance.Item_Ctra_id = 6
form2.instance.Invoce_Nbr_id= id_itm
form2.instance.author = request.user
form2.save()
return redirect('Invoic_billing', id_itm)
else:
form_error_ablt = 'Check your inputs'
Now it send 3 parameters but there is an issue with the Field.id
the printed output of form2 is:
<tr><th><label for="id_Unites">Unites:</label></th><td><input type="number" name="Unites" value="55" id="id_Unites" step="any" /></td></tr>
<tr><th><label for="id_Discu">Discu:</label></th><td><input type="number" name="Discu" value="55" id="id_Discu" step="any" /></td></tr>
<tr><th><label for="id_Item_Ctra">Item ctra:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="number" name="Item_Ctra" id="id_Item_Ctra" required /></td></tr>
Ah, what’s happening is that the name of the field in the form doesn’t match the name=
attribute in the html form.
Change:
<input type="hidden" name="Item_Ctra_id" value={{Field.id}} />
To:
<input type="hidden" name="{{form.Item_Ctra.html_name}}" value={{Field.id}} />
That will be a little more robust in case you decide to change the name of the field in the future.
1 Like
smailt
July 8, 2021, 9:34pm
18
Yes it takes the three values to views.py now and this is the printed form2:
<tr><th><label for="id_Unites">Unites:</label></th><td><input type="number" name="Unites" value="22" step="any" id="id_Unites" /></td></tr>
<tr><th><label for="id_Discu">Discu:</label></th><td><input type="number" name="Discu" value="22" step="any" id="id_Discu" /></td></tr>
<tr><th><label for="id_Item_Ctra">Item ctra:</label></th><td><input type="number" name="Item_Ctra" value="18" required id="id_Item_Ctra" /></td></tr>
but it doesn’t save the form and gives me an error in the HTML page:
# IntegrityError at /Invoic_billing/3/
NOT NULL constraint failed: Home_invoice_billing.Item_Ctra_id
I encounter the same issue but my experience was base on API. This is how I solve it, I use zip and getlist
def save_fixture(self, request, header=None, instance=None):
game_number = request.data.getlist('game_number')
home_name = request.data.getlist('home_name')
away_name = request.data.getlist('away_name')
status = request.data.getlist('status')
home_result = None if 'home_result' not in request.data else request.data['home_result']
away_result = None if 'away_result' not in request.data else request.data['away_result']
result = 'LOADING' if 'result' not in request.data else request.data['result']
for (game_number, home_name, away_name, status) in zip(game_number, home_name, away_name, status):
data = {
'game_number': game_number,
'home_name': home_name,
'away_name': away_name,
'status': status,
'home_result': home_result,
'away_result': away_result,
'result': result,
}
if header is not None:
data['header'] = header
serializer_fixture = FixtureSerializer(instance, data=data)
if serializer_fixture.is_valid():
serializer_fixture.save()
return True
I’m sure this can help you.
smailt
July 9, 2021, 6:53am
20
it is a half another problem what is the inputs in HTML page.
could you please delete this , I am in the middle of solving the problem please.