Limit the user to give the test only once - javascript

I want to limit the student to attempt specific test once.
There can be multiple quizzes but each student should be giving test once only.
The student field is one to one field with user
#login_required(login_url='studentlogin')
#user_passes_test(is_student)
def calculate_marks_view(request):
if request.COOKIES.get('course_id') is not None:
course_id = request.COOKIES.get('course_id')
course=QMODEL.Course.objects.get(id=course_id)
total_marks=0
questions=QMODEL.Question.objects.all().filter(course=course)
for i in range(len(questions)):
selected_ans = request.COOKIES.get(str(i+1))
actual_answer = questions[i].answer
if selected_ans == actual_answer:
total_marks = total_marks + questions[i].marks
student = models.Student.objects.get(user_id=request.user.id)
result = QMODEL.Result()
result.marks=total_marks
result.exam=course
result.student=student
result.save()
return HttpResponseRedirect('view-result')
(Edited)
I'm giving the models that I used in this .
The models used are as follows :
Student :~
class Student(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE)
profile_pic= models.ImageField(upload_to='profile_pic/Student/',null=True,blank=True)
address = models.CharField(max_length=40)
mobile = models.CharField(max_length=20,null=False)
#property
def get_name(self):
return self.user.first_name+" "+self.user.last_name
#property
def exams_taken(self):
return [r.course for r in Result.objects.get(student=self)]
#property
def get_instance(self):
return self
def __str__(self):
return self.user.first_name
Quiz :~
class Course(models.Model):
course_name = models.CharField(max_length=50)
question_number = models.PositiveIntegerField()
total_marks = models.PositiveIntegerField()
def __str__(self):
return self.course_name
class Question(models.Model):
course=models.ForeignKey(Course,on_delete=models.CASCADE)
marks=models.PositiveIntegerField()
question=models.CharField(max_length=600)
option1=models.CharField(max_length=200)
option2=models.CharField(max_length=200)
option3=models.CharField(max_length=200)
option4=models.CharField(max_length=200)
cat=(('Option1','Option1'),('Option2','Option2'),('Option3','Option3'),('Option4','Option4'))
answer=models.CharField(max_length=200,choices=cat)
class Result(models.Model):
student = models.ForeignKey(Student,on_delete=models.CASCADE)
exam = models.ForeignKey(Course,on_delete=models.CASCADE)
marks = models.PositiveIntegerField()
date = models.DateTimeField(auto_now=True)
The template for exam that I used is given as follows:
<div class="container">
<div class="panel panel-primary">
<div class="panel-heading">
<h6 class="panel-title">Courses</h6>
</div>
<table class="table table-hover" id="dev-table">
<thead>
<tr>
<th>Exam Name</th>
<th>Take Exam</th>
</tr>
</thead>
{% for t in courses %}
<tr>
<td> {{t.course_name}}</td>
<td><a class="btn btn-danger btn-xs" href="{% url 'take-exam' t.id %}"><span class="glyphicon glyphicon-circle-arrow-right"></span></a></td>
</tr>
{% endfor %}
</table>
</div>
</div>
I want to show the button only to new user
<td><a class="btn btn-danger btn-xs" href="{% url 'take-exam' t.id %}"><span class="glyphicon glyphicon-circle-arrow-right"></span></a></td>

