I have a table with a feature to select value of a row to send it to the Flask backend, that on button click also redirects my users to a different endpoint. What I need is to open the new endpoint requested in a new webpage instead of the same page. My HTML code where the button is located is as follows. It envelopes a table column value.
{% for item in rows %}
<tr>
<td>{{ item[0] }}</td>
<td>
**<button** formaction="/stockpopup"
type="submit" name = 'stock' value = {{`item[11] }}>
{{ item[11] }}**</button>**
</td>
<td>{{ item[1] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
I am looking for possible alternates to using JavaScript to achieve this outcome if anyone can help.
You can use the onclick method inside of html.
Something like this should work:
<button onclick="window.open('https://stackoverflow.com','_blank')">Open in new tab</button>
Related
I created a table in my html file for my Django project, and the raw data is based on the following list (It's a very long list, so I only list a few lines):
mylist=
[{'StartDate': '2021-10-02', 'ID': 11773, 'Receiver': Mike, 'Days':66 },
{'StartDate': '2021-10-03', 'ID': 15673, 'Receiver': Jane, 'Days':65},
...
{'StartDate': '2021-10-5', 'ID': 34653, 'Receiver': Jack, 'Days':63}]
My Html file:
<table class="table table-striped" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>StartDate</th>
<th>ID</th>
<th>Name</th>
<th>Days</th>
</thead>
<body>
{% for element in mylist %}
<tr>
<td>{{ element.StartDate}}</td>
<td>{{ element.ID }}</td>
<td>{{ element.Receiver }}</td>
<td>{{ element.Days }}</td>
</tr>
{% endfor %}
</tbody>
</table>
I want to make all the rows with the same ID value the same color. Please advise what I should add into the <td>{{ element.ID }}</td>. Thank you!
parts of my views.py:
client = gspread.service_account_from_dict(creds)
def CreateSheet(Return_record):
sheet = client.open(Return_record).sheet1
return sheet
from sheet2api import Sheet2APIClient
sheet = client.open('Return Record 2022')
sheet_instance = sheet.get_worksheet(0)
mylist = sheet_instance.get_all_records()
mylist
def table2022(request):
return render(request,'table2022.html',{'mylist':mylist})
Everything we want to pass as context, we should keep inside view we want to use it in. It's more readable when we have more and more code.
What we are going to do, it's define a color for numbers 0-9. I'll pick some light colors for now, you can change them as you prefer.
views.py:
def table2022(request):
mylist = sheet_instance.get_all_records()
colors = {'0': 'aqua', '1': 'beige', '2': 'burlywood', '3': 'lightgrey', '4': 'silver', '5': 'skyblue', '6': 'lightblue', '7': 'lightpink', '8': 'lightgreen', '9': 'lawngreen'}
context = {'mylist': mylist, 'colors': colors}
return render(request, 'table2022.html', context)
Now, because in templates it's not that simple to use Python, we need to create custom Template Tag. Let's start with creating folder in your app, let's name it custom_tags.py. It should be created in YourProject/your_app/templatetags/ folder, so we have to also create templatetags folder in there.
custom_tags.py:
from django import template
register = template.Library()
#register.filter(name='get_color')
def get_color(colors, number):
return colors[str(number)[-1]]
your_template.html:
{% load custom_tags %}
...
{% for element in mylist %}
<tr>
<td>{{ element.StartDate }}</td>
<td style="background-color: {{ colors|get_color:element.ID }}">
{{ element.ID }}
</td>
<td>{{ element.Receiver }}</td>
<td>{{ element.Days }}</td>
</tr>
{% endfor %}
get_color tag is basically taking whole ID, then extract only last number and make it a string. After that it uses the single number as a key in colors dictionary and passes corresponding value to template, where it is going to be a valid html color.
Custom tags are used to 'implement' some Pythonic code directly into template. Don't use it too much, because most of coding should be in standard files like views.py and models.py. But sometimes there is no better way. :)
For more details about Tags, check that Django's DOCS
I have found many answers to this on SO but my understanding of all of this is still too new to be able to understand how to implement so just posting my exact question:
I have a table which is a filtered view of my database that shows up on one page of my app. It has a notes column where each cell uses content-id-editable. I want to add a save button and when someone wishes to save that particular notes section cell I want them to be able to press "save" and have the updated cell post to the database.
UPDATED QUESTION:
I have made an attempt at using AJAX to push the data to the database (based on #rastawolf's answer) but I haven't made much progress and everything online seems to be geared toward inputting an entire form instead of one column of a table. Here's where I'm at so far:
notes.js:
function saveNoteAjax() {
return $.ajax({
type: 'POST',
url: '/Users/justinbenfit/territorymanagerpython/homepage/views.py/notes',
data: {note: document.getElementById('notes').value,}
})
}
async function SaveLoadNote(){
await saveNoteAjax()
return $.ajax({
type: 'GET',
url: '/Users/justinbenfit/territorymanagerpython/homepage/views.py/notes',
data: {note: document.getElementById('notes').value}
})
let location = "/Users/justinbenfit/territorymanagerpython/homepage/", """I don't have any idea how to make the page refresh"""
location.reload()
}
detail.hmtl:
<table class= "content-table">
<thead>
<tr>
<th>Name</th>
<th>Distributor</th>
<th>State</th>
<th>Brand</th>
<th>Cell</th>
<th>Email</th>
<th>Notes</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
{% for tm in territory_manager %}
<td style="white-space:nowrap;">{{ tm.Name }}</td>
<td style="white-space:nowrap;">{{ tm.Distributor }}</td>
<td style="white-space:nowrap;">{{ tm.State }}</td>
<td style="white-space:nowrap;">{{ tm.Brand }}</td>
<td style="white-space:nowrap;">{{ tm.Cell }}</td>
<td style="white-space:nowrap;">{{ tm.Email }}</td>
<td id='notes' contenteditable="True">{{ tm.Notes }}</td>
<td><input type='submit', align="right" value='Update' class='btn btn-primary'></td>
</tr>
{% endfor %}
</tr>
{% else %}
<h2>No Results for: {{ state }} </h2>
{% endif %}
</tbody>
</table>
<!-- Scripts -->
<script src="assets/js/notes.js"></script>
</body>
</html>
views.py:
def notes(request):
if request.is_ajax():
note = request.POST['note']
updatedNote = TM.objects.update(note) #how is the database supposed to know which tm's notes field to update? How do I pass that information in here?
return render(request, 'homepage/detail.html', {"note": updatedNote})
I wouldn't recommend setting it up this way as the page will refresh every time someone saves a note...
Why don't you instead send the POST data via AJAX?
You will need to write a JavaScript function that you can call when your button is clicked.
You can do something simple like...
Notes.js
function saveNoteAjax() {
return $.ajax({
type: 'POST',
url: 'your route to the function notes function in views.py',
data: {note: document.getElementById('yourNotesInput_ID').value}
})
}
async function SaveLoadNote(){
await saveNoteAjax()
*use another Ajax call to get the new notes from the DB*
*insert some function to refresh the notes on-screen*
}
views.py
def notes(request):
if request.is_ajax():
note = request.POST['note']
*insert your code for updating your DB table*
return HttpResponse('')
If you don't want AJAX, you could make your entire table into a Django model formset. Each notes field would be an input element. To get started, {{form.notes}}. Once it's working you can change your html to render the and style the form field any way you want). The other non-editable fields would be accessed with {{form.instance.fieldname}}
The differemce would be that the user would need to explicitly update after making changes, i.e. you need an Update button to submit the change(s)
Formsets and model formsets look complicated to start with, but they aren't really once you have done a few on them!
I have a simple Flask application with just one table.
So python code is irrelavantly simple:
#app.route('/')
def home():
items = long_db_request()
return render_template("index.html", items=items)
#app.route('/extended')
def extended():
return render_template("animals.html")
And items is a huge JSON object.
I created a table which reflects that data:
<table>
<tr>
<th style="text-align:center">id</th>
<th style="text-align:center">creation time</th>
<th style="text-align:center">name</th>
<th style="text-align:center">animals</th>
<th style="text-align:center">number</th>
</tr>
{% for item in items %}
<tr>
<td> {{ item.id }} </td>
<td> {{ item.time }} </td>
<td>
{{ item.name }}
</td>
<td> {{item.group}} </td>
<td>{{ item.group|length }}</td>
</tr>
{% endfor %}
</table>
The table looks like:
As you can see, column animal contains a lof of object which makes it all difficult to percieve.
I want it to be like this
which is a lot easier to get. And show animals is a link to another page, where a pure json exists.
How can I achieve this?
I followed the doc of jinja2 and Flask and found method url_for() but in that case I have to pass all my json in query which is unacceptable..
How can I jump from first image to exellent nice view of the second one?
working code with the first picture is place here
Thank you very much in advance!
P.S. I only saw one question here with rellevant topic, but it does not help me
Instead of passing all the animals (e.g. cats) from one view to another, just pass the category cats to the next page.
The view function for the next page then selects all cats from the json, and passes the cats then to the detailed view.
So, on you overview page, you render links like species.html?cats (and so on), and when somebody clicks on these links the view function selects all cats, and then passes them into a render_template("species.html", species=cats) view.
I'm new to Flask and programming. I'm creating a simple database using Flask/SQLite. I'm having users enter the data in a form and having that data populate on an HTML table next to the form. I've managed to achieve this. However, I've like to add the ability of a user to delete a row in the table.
I've created a function in my routes.py that I've like to utilize, but I can't find a way to pass user submitted information back to my routes.py function. I've tried using an HTML link but I don't want to pass the user to another URL and back. Is there a way to achieve this?
From routes.py
#app.route("/")
#app.route('/interventions', methods=['GET', 'POST'])
#login_required
def interventions():
.....
qinter = Interventions.query.all()
def delete_entry(entry):
db.session.delete(qinter[(entry-1)])
db.session.commit()
return redirect(url_for('interventions'))
.....
From Interventions.html
.........
<table border="1">
<tr>
<th>Delete?</th>
<th>Date</th>
<th>Chart #</th>
<th>Provider</th>
<th>Pharmacist</th>
<th>COI</th>
<th>Accepted?</th>
<th>Intervention</th>
</tr
{% for q in qinter %}
<tr>
<td><delete</td>
<td>{{ q.date }}</td>
<td>{{ q.chart }}</td>
<td>{{ q.prescriber }}</td>
<td>{{ q.pharmacist }}</td>
<td>{{ q.category }}</td>
<td>{{ q.accepted }}</td>
<td>{{ q.intervention }}</td>
</tr>
{% endfor %}
</table>
What you need is some way to communicate from your HTML template to your interventions route that you want to delete a certain row in your database table. To do that you need to add some additional parameters to your route function, like this:
#app.route('/interventions', methods=['GET', 'POST'])
#app.route('/interventions/<action>/<item_id>', methods=['GET', 'POST'])
#login_required
def interventions(action=None, item_id=None):
def delete_entry(entry):
db.session.delete(entry)
db.session.commit()
if request.method == "POST":
if action == 'delete':
# Get specific row user wants to delete
qinter_row_to_delete = Interventions.query.get(item_id)
# Delete row
delete_entry(qinter_row_to_delete)
return redirect(url_for('interventions'))
elif request.method == "GET":
qinter = Interventions.query.all()
# Render template etc...
Then from Jinja template make a call to that endpoint to delete the row:
<form id="form" action="{{url_for('interventions', action='delete', item_id=q.id)}}" method="POST">
I am trying to save checked off checkboxes.
The issue I am having right now is that when I press the email button, the page goes blank and when I try to go back, it asks me if I want to "Confirm Form Resubmission". I also tried linking the same page back like this in the form tag:
<form action="{% url 'ordered_user_list' %} method="post">
Note that the email button shouldn't do anything except reload the same page, but have the boxes checked as before. Also, if I come back to it from a different page, it should still be checked off as before.
in html file
<form method="post">
<table class="table">
<tr>
<th></th>
<th><u>Last Name</u></th>
<th><u>First Name</u></th>
<th style="width: 30%"><u>Email</u></th>
<th><u>Phone</u></th>
</tr>
{% for user in object_list %}
<tr>
<td><input type="checkbox" name="emailList" value="{{user.id}}"></td>
<td> {{ user.lastName|capfirst }}</td>
<td><a href="{% url "user_info" user.id %}">{{ user.firstName|capfirst }}</td>
<td>{{ user.email }}</td>
<td>{{ user.phone }}</td>
</tr>
{% endfor %}
</table>
{% csrf_token %}
<input class = "btn btn-danger" type="submit" value="Email"/></form>
in View file
class OrderedUserList(ListView):
model = User
template_name = "Schedule/ordered_user_list.html"
def dispatch(self, *args, **kwargs):
if not self.request.user.is_authenticated() or (not self.request.user.admin and not self.request.user.volunteer_coordinator):
return forbidden()
checked = request.POST.get('emailList')
return super(OrderedUserList, self).dispatch(*args, **kwargs)
You can save the selections by setting a COOKIE(in your view) by using the 'set_cookie' command.You can then access this cookie within your session and get the values of selections wherever you want.But remember that 1)the cookie saves your selection as a single string so be careful about how you save your selections so it is easier to extract them later (using string split method) and 2)it has a downside that this will be a system-dependent solution as the cookie wont be accessible if you save a cookie on one device and try to login from some other device/system at the same time.Hope this helps....