UndefinedError: 'flask_paginate.Pagination object' has no attribute 'skip' - python

I am trying to paginate data coming from backend using flask_paginate. I followed, https://pythonhosted.org/Flask-paginate/ to get it implemented.
My view -
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset="utf-8" />
<title>AT - Monitoring System</title>
</head>
<body>
{{ pagination.info }}
{{ pagination.links }}
<table id="myTable">
<thead>
<tr>
<th>Sector ID</th>
<th>Username</th>
<th>Password</th>
<th>Camera Name</th>
<th>Camera ID</th>
<th>Recording status</th>
</tr>
</thead>
<tbody>
{% for each in response %}
<tr>
<td>{{ loop.index + pagination.skip }}</td>
<td>{{each[0]}} </td>
<td>{{each[1]}} </td>
<td>{{each[2]}}</td>
<td>{{each[3]}}</td>
<td> {{each[4]}}</td>
<td>{{each[5]}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ pagination.links }}
</body>
</html>
Python Code -
APP = flask.Flask(__name__)
#APP.route('/', methods=['GET', 'POST'])
def index():
""" Displays the index page accessible at '/'
"""
search = False
q = request.args.get('q')
if q:
search = True
page = request.args.get('page', type = int, default = 1)
pagination = Pagination(page=page, total=len(Backend()), search=search, record_name='response')
if request.method == 'GET':
return flask.render_template('index.html',
response = data,
pagination = pagination
)
if __name__ == '__main__':
data = Backend()
Thread(target=main_loop).start()
APP.debug=True
APP.run(port=63000)
I tried to find documentation which shows me the usage of pagination.skip(), but can't find anything. On removing this function, I see the no. of pages on my browser, but on content is not displayed as per the page nos. There is definitely something, I am missing big time. The other examples online are very different to the example mentioned in https://pythonhosted.org/Flask-paginate/

Related

Handling WTF form With for Loop correctly

Hello all I am new to flask I am just creating a basic table with DB data as S.no & Name & filling this with some random data of 10 users , Now I am query Db & displaying this list on HTML page in a table , on the HTML page I have added an extra column which takes input from WTF form Select field with option as YES & NO & Pending now the issues I am getting is on the HTML page select column If I select Yes as option & submit all other below row are getting this value , similarly If I select Pending On first & submit all row get pending How can I fix this kindly pardon my english
# for wtf-forms
class inputform(FlaskForm):
userinput = SelectField(choices=[('Yes'), ('No'),('Pending')])
Submit = SubmitField(label="Click to Submit")
#route
#app.route('/', methods=['GET', 'POST'])
def index():
form = inputform()
dbdata = mydb.query.all()
if form.validate_on_submit():
usernameinput = form.userinput.data
print(f"usernameinput {usernameinput}")
return render_template('index.html', userdata=dbdata, form=form)
On HTML
<form action="" method="post">
{{ form.hidden_tag() }}
<table class="table table-bordered ">
<thead>
<tr>
<th class="">S.No</th>
<th class="">name</th>
<th class="">Select</th>
</tr>
</thead>
<tbody>
{% for x in userdata %}
<tr>
<td>{{loop.index}}</td>
<td>{{x.user_name}}</td>
<td>{{form.userinput}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{form.Submit()}}
</form>

Duplicate HTML header when using JQuery/AJAX to add new data to a table without page refresh?

I referenced this stack overflow to do away with page refreshing and use ajax/JQuery to update only the table when new data came in. However, I am getting a weird bug. My HTML header for the website is being duplicated, present once at the top of my page and again right above my table with the border extending above it, almost as if it's in the table- see the attached image of my site: A screenshot of a table-based website that has duplicate titles. I've tried moving the header up to the head part of the HTML and that changed nothing, as well as removing it entirely to no success. It's only in my HTML code once so I figure it might be something wrong with the JQuery/ajax side of things but I'm new to these so I don't know how to trouble shoot. Any help would be appreciated! Here's some of my code:
ftp.html
<html>
<head>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'ssheet.css'%}" >
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<title>FTP Stats Table</title>
</head>
<body>
<h2>Ftp Stats Table</h2>
<form action='deletef' method='GET'>
<button type='submit'>Clear table</button>
</form>
<table id="_appendHere2" class="tb" border="1">
<tr>
<th>Src_Fname</th>
<th>Dest_Fname</th>
<th>Bytes_Xfer</th>
<th>Xfer_Sec</th>
<th>Xfer_MBPS</th>
</tr>
{% for ftp in filetp %}
<tr>
<td>{{ ftp.Src_Fname }}</td>
<td>{{ ftp.Dest_Fname }}</td>
<td>{{ ftp.Bytes_Xfer }}</td>
<td>{{ ftp.Xfer_Sec }}</td>
<td>{{ ftp.Xfer_MBPS }}</td>
</tr>
{% endfor %}
</table>
</body>
<script>
$(document).ready(function () {
var append_increment = 0;
setInterval(function(){
$.ajax({
type: "GET",
url: "{% url 'ftprefresh' %}",
data: {'append_increment': append_increment}
})
.done(function(responses){
$('#_appendHere2').html(responses);
append_increment += 10;
})
}, 1000)
})
</script>
</html>
views.py (not including my delete function since it works fine and isn't involved in this)
def ftptable(request):
filetp = FTP.objects.all() #assigns filetp with all of the current objects of ftp
return render(request,'ftp.html',{'filetp':filetp}) #passes filetp object to the table generating html
#parses data from ftp post request
def ftpin(request):
if request.method == 'POST':
ftppost = FTP() #creates new ftp object
rawpost1 = request.body #retrieves post message
stringpost1 = str(rawpost1, "utf-8") #puts raw message into string
if( not stringpost1 or (stringpost1.split(' ',1)[0] != "COMPLETE")):
return HttpResponse()
stringpost1 = stringpost1.split(' ', 1)[1] #takes off the first object
ftplist = stringpost1.split() #splits new string into list
ftppost.Src_Fname = ftplist[0] #populates new object
ftppost.Dest_Fname = ftplist[1]
ftppost.Bytes_Xfer = ftplist[2]
ftppost.Xfer_Sec = ftplist[3]
ftppost.Xfer_MBPS = ftplist[4]
ftppost.save() #saves new object to database
return HttpResponse()
def ftprefresh(request):
increment = int(request.GET['append_increment'])
increment_to = increment + 10
ftpt = Ingest.objects.order_by('-id')[increment:increment_to]
return render(request, 'ftp_table_refresh.html', {'ftpt':ftpt})
and lastly, ftp_table_refresh.html
{% load static %}
{% for ftp in ftpt %}
<tr>
<td>{{ ftp.Src_Fname }}</td>
<td>{{ ftp.Dest_Fname }}</td>
<td>{{ ftp.Bytes_Xfer }}</td>
<td>{{ ftp.Xfer_Sec }}</td>
<td>{{ ftp.Xfer_MBPS }}</td>
</tr>
{% endfor %}
If it's necessary I can include my urls.py, but they look exactly how you would expect and function perfectly fine.

Access these dictionary values in flask template

My Template is outputting the below. It doesnt pull in any of the queried values, but the page loads fine and doesnt fail, but it doesnt show any of the values.
I double checked the query in a mysqlmonitor, and it pulls 3 records as it should.
<li></li>
In the templates/index.html I have:
{% for blogpost in blogposts %}
<li>{{blogpost[0]}}</li>
{% else %}
<li>no blog posts right now...</li>
{% endfor %}
app.py has this:
import pymysql.cursors
app = Flask(__name__)
connection = pymysql.connect(host='localhost', user='myuser', port=3306, password='mypass', db='mydb', charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor)
#app.route('/', methods=('GET', 'POST'))
def email():
form = EmailForm()
curs = connection.cursor()
curs.execute("SELECT post_title, post_name, YEAR(post_date) as YEAR, MONTH(post_date) as MONTH FROM mydb.wp_posts WHERE post_status='publish' ORDER BY RAND() LIMIT 3")
blogposts = curs.fetchall()
if request.method == 'POST':
return render_template('index.html', form=form, blogposts=blogposts)
if __name__ == '__main__':
app.run()
UPDATE I think my for() is not working correctly, because when i update in the template i get all the data like:
[{u'MONTH': 12, u'YEAR': 2016, u'post_name': u'data is here', u'post_title': u'data is here'},
{u'MONTH': 12, u'YEAR': 2016, u'post_name': u'data is here', u'post_title': u"data is here"}]
How can i access this data in my flask template ?
Thank you so much!
Try finding out what is being sent to the template. Add print(blogposts) to the email function - just below the if request.method == 'POST': line and see what information it gives you.
If blogposts is a list of dictionaries, then you cannot access them by number. You need to use the name of the key. For example, you will need to change blogpost[0] to blogpost['name']. With Flask's templates you can also use the dot notation, so the blogpost name would become blogpost.name.
#app.route('/get', methods=['POST','GET'])
def requestCustomerDataFromTestForm():
data={'id':1, 'name':'Josh'}
return render_template("index.html", data = data)
In index.html
{% if data %}
<h1>{{data['id']}}</h1>
<h1>{{data['name']}}</h1>
{% endif%}
Or.. you can also iterate
<table class="table table-striped" >
<thead>
<tr>
<th scope="col">id</th>
<th scope="col">name</th>
</tr>
</thead>
<tbody>
{% for key, value in data.items() %}
<tr>
<th scope="row">{{ key }}</th>
<td>{{ value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
Or, to display all data with their index
{% if data %}
<p>{{data}}</p>
{% endif %}

Render an editable table using Flask, Jinja2 templates, then process the form data returned

I'm using Flask and Jinja2 and I need to make an editable table with multiple rows.
This is what the table will look like:
And here's HTML for that:
<form action="/support/team-members-update" method="post">
<table>
<tbody><tr>
<th>Name</th>
<th>Id</th>
<th>Inbox Share</th>
</tr>
<tr>
<td>Ben</td><td>55555</td><td><input type="text" name="share_55555" value="0"></td></tr> <tr>
<td>Steve</td><td>66666</td><td><input type="text" name="share_66666" value="1"></td></tr> <tr>
<td>Harry</td><td>77777</td><td><input type="text" name="share_77777" value="1"></td></tr> <tr>
<td>Sally</td><td>88888</td><td><input type="text" name="share_88888" value="1"></td></tr></tbody></table>
<button type="submit">Send</button>
</form>
My current implementation is in Lua, where I'm hard coding a bunch of strings and connecting up the post data to native Lua types by hand (fun!). If I have to, I can process the form data by hand in Python as well, but I imagine there's probably a better solution out there.
I have explored WTForms a bit, but haven't had much luck getting it to work correctly.
I did find FieldList, but that seems to deal with a list of the same field, not multiple rows with the same exact fields.
I also found TableWidget, but the documentation is sparse and I can't figure out how to implement it to know if that would do what I'm looking to do.
FieldList will work, you need to make a list of a FormField. Specify your FormField like so:
class MemberForm(Form):
name = StringField('name')
member_id = StringField('member_id')
inbox_share = IntegerField('inbox_share')
# etc.
class TeamForm(Form):
title = StringField('title')
teammembers = FieldList(FormField(MemberForm))
Then you can create the forms from your database in a view function like so:
#app.route('/support/team-members-update', methods=['GET','POST'])
def update_team_members():
teamform = TeamForm()
teamform.title.data = "My Team" # change the field's data
for member in DB.get('teammembers') # some database function to get a list of team members
member_form = MemberForm()
member_form.name = member.name # These fields don't use 'data'
member_form.member_id = member.id
member_form.inbox_share = member.share
teamform.teammembers.append_entry(member_form)
return render_template('edit-team.html', teamform = teamform)
And then in the template, you can iterate over each item in teammembers as you create your table rows:
<html>
<head>
<title>Edit Team Members</title>
</head>
<body>
<h1>Edit Team</h1>
<div>
<form action="" method="post" name="teamform">
{{ teamform.hidden_tag() }}
Team Title: {{ teamform.title }}<br>
<div>
<table>
<tr>
<th> Name </th>
<th> ID </th>
<th> Inbox Share </th>
</tr>
{% for member in teamform.teammembers %}
<tr>
<td>{{ member.name }}</td>
<td>{{ member.member_id }}</td>
<td>{{ member.inbox_share }}</td>
</tr>
{% endfor %}
</table>
</div>
<p><input type="submit" name="edit" value="Send"></p>
</form>
</div>
</body>
</html>
I never was able to get WTForms to work quite how I wanted. I think it was a bit too heavy for my needs, so I ended up just using my own Jinja2 template to build the form and then used the formencode library to parse the post variables into a dict. This works well enough for me. (Thanks to this question for pointing me to the formencode library).
I'll give you a rough look at the various files I'm using and then explain the important parts at the bottom:
app.py:
from flask import Flask, render_template, request
from formencode import variabledecode
import pickledb
app = Flask(__name__)
DB = pickledb.load('data/data.db', False)
#app.route('/team-members', methods=['GET', 'POST'])
def team_members():
global DB
teammembers = DB.get('teammembers')
# teammembers looks like this, roughly:
# [{"id": 55555, "name": "Ben", "share": 0},
# {"id": 66666, "name": "Amy", "share": 1},
# {"id": 77777, "name": "Ted", "share": 1}]
if request.method == 'POST':
postvars = variabledecode.variable_decode(request.form, dict_char='_')
for k, v in postvars.iteritems():
member = [m for m in teammembers if m["id"] == int(k)][0]
member['share'] = v["share"]
DB.set('teammembers', teammembers)
DB.dump()
return render_template('team-members.html', teammembers=teammembers)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--debug', '-d', action='store_true')
parser.add_argument('--port', '-p', default=5000, type=int)
parser.add_argument('--host', default='0.0.0.0')
args = parser.parse_args()
app.run(args.host, args.port, debug=args.debug)
I have three template files, but you of course don't need this many. team-members.html has the code that's relevant to this problem.
_formhelpers.html:
{% macro render_input(id, fieldname, value) %}<input type="text" name="{{ id }}_{{ fieldname }}" value="{{ value }}" />{% endmacro %}
layout.html:
<!doctype html>
<html>
<head>
<title>Support Team Site</title>
</head>
<body>
<div class="page">
<h1>Support Team Site</h1>
{% for message in get_flashed_messages() %}
<div class=flash>{{ message }}</div>
{% endfor %}
{% block body %}{% endblock %}
</div>
</body>
</html>
team-members.html:
{% from "_formhelpers.html" import render_input %}
{% extends "layout.html" %}
{% block body %}
<form action="/team-members" method="post">
<table>
<tr>
<th>Name</th>
<th>ID</th>
<th>Inbox Share</th>
</tr>
{% for member in teammembers %}
<tr>
<td>{{member['name']}}</td>
<td>{{member['id']}}</td>
<td>{{ render_input(member['id'], 'share', member['share']) }}</td>
</tr>
{% endfor %}
</table>
<button type="submit">Send</button>
</form>
{% endblock %}
This will render the following HTML:
<!doctype html>
<html>
<head>
<title>Support Team Site</title>
</head>
<body>
<div class="page">
<h1>Support Team Site</h1>
<form action="/team-members" method="post">
<table>
<tr>
<th>Name</th>
<th>ID</th>
<th>Inbox Share</th>
</tr>
<tr>
<td>Ben</td>
<td>55555</td>
<td><input type="text" name="55555_share" value="0" /></td>
</tr>
<tr>
<td>Amy</td>
<td>66666</td>
<td><input type="text" name="66666_share" value="1" /></td>
</tr>
<tr>
<td>Ted</td>
<td>77777</td>
<td><input type="text" name="77777_share" value="1" /></td>
</tr>
</table>
<button type="submit">Send</button>
</form>
</div>
</body>
</html>
It's worth mentioning what's going on in the if request.method == 'POST': part of app.py. The request.form variable will be of type ImmutableMultiDict, which would look kind of like this when printed out:
ImmutableMultiDict([('55555_share', u'0'), ('66666_share', u'1'), ('77777_share', u'1')])
This is somewhat useful, but we'd still have to parse this by hand to do anything with it. Note the format of the keys there, in the id_fieldname format (e.g. 55555_share). This was thanks to the render_input macro we put in our _formhelpers.html template file. When we process the post form input, we use variabledecode.variable_decode(request.form, dict_char='_'), which parses the form data and turns it into a dictionary based on the naming convention we used for the name values of the form inputs. Here's what it looks like:
{
"55555": {
"share": "0"
},
"66666": {
"share": "1"
},
"77777": {
"share": "1"
}
}
This makes it easy to map back to our original data and update it.

How can i submit data in django?

I want to have 3 pages. The one displays certain usernames of a certain directory which is called "static" (you will see it in my views.py). And if the user wants to add a user, he presses on one of the 2 "Add" buttons.. if he does that he is getting to the second page where he can type in username and password and can confirm it with the "Submit" button. Then the data should be saved in the "static" folder. After that he is getting directed to another site where it says "registration successful" and after 3 seconds he is getting back to the index.html to see the results. In the django documentation, I think they do almost the same just in another way xP https://docs.djangoproject.com/en/1.5/intro/tutorial04/ I just don't get how I can assign their example to my project :/
Her are my views:
from django.shortcuts import render
import os
def index(request):
os.chdir("/home/ubuntu/newproject/static")
files = []
for file in os.listdir("."):
files.append(file)
return render(request, 'sslcert/index.html', dict(files = files))
def adduser(request):
return render(request, 'sslcert/adduser.html')
def redirect(request):
return render(request, 'sslcert/redirect.html')
This is the template for the first website:
<head>
{% block title %}
<h3>
Following users exist in the folder 'static' :
</h3>
{% endblock %}
</head>
<body>
<table border = "0" width = "100%" align = "left">
<tr>
<td align = "right">
<form action = "adduser.html" method = "post">{% csrf_token %}
<input type = "submit" name = "form" style = "width:8%" value = "Add">
</td>
</tr>
{% for file in files %}
<tr>
<td align = "left"> {{ file }} </td>
</tr>
{% endfor %}
<tr>
<td align = "right">
<form action = "adduser.html" method = "post">{% csrf_token %}
<input type = "submit" name = "form" style = "width:8%" value = "Add">
</form>
</td>
</tr>
</table>
</body>
And this is the template for my second website:
<head>
{% block title %}
<h2 align = "middle" >
<u>Add a user</u>
</h2>
{% endblock %}
</head>
<body>
<table border = "0" width = "100%">
<tr>
<td>
<p>Username:</p>
<input type = "text" name = "" value = "" />
</td>
</tr>
<tr>
<td>
<p>Password:</p>
<input type = "password" name = "" value = "" />
</td>
</tr>
<tr>
<td>
<form action = {% url 'sslcert:redirect' %} method = "post"> {%csrf_token %}
<input type = "submit" value = "Submit">
</form>
</td>
</tr>
</table>
</body>
And this is the template for the redirect site:
<head>
<meta http-equiv = "refresh" content = "3; URL=http://10.0.3.79:8000/sslcert/">
{% block title %}
<h4>
Registration successful !
</h4>
{% endblock %}
</head>
I read the documentation and I found this code example:
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from polls.models import Choice, Question
# ...
def vote(request, question_id):
p = get_object_or_404(Question, pk=question_id)
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': p,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(p.id,)))
I thought that this Line might be helpful:
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
but I really don't know how to assign this to my project :/ I already created 2 classes in the models with the names: "Username" and "Password". Please guys help me out :(
Help is much appreciated :)
Well, when the browser first gets the form to fill up, you're sending a GET request. Otherwise, if you send information to the server, you need to send a POST request. Take a look at the documentation.
Okay I found the answer myself ... It is frustrating that I wasted so much time on this but I was kind of blind xP in my adduser.html (the second page) I had my just around the submit button ... the only thing that got submitted was the csrf_token. Now it looks like this and it submits the Username and the Password as well:
<!DOCTYPE html>
<html>
<head>
{% block title %}
<h2 align = "middle" >
<u>Add a user</u>
</h2>
{% endblock %}
</head>
<body>
<form action = "{% url 'sslcert:redirect' %}" method = "post">{% csrf_token %}
<table border = "0" width = "100%">
<tr>
<td>
<p>Username:</p>
<input type = "text" name = "username" value = "" />
</td>
</tr>
<tr>
<td>
<p>Password:</p>
<input type = "password" name = "password" value = "" />
</td>
</tr>
<tr>
<td>
<input type = "submit" value = "Submit">
</td>
</tr>
</table>
</form>
</body>
</html>
And I changed my views.py like this:
from django.shortcuts import render
import os
def index(request):
os.chdir("/home/ubuntu/newproject/static")
files = []
for file in os.listdir("."):
files.append(file)
return render(request, 'sslcert/index.html', dict(files = files))
def adduser(request):
return render(request, 'sslcert/adduser.html')
def redirect(request):
username = request.POST['username']
password = request.POST['password']
print username
print password
return render(request, 'sslcert/redirect.html')

Categories