I assume from your code example, each course has one exam and each student should be able to take each of the exams once. Looks like you already have a model Result that stores the relation between the student and each exam or course. You could simply check if such an object already exists for the combination of the user and the course.
class Student(model):
[...]
#property
def exams_taken(self):
return [r.course for r in Result.objects.get(student=self)]
(I'm pretty sure there is a more elegant way to do use the query language instead of the list comprehension..)
In your template you could simply check each exam to be in this list.
{% for t in courses %}
<tr>
<td> {{t.course_name}}</td>
<td>
{% if t in student.exams_taken %}
<span> already taken </span>
{% else %}
<a class="btn btn-danger btn-xs" href="{% url 'take-exam' t.id %}"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
{% endif %}
</td>
{% endfor %}
have not tested the code and did a lot of assumtions to find a solution that fits your needs perfectly more Information as the definition of your current models could be helpful.
And make sure your exam view checks if the student has taken the exam from the database. Checking the cookies or hiding the button does not prevent "creative" people from taking the exam again.

Related

Pass Javascript Calculations to Django Backend

I have an HTML form where users type in the name of items and value corresponding to it in an input form, which is reflected when the form is submitted to Django backend.
In my HTML form I have included some Javascript so that the total of these values are reflected instantly without refreshing and even before submitting the form.
My goal:
Send the total amount calculated by Javascript in the HTML under id Total
<th scope="col">Total Equipment and Assets</th>
<th scope="col" id="Total"></th>
to the class in the
total_assets= models.IntegerField(null=True, blank=True, verbose_name='Total Assets')
in the Models.py after submitting.
Note that the reason for the question is that the total values are not manually added they are directly calculated using Javascript.
Here is a sample to make things more clear.
Here is the HTML Template:
<tr>
<td>
<input
placeholder="Type in the Equipment and assets"
type="text"
class="form-control"
name="item_1"
id="item_1"
{% if form.is_bound %}value="{{ form.item_1.value }}"{% endif %}/>
{% for err in form.item_1.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
<td>
<h6 style="float:left; margin-right:5px; margin-top:7px">$</h6>
<input
type="number"
class="form-control w-25 subtotal-group subtotal-group-1"
name="item_1_amount"
id="item_1_amount"
{% if form.is_bound %}value="{{ form.item_1_amount.value }}"{% endif %}/>
{% for err in form.item_1_amount.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
</tr>
<tr>
<td>
<input
placeholder="Type in the Equipment and assets"
type="text"
class="form-control"
name="item_2"
id="item_2"
{% if form.is_bound %}value="{{ form.item_2.value }}"{% endif %}/>
{% for err in form.item_2.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
<td>
<h6 style="float:left; margin-right:5px; margin-top:7px">$</h6>
<input
autocomplete="off"
type="number"
class="form-control w-25 subtotal-group subtotal-group-1"
name="item_2_amount"
id="item_2_amount"
{% if form.is_bound %}value="{{ form.item_2_amount.value }}"{% endif %}/>
{% for err in form.item_2_amount.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
</tr>
Here is the Javacript
<script>
const q=(e,n=document)=>n.querySelector(e);
const qa=(e,n=document)=>n.querySelectorAll(e);
const results={};
console. log(results)
qa('[type="number"].form-control').forEach(input=>input.addEventListener('input',function(e){
results[ this.name ]=Number( this.value );
const resultGroupSet1 = [...qa('.subtotal-group-1')]
.map(s => Number(s.value))
.reduce((a,v) => a+v);
q('th#Total').textContent = resultGroupSet1;
}));
</script>
Here is where the total is reflected in the HTML template
<thead class="table-light">
<tr>
<th scope="col">Total Equipment and Assets</th>
<th scope="col" id="Total"></th>
</tr>
</thead>
Here is the models.py
item_1 = models.CharField(max_length=100,null=True, blank=True, verbose_name='Item 1')
item_1_amount = models.IntegerField(null=True, blank=True, verbose_name='Item 1 Amount')
item_2 = models.CharField(max_length=100,null=True, blank=True, verbose_name='Item 2')
item_2_amount = models.IntegerField(null=True, blank=True, verbose_name='Item 2 Amount')
total_assets = models.IntegerField(null=True, blank=True, verbose_name='Total Assets')
Here is the views:
def add_bp(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = infoForm(request.POST)
# check whether it's valid:
if form.is_valid():
form.save()
b_name = form.cleaned_data.get('bName')
messages.success(request, f'PDF created for {b_name}!')
return redirect('application:core')
# if a GET (or any other method) we'll create a blank form
else:
form = infoForm()
return render(request, 'application/template.html', {'form': form, })
Update html to:
<thead class="table-light">
<tr>
<th scope="col">Total Equipment and Assets</th>
<th scope="col">
<!-- Value which is visible (calculated using JS) -->
<span id="Total"></span>
<!-- Add a hidden input to store value (value calculated and assigned using JS) -->
<input type="hidden" name="total_assets" value="0" id="total_assets">
</th>
</tr>
</thead>
Update script to assign resultGroupSet1 as:
textual content to the span tag with id=Total
value to the hidden input with name=total_assets
// Assign result to span tag which is visible
q('span#Total').textContent = resultGroupSet1;
// Assign result as value to hidden input field with name total_assets
q('input#total_assets').value = resultGroupSet1;
No other changes in views.
As an input field with a name="total_assets" is used, the value will be passed on to the request body and will be accessible at request.POST. Here, as the total_assets field is hidden it is not visible to the users and still the value is available in POST data when form is submitted. So, when form.save() is called the calculated value (using JS) will be saved.
I assumes your question is how to get the value in this element:
<th scope="col" id="Total"></th>
You can just simply add input element in your html code and add the name into it:
<th scope="col"><input id="Total" name="total_assets" value=""></th>
Then in your views.py:
def add_bp(request):
if request.method == 'POST':
form = infoForm(request.POST)
if form.is_valid():
form.save()
You can also manually get the Total:
def add_bp(request):
if request.method == 'POST':
total_assets = request.POST.get("total_assets")
Probably what you are looking for is <input type="hidden" ...>, it's not visible by the end user and it's included in the form submit
Why not do this calculation in Django Backend?
My suggestion is to pass all the arguments normally and just add a listener to the model saving (every time you will save an element to the table this little piece of code will run right before it saves it):
from django.db.models.signals import pre_save
from django.dispatch import receiver
#receiver(pre_save, model_class)
def form_pre_save(instance, *args, **kwargs):
instance.total_assets = instance.item_1_amount + instance.item_2_amount
This way when you want to save this kind of element in a different place (in the backend for example) you won't have to re-write the code that does that, but rather just save the instance.
You can read more about the signals pre_save function here

How to pass checkbox values to modal bootstrap for Python Flask remove data from mysql table?

Environment:
Python 3.7.7
Flask 1.1.2
Werkzeug 1.0.1
Introduction:
I am making a Flask application for my saas dashboard.
I have a page "categories.html" which displays a list of categories in a table.
Each category has a checkbox if the user wants to delete several categories by checking the categories and clicking on the "DELETE" button. See screenshot below:
So users will be able to select multiple categories and remove them by clicking on the "DELETE" button.
But before to delete the rows in Mysql table categories, a confirmation popup is showing up. This popup is done by Bootstrap modal.
Problem:
I don't how to pass the list of checkbox values selected by the user to the modal popup.
What did I try:
I tried to fix this issue with some javascript code, but it doesn't work.
My code:
My template categories.html (I removed unecessary code):
<form>
<table id="categories" class="table dataTable no-footer" role="grid">
<thead>
<tr role="row">
<th tabindex="0" rowspan="1" colspan="1" style="white-space: nowrap"></th>
</tr>
</thead>
<tbody>
{% for category in categories %}
<tr role="row" >
<td style="white-space: nowrap">
<input name="category_id" value="{{ category.ID }}" type="checkbox" class="form-check-input" style="float: left; margin: 0 auto;">
</td>
<td>{{ category.name }}</td>
<td style="white-space: nowrap">
{% if category.icon %}
{% if category.icon.find('<i class')!=-1 %}
{{ category.icon|safe }}
{% else %}
<img src="{{ url_for('static', filename='images/<category.icon>') }}">
{% endif %}
{% else %}
na
{% endif %}
</td>
</tr>
{% endfor %}
</tr></tbody>
</table>
</form>
<!-- Modal -->
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteModalLabel">Delete Category</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure you want to delete these categories?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<form action="{{ url_for('delete_category')}}" method="POST">
<input name="category_id" type="hidden" value="pass_checkedvalue" id="hidden_checkedinput">
<input class="btn btn-danger" type="submit" value="delete"/>
</form>
</div>
</div>
</div>
</div>
<script>
$('#deleteModal').on('show.bs.modal', function(e) {
var checkedValues = $('.record:checked').map(function(){ return this.value; }).get();
//put the ids in the hidden input as a comma separated string
$('#hidden_checkedinput').val(checkedValues.join(','));
});
</script>
My route.py:
#app.route('/delete_category', methods=['GET', 'POST'])
#login_required
def delete_category():
if request.method == "POST":
if request.form["category_id"]:
print(request.form["category_id"])
Category.query.filter(Category.ID.in_(request.form["category_id"])).delete()
db_mysql.session.commit()
flash('The categories have been deleted', 'success')
return redirect(url_for('categories'))
My models.py:
class Category(db_mysql.Model):
__tablename__ = "W551je5v_pb_categories"
ID = db_mysql.Column('ID', db_mysql.Integer, primary_key=True)
name = db_mysql.Column('name', db_mysql.Unicode)
icon = db_mysql.Column('icon', db_mysql.Unicode)
icon_blue_img = db_mysql.Column('icon_blue_img', db_mysql.Unicode)
icon_white_img = db_mysql.Column('icon_white_img', db_mysql.Unicode)
icon_black_img = db_mysql.Column('icon_black_img', db_mysql.Unicode)
platforms = db_mysql.relationship('Platform', backref='W551je5v_pb_categories', lazy=True)
def __repr__(self):
return f"Category('{self.ID}','{self.name}','{self.icon}','{self.icon_blue_img}','{self.icon_white_img}','{self.icon_black_img}')"
OUTPUT:
When I execute this code, I get this error message:
sqlalchemy.exc.InvalidRequestError
sqlalchemy.exc.InvalidRequestError: Could not evaluate current criteria in Python: "Cannot evaluate clauselist with operator <function comma_op at 0x0000026EB4542558>". Specify 'fetch' or False for the synchronize_session parameter.
And the print(request.form["category_id"]) showed in console:
pass_checkedvalue
Which is the value of my hidden field.
I have no idea what am I doing wrong. Can anyone help me, please?
I don't how to pass the list of checkbox values selected by the user to the modal popup.
I don't think that's the right approach.
Actually, I don't think you need to pass ANY data to the modal popup.
What I would instead do is add an on-click for the modal button that would run a javascript function.That function needs to simply iterate over the <tr> tags and find the checked rows.
After you have a list containing the checked rows' IDs, you can send that to your backend via some HTTP request (you can use Javascript's FETCH API for that).
Your code would like something like that (please treat this as a schema since I don't actually know how your HTML looks like):
let checked_arr = [];
let tr_lst = document.getElementsByTagName('tr'); // probably better to be done with getElementsByClassName
for (let i=0; i<tr_lst.length; i++) {
let checkbox_td = tr_lst[i].children[0]; // assuming first <td> is the checkbox
let checkbox_element = checkbox_td.children[0]; // assuming your HTML looks like <td><input type="checkbox"...></td>
if (checkbox_element.checked) {
checked_arr.push(tr_lst[i].id);
}
}
let response = await fetch('/your_api_endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify({"data": checked_arr})
});
Also, here is a nice tutorial on how to use FETCH API:
https://javascript.info/fetch
Hope that's helpful :)

How to call a function from python inside a html loop?

I am new to web coding... I was not able to find a good solution on my own. I need to add a function in my buttons and write the function in "application.py". I can't create a new html and I would prefer not to write a script in the html, if possible. The function should use the "i.stock" of the moment since it is inside a for loop. Any help is appreciated, thanks.
My html code:
{% extends "layout.html" %}
{% block head %}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet">
{% endblock %}
{% block title %}
Your Portfolio
{% endblock %}
{% block main %}
<h2> This is your current Portfolio:</h2>
<table class="table">
<thead class="thead-light">
<tr>
<th scope="col">Symbol</th>
<th scope="col">Name</th>
<th scope="col">Shares</th>
<th scope="col">Current Price</th>
<th scope="col">Total</th>
<th scope="col">Buy</th>
<th scope="col">Sell</th>
</tr>
</thead>
<tbody>
{% for i in portfolio %}
<tr>
<th scope="row">{{ i.stock_symbol }}</th>
<td>{{ i.stock_name }}</td>
<td>{{ i.stock_shares }}</td>
<td>{{ i.stock_price }}</td>
<td>{{ i.total_amount }}</td>
<td><a type="button" class="btn btn-success" onClick="buy()">+</a></td>
<td><a type="button" class="btn btn-danger">-</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<h4> Your currently have {{cash}} available in cash </h4>
<h4> Your Total (stocks + cash) is {{total}}</h4>
{% endblock %}
My python below [the part that matters, the def index is for the table]. The i.stock here does not work (obviously you may say) any suggestions on how to fix that?
Maybe I should create another #? I will need to refresh his portfolio once he buys another stock.
#app.route("/")
#login_required
def index():
"""Show portfolio of stocks"""
...
#Function to buy stocks directly from index
def buy():
cost = float(i.stock["price"])
#Looks in the datababse for the amount of cash the user still has
query = db.execute("SELECT cash FROM users WHERE id = :id", \
id=session["user_id"])
cash = query[0]["cash"]
#See if user has enough money and handle when user does not
if cost > cash:
return apology("You don't have enough money")
#Append information to the history table
db.execute("INSERT INTO history (user_id, stock_symbol, stock_price, stock_amount, total_amount) \
VALUES (:user_id, :stock_symbol, :stock_price, :stock_amount, :total_amount)", \
user_id = session["user_id"], stock_symbol = i.stock["symbol"], stock_price = usd(i.stock["price"]), stock_amount = 1, total_amount = cost)
#Calculates new cash amount and update database
net_cash = int(cash - cost)
db.execute("UPDATE users SET cash = :new_cash WHERE id = :id", \
id = session["user_id"], new_cash = net_cash)
You can't access Python functions in HTML. Instead, you send an AJAX request to the server. To do this, you need to modificate your buy-function:
import json
from flask import request
#app.route('/buy', methods=['POST'])
def buy():
i = json.loads(request.args.get('i'))
Now you can create the actual JavaScript-buy-function that will call the Python-buy-function:
function buy() {
var i = {}; // You need to get the details
var i_json = JSON.stringify(i);
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "/buy", true);
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log("Done.");
}
};
xhttp.send(i_json);
}
Now the only thing you have left to do, is passing all the necessary information (i) to the JS-buy-function.

Django the best way to create an edit modal form?

In one of my django app I have set the following architecture:
#models.py
class Income(models.Model):
price = models.DecimalField()
quantity = models.DecimalField()
date=models.DateField()
# forms.py
class IncomeForm(forms.ModelForm):
class Meta:
model = Income
fields = "__all__"
#views.py
def income_(request):
elements = Income.objects.all()
if request.method == 'POST':
form = IncomeForm(request.POST)
if form.is_valid():
new_input = form.save()
else :
form = IncomeForm()
elements = Income.objects.all()
context= {
'form': form,
'elements':elements,
}
return render(request, "income/income.html", context)
In my income.html file I have set the following
{% load crispy_forms_tags %}
<form id="" method="post">
<div class="form-group col-2 0 mb-0" >
{{form.quantity|as_crispy_field}}
</div>
<div class="form-group col-2 0 mb-0" >
{{form.price|as_crispy_field}}
</div>
<div class="form-group col-2 0 mb-0" >
{{form.date|as_crispy_field}}
</div>
</div>
After that I have created a table that list all data filled.
Now I want to create a button for each row that open a modal form that give me the possibility to modify the specific data for each id dataset.
I have tried to perform it with an ajax call, but I have had difficults to perform the form and the type of data (becouse in this manner I don't have the possibility to use crispy form or the forms model of the django framework).
So my question is: there is a simple way to achive my aim?
From what I understand from your question, you can try create a UpdateView in your view.py and redirect your html button with the object id to that view.
Updated answer-
since you are asking for simpler way implementing the edit page...
- models.py
class Income(models.Model):
price = models.DecimalField(decimal_places=2, max_digits=10000)
quantity = models.DecimalField(decimal_places=2, max_digits=10000)
date = models.DateField()
- urls.py
urlpatterns = [
path('income/', views.IncomeListView.as_view(), name='income'),
path('income_edit/<int:pk>', views.IncomeEdit.as_view(), name='income-edit'),
]
- views.py
class IncomeListView(ListView):
model = Income
template_name = 'income.html'
class IncomeEdit(UpdateView):
model = Income
form_class = IncomeForm
template_name = "income_form.html"
- forms.py
class IncomeForm(forms.ModelForm):
class Meta:
model = Income
fields = '__all__'
- income.html
<h1>Income List</h1>
<table>
<tr>
<th>ID</th>
<th>price</th>
<th>quantity</th>
<th>date</th>
</tr>
{% if income_list %}
{% for income in income_list %}
<tr>
<td>{{income.id}}</td>
<td>{{income.price}}</td>
<td>{{income.quantity}}</td>
<td>{{income.date}}</td>
<td>Edit </td>
</tr>
{% endfor %}
{% endif %}
</table>
- income_form.html
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
{{ form.media }}
</form>
please look into the class used for more information and understanding. hope this help =)

Flask does not return db query when I use the JS hide/unhide. Works if I comment out JS

I am trying to retrieve data from the database based on a users search results. The results, in a table format, should only be shown after the user hits the search button.
Query executes fine when javascript is cancelled out and the table "list" display is changed to block. However, when I enable the javascript I get no results.
<div style="text-align: center;">
{% from "_formhelpers.html" import render_field %}
<form method=post action="/">
<dl style="display: inline-block; text:white;" >{{render_field(form.search)}} </dl>
<button id="searchbutton" type="submit" style="display: inline-block;" class="btn btn-outline-success my-2 my-sm-0" onclick="fetchlist(); return false;">Search</button>
<br>
{% if error %}
<p class = "error"><strong>Error:</strong>{{error}}</p>
{% endif %}
</form>
</div>
<div style="text-align:center;">
<table id="list" style="display:none;" class = "table table-hover" >
<thead>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Rating</th>
<th scope="col">Review</th>
</thead>
<tbody>
{% for row in data %}
<tr>
{% for d in row %}
<td>{{ d }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
<script>
function fetchlist() {
if (document.getElementById('searchbutton').onclick) {
document.getElementById('list').style.display = 'inline';
}
else document.getElementById('list').style.display = 'inline';
}
</script>
{% endblock %}
</html>
#app.route('/', methods=['GET', 'POST'])
def homepage():
try:
form=SearchForm(request.form)
global d1
d1 =""
if request.method == "POST" and form.validate():
search = form.search.data
a = search.split(" ",1)
firstname, lastname = (a[0], a[1])
c,conn = connection()
qry = "SELECT FirstName, LastName FROM posts WHERE FirstName LIKE (%s) AND LastName like (%s)"
c.execute(qry, ((thwart(firstname)), (thwart(lastname))))
d1 = c.fetchall()
c.close()
conn.close()
else: print('error')
return render_template("index.html", data=d1, form = form)
except Exception as e:
return(str(e))
As you already know the problem is caused by your JS. This is because the JS is waiting for the search button to be clicked before it changes the style of the list to inline.
This all seems fine, but the problem comes in the fact that the JS is executed when the button is clicked. But then the request is posted to the server and a new page is sent to the browser with the search results. However, this new page the search button has never been clicked.
You can fix writing the method to display the results into your template. For instance you could wrap the table in an if statement like this...
{% if data|length %}
<div style="text-align:center;">
<table id="list" style="display:none;" class = "table table-hover" >
<thead>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Rating</th>
<th scope="col">Review</th>
</thead>
<tbody>
{% for row in data %}
<tr>
{% for d in row %}
<td>{{ d }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table
</div>
{% endif %}
The |length filter makes sure data is not an empty string. Otherwise I believe it may always be true. You could try {% if data %} to double check. It may work.
There are a lot more options....
You could wrap you <script> in the if statement. You should modify it a little. So it does not wait of the search button to be clicked.
You could wrap the inline style in the if statement. Of course you could use CSS classes instead of inline styling. This would be cleaner.

Categories

Resources