get_template_attribute not displaying data in html - python

i came across get_template_attribute in the flask api and thought of it as a great way to achieve partial page rendering.
so the goal was
create a 2 layer menu-page layout
menu should be static
on click of
menu, page should be shown dynamically without refreshing the entire
page
so i did something like so
LandingPage.html
<html>
<head>
<style>
html,body{
height:100%;
}
</style>
<script type="text/javascript">
function finalConfirmationToStartJob() {
alert('in here')
$.ajax({
type : 'GET',
url : 'home2',
data : ''
});
};
</script></head>
<body>
<table border=1 height=100% width=100%>
<tr><td colspan='2'/></tr>
<tr>
<td width=15%>
<ul>
<li>ABC</li>
<ul>
<li>ABC1</li>
<li>ABC2</li>
<li>ABC3</li>
</ul>
<li>DEF</li>
<li>GHI</li>
<li>JKL</li>
</ul>
</td>
<td>
{% macro hello(name) %}Hello {{ name }}!{% endmacro %}
how are you darlings!!! {{hello()}}
</td>
</tr>
<tr><td colspan='2'/></tr>
</table>
</body>
</html>
Controller
#app.route("/home")
def goto_home():
return render_template('/LandingPage.html')
#app.route("/home2")
def try_out_macro():
print 'hellooo elloo'
hello = get_template_attribute('/LandingPage.html', 'hello')
return hello('World')
However when i do click on the action link, even though the controller actually returns perfect data , the data is not displayed on the screen.
When i hit the url /home2 i do get perfect data, however on click on action link nothing happens on the html
Can someone please help me, i am not sure what i am doing wrong
PS : i got it to work using innr html and div combination, however i would still like to know why the above doesnt work.

Related

Table order messed in Firefox, but works fine in other browsers

I have a table that I sort by date, it works fine in EDGE and Chrome, but the order is messed in Firefox. A series of rows that should be on top got moved down to the bottom.
HTML:
<div class="row mt-4">
<div class="col-12">
<div class="card">
<h6 class="card-header">Change Log Items</h6>
<div class="card-body">
<table id="changes" class="table table-striped table-hover table-bordered table-sm">
<thead class="table-dark">
<tr class="sticky">
<th>Title</th>
<th>Component</th>
<th>Date Committed</th>
<th>Jira Link</th>
<th>Details</th>
</tr>
</thead>
<tbody>
{% for log in logs %}
<tr>
<td>{{log.title}}</td>
<td>{{log.component}}</td>
<td>{{log.date_added}}</td>
<td>{% if log.jira_number %}<a class="general" href="https://jira.kinaxis.com/browse/{{log.jira_number}}" target="_blank">{{log.jira_number}}{% endif %}</a></td>
<td>{% if log.details %}{{log.details}}{% elif not log.details and log.jira_number %}See Jira ticket{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
View:
#login_required
def change_log(request):
logs = ChangeLog.objects.all().order_by('date_added')
return render(request, 'help\changelog.html', {'logs': logs})
Any information helps! :)
Update:
I realized the problem was caused by the jQuery corresponding to the HTML element:
<script type="text/javascript">
$(document).ready(function () {
const exceptions = $('#changes').DataTable({
"order": [[ 2, "desc" ]],
"pageLength": 50,
"columnDefs": [{"type": "date", "targets": [2],}], // Sort by Date properly
});
});
</script>
Seems like DataTable has some issues with FF?
Changing the order in "order": [[ 2, "desc" ]]" to asc doesn't work for FF.
Most likely, the date format you are using is not supported by Firefox, as "the date formats supported by each browser vary significantly". In such cases, one could use the "ultimate" date / time ordering plug-in for DataTables, as suggested here. To do that, include the following libraries in your HTML file, as described in the above link:
<script type="text/javascript" charset="utf8" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.4/moment.min.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/plug-ins/1.11.5/sorting/datetime-moment.js"></script>
Next, register the date format(s) that you wish DataTables to detect and order using the $.fn.dataTable.moment(format) method. For instance:
$(document).ready(function() {
$.fn.dataTable.moment( 'HH:mm MMM D, YY' );
...
DataTables will automatically detect the column(s) with date data, by checking to see if the data in a column matches any of the given types. You can register multiple date formats, if a DataTable contains more than one date columns.
Try explicitly adding "ordering: true" to your DataTable() instantiation, like so:
<script type="text/javascript">
$(document).ready(function () {
const exceptions = $('#changes').DataTable({
ordering: true, # add this line
"order": [[ 2, "desc" ]],
"pageLength": 50,
"columnDefs": [{"type": "date", "targets": [2],}], // Sort by Date properly
});
});
</script>
More a suggestion than an answer, but didn't want to paste this code in the comments.

Django: Get a table into Django view

I have Django model that contains data ("Name" and "Status") for 10 people. I display this model in a DataTable with checkboxes and if I check a box it changes the Class into selected, e.g. <tr role="row" class="odd selected"
The user makes a selection from the DataTable and press a button ("Send selection by email"). The selection will go into a Django View. I will write code that filter out those contains a selected, obtain its PK and send an email with info.
However, I have problem in the first step, to get the DataTable object into the view.
A similar approach would have been to use a Multiselect, but here I want the look of a table and not a form box.
My attempted solution is to put form tags around the DataTable and then read the table to filter out all that are selected.
Problem I currently have is that I cannot get the DataTable into the views.py.
So my question is: How do I access the table in Django View?
I have tried both POST and GET within below, but request object returns as None
$('#datatable').DataTable({
responsive: true,
columnDefs: [{
orderable: false,
className: 'select-checkbox',
targets: 0
}],
select: {
style: 'multi',
selector: 'td:first-child',
// selectRow: true
},
order: [
[1, 'asc']
],
language: {
searchPlaceholder: 'Search...',
sSearch: '',
lengthMenu: '_MENU_ items/page',
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.min.js"></script>
</head>
<body>
<div class="container">
<form method="post" action="{% url 'product-send2' %}">
{% csrf_token %}
<div class="table-wrapper">
<table class="form-control table display responsive" id='datatable' style="width:100%;">
<thead>
<tr>
<th>Send</th>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
<td></td>
<td>{{ object.name }}</td>
<td>{{ object.status }}</td>
<tr>
{% endfor %}
</tbody>
<tfoot>
</tfoot>
</table>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</body>
</html>
In the Urls
path('product/send/', send_product2, name='product-send2')
and in the views
def send_product2(request):
recipients = request.POST.get('datatable')
print(recipients)
return HttpResponseRedirect('/product/list')
I have tried variants such as
recipients = request.GET.get('datatable')
and
recipients = request.POST.get('datatable', False)
I cannot get hold of the "object" and don't really know how to debug it.
In the end, it should work as a multiselect for the form (that will be sent by email).
I hope I can help with some hints how to progress.
Thanks!
When I print(request.__dict__) it looks like below
: <SimpleLazyObject: <function AuthenticationMiddleware.process_request.<locals>.<lambda> at 0x7f907ab5f680>>, '_messages': <django.contrib.messages.storage.fallback.FallbackStorage object at 0x7f907ab82b10>, '_body': b'csrfmiddlewaretoken=xxx_length=10', '_post': <QueryDict: {'csrfmiddlewaretoken': ['xxxxx'], 'datatable_length': ['10']}>, '_files': <MultiValueDict: {}>, 'csrf_processing_done': True}
you can not submit an entire table in a form, especially based on id tag. From the code you posted it looks like you configured your datatable without event handlers.
From: https://editor.datatables.net/examples/inline-editing/submitButton.html
dom: "Bfrtip",
ajax: "../php/staff.php",
columns: [
{
data: null,
defaultContent: '',
className: 'select-checkbox',
orderable: false
},
{ data: "first_name" },
{ data: "last_name" },
{ data: "position" },
{ data: "office" },
{ data: "start_date" },
{ data: "salary", render: $.fn.dataTable.render.number( ',', '.', 0, '$' ) }
],
order: [ 1, 'asc' ],
select: {
style: 'os',
selector: 'td:first-child'
},
buttons: [
{ extend: "create", editor: editor },
{ extend: "edit", editor: editor },
{ extend: "remove", editor: editor }
]
and then added a submit button that actually tries to pull all the elements with name tag in the form dom sub-tree and sends those to the back-end.
In order to achieve what you want you need to create a custom event handler in the front-end that is hooked to the checkbox(or use functions integrated in the DataTable plugin) then generate a form on the fly with javascript where you add the relevant information(the pk of the selected record/s I assume). Submitting the newly generated form will result in a valid POST request that you can handle in the view.
Given all above, I would recommend to avoid using such mechanics in general. POST/GET that are not REST based lead to the regeneration of the entire page which is a bad thing to do when dealing with large interactive tables.

View to Download FileField From Django

I have files which are saved to the MEDIA_ROOT - and I am displaying the file paths as URLs in a table in my UI. I would like for these files to download when the user clicks the link in the table. However, when that happens I get an error because I don't have a URL or View defined to handle this I suppose. Problem is, I'm not really sure where to start - any suggestions. Below is my model, and the .html which displays the table and the link.
models.py
class Orders(models.Model):
...
order_file = models.FileField(upload_to='web_unit', null=True, blank=True)
...
def __str__(self):
return self.reference
index.html
<div class="table-responsive">
<table id="main_table" class="table table-striped table-bordered" cellspacing="0" style="width="100%">
<thead>
<tr>
....
</thead>
<tbody>
{% for orders in orders %}
<tr>
<td>
<!-- Update book buttons -->
<button type="button" class="update-book btn btn-sm btn-primary" style="color: #FFCF8B; border-color: #FFCF8B; background-color: #FFF;" data-id="{% url 'order_update' orders.pk %}">
<span class="fa fa-pencil"></span>
</button>
</td>
....
<td>Download</td> #this is the link
</tr>
{% endfor %}
</tbody>
</table>
When the link in the table is clicked - I'd like for the file to be downloaded - I need help on how to define the URL and the View to make this happen.
This has been marked as a duplicate a few times now - but I don't believe it is. The link that I have been referred to only shows a view. I don't understand how I am to trigger that view using a url since there will be many download links in the same screen. How does the view know which file link I have clicked on? Wouldn't that need to leverage the URL somehow?
First, don't do {% for orders in orders %}; instead do {% for order in orders %}
Then this should work (assuming order_file is the field name you didn't show in the model)
<td>Download</td>

Django Sending HTML Table to Python

Hello Guys
I'm working with Django and I have a big doubt, i have 3 HTML tables and i need save this data in mysql, that table is filled by users and im not sure how can i sending the tables to python.
i tried using Ajax, but, really I'm not sure how to use it.
HTML CODE from one of my 3 tables:
custom.html
<table id="idTable" name="table" class="table table-striped table-bordered">
<thead>
<tr>
<th>FIRST</th>
<th>Second</th>
<tr>
</thead>
<tbody>
</tbody>
</table>
<button class="btn btn-primary" onclick="ajaxFunction()" id="IDButton">Touch me!</button>
The tbody rows are added with javascript
Ajax code:
<script type="text/javascript">
function ajaxFunction(){
var request = $.ajax({
url: window.location.href,
type: 'get',
data: {data1: "hello"},
contentType: 'application/json; charset=utf-8'
});
request.done(function(data)){
console.log("works")
});
</script>
When i click the button in the console i can see "works" but in python is not working
Python code:
crm/views.py
def custom(request, op_id):
if request.method == "GET":
IF request.is_ajax():
message ="Yes"
else:
message="No"
return render(request, "custom.html")
I don't know why function is_ajax does not works.
I only wanna find a way to do this,
i will be glad !!!!
Thank you!

manipulating web forms in python

I'm a novice at Python. I'm trying to learn how to post data to a web form and grab the result but I couldn't understand any of the examples I found on the web, and they pointed to websites that no longer exist. So I found this website http://www.autotrader.co.uk/vehiclecheck which accepts a vehicle reg and gives you some more data.
Can anyone show me how to put that data in the form and grab the text that then appears (on a new website)? I'm hoping someone can explain what the code does rather than just tell me the answer, as I just chose a random example (and therefore feel free to choose a different example). thanks
You can make a get request passing the reg:
import requests
params = {"SC":"132","vrm":"foobar"}
req = requests.get("https://www.vehiclecheck.co.uk/",params=params)
print(req.content)
Which if you run you will see in the output:
<h3>Sorry, we didn't recognise that registration.</h3>
<p>Please check that you have entered your registration correctly and try again. For example, a zero (0) and a capital O (letter) or a one (1) and a capital I (letter) can appear very similar.</p>
Which is exactly what you see in the browser.
Using a proper reg you can see part of the html returned below which contains the search result, I removed art of reg :
<div id="searchResult">
<h1 class="HeaderMargin HideOnMobile">Vehicle details</h1>
<h2 class="NoMargin HideOnMobile">We've identified this car using the details you provided</h2>
<h2 class="NoMargin ShowOnMobile">We've identified this car</h2>
<h3>HANGLONG UNKNOWN 2007 </h3>
<div class="SearchResultCarImageContainer">
<img src="/VehicleCheck/ShowImage/?id=&CapType=0" alt="Vehicle image" id="searchResultCarImage">
<p class="SubLine">Vehicle Image for illustrative purposes only.</p>
</div>
<div class="Column">
<table id="vrmSearchTable">
<tr>
<td class="Reg"><strong>Registration number:</strong></td>
<td class="Reg">GN57###</td>
</tr>
<tr>
<td><strong>Body type:</strong></td>
<td>Scooter</td>
</tr>
<tr>
<td><strong>Colour:</strong></td>
<td>Red</td>
</tr>
<tr>
<td><strong>Date of first registration:</strong></td>
<td>November 2007</td>
</tr>
</table>
If you were to input foobar into the search box in the browser you see a new tab open with the url:
https://www.vehiclecheck.co.uk/?SC=132&vrm=foobar
You just need to mimic that with the request.
If you inspect the html you can see the form and what the input name is i.e input name="vrm":
<form action="https://www.vehiclecheck.co.uk" method="get" target="_blank" class="js-top-form vrm-lookup-form">
<input type="hidden" id="SC" name="SC" value="132">
<div class="gb-reg-icon--wrap">
<svg class="gb-reg-icon">
<title>Registration GB Icon</title>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/templates/_generated/svg_icons/vehicle-check.svg#icon-gb-reg"></use>
</svg>
</div>
<span class="js-vrm-input input-error-wrap">
<input name="vrm" type="text" maxlength="8" class="reg-input-large input-large js-vrm-input-focus" placeholder="ENTER REG">
<span class="js-input-error input-error vrm-mileage-input__vrm-error is-hidden"></span>
</span>
<button type="submit" class="vrm-lookup-form__button button-green-large track-submitVrmLookup tracking-motoring-products-link" data-label="vehicle-check-start-check-initiation">
Start check
</button>
</form>
When you go to the page after clicking i.e the:
https://www.vehiclecheck.co.uk/?SC=132&vrm=foobar
page, open the developer console in chrome firefox, open the network tab and hit f5, then have a look at the requests being made, in chrome you can see the first is ?SC=132&vrm=foobar then when you click on that you see under query string parameters:
SC=132&vrm=foobar
Or if you click view parsed:
SC:132
vrm:foobar
Which are the parameters that need to be passed.
You have the input name so if you were trying to post, you would use the name i.e vrm as a key and the value you want to submit, using your own details:
import requests
data= {"vrm": "SM59TXS"}
req = requests.post("https://www.vehiclecheck.co.uk/",data=data)
print(req.content)
We see the searchResult again this time with your car details:
<div id="searchResult">
<h1 class="HeaderMargin HideOnMobile">Vehicle details</h1>
<h2 class="NoMargin HideOnMobile">We've identified this car using the details you provided</h2>
<h2 class="NoMargin ShowOnMobile">We've identified this car</h2>
<h3>VOLVO V70 R-DESIGN SE D 2009 </h3>
<div class="SearchResultCarImageContainer">
<img src="/VehicleCheck/ShowImage/?id=42B913362B14F8DF&CapType=0" alt="Vehicle image" id="searchResultCarImage">
<p class="SubLine">Vehicle Image for illustrative purposes only.</p>
</div>
<div class="Column">
<table id="vrmSearchTable">
<tr>
<td class="Reg"><strong>Registration number:</strong></td>
<td class="Reg">SM59TXS</td>
</tr>
<tr>
<td><strong>Body type:</strong></td>
<td>Estate</td>
</tr>
<tr>
<td><strong>Colour:</strong></td>
<td>Blue</td>
</tr>
<tr>
<td><strong>Date of first registration:</strong></td>
<td>December 2009</td>
</tr>
</table>
So the bottom line is you need to find the input id or name from the html then post the using the id/name as the keys and the values you want to submit as the values. There is no magic bullet that will work for every form so you have to understand what is happening, that is why learning how to use the developer console will be be invaluable.
One library for manipulating forms with Python is selenium. here's an example of how you would interact with your given page with selenium:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('http://www.autotrader.co.uk/vehiclecheck')
# find the input you want to manipulate by checking the source code of the website
# for example, to enter a reg, first ID the reg form by it's class
reg_form = driver.find_element_by_name('vrm')
# then send some input to it
reg_form.send_keys('test reg you want to send')
# then ID the start check button to be able to click it
start_check_button = driver.find_element_by_css_selector('button.vrm-lookup-form__button.button-green-large.track-submitVrmLookup.tracking-motoring-products-link')
# and send a click
start_check_button.click()
# then parse the page as you want

Categories

Resources