68273

Python/Flask: How to tell how long a user spends on a page? (Data entry/time log app)

I have seen answers to see how long a user spends on a page using Javascript, but my knowledge of JS is lacking (much less integrating JS into my Python/Flask framework).

My objective is to create a web application that users can enter data into, while the time spent (both duration and what time during the day) doing the task is recorded.

I am using Python, Flask, WTForms, and SQLAlchemy for most of the functionality. From my views.py file, I have this configured:

@app.route('/logpage', methods=['GET', 'POST']) @login_required def logpage(): form = LogForm() if form.validate_on_submit(): entry = LogData(sessionid=form.sessionid.data, user_id=current_user.get_id(), endtime=datetime.utcnow()) db.session.add(entry) db.session.commit() return redirect(url_for('home')) return render_template('logpage.html', form=form)

When the user hits submit, the Session ID, the user's ID, and the endtime is recorded to a PostgreSQL server. I tried setting pageload = datetime.utcnow() before the form validation in hopes it would store the time the page loaded, but it seems to save the same time as end time.

I was trying to figure out a way to write the current date time to the SQL entry/row and entering to the same row when the form validates, but I am unaware of how to write to the same row twice. Perhaps something with the primary key and linking them? I will continue to investigate this.

I would like a way to save the datetime this page loads so it can be compared to the time the form is submitted. Is there a straightforward way to accomplish this without javascript?

Answer1:

You can use a Flask session to track the start time. It's implemented on top of browser cookies.

http://flask.pocoo.org/docs/0.12/quickstart/#sessions

You need to implement a secret key for the app (as shown in the quickstart example), and then you can use the session object as a key value store for user-specific information.

For your particular use case, it might be something like:

@app.route('/logpage', methods=['GET', 'POST']) @login_required def logpage(): form = LogForm() if form.validate_on_submit(): entry = LogData(sessionid=form.sessionid.data, user_id=current_user.get_id(), starttime=session.pop('start_time', None), endtime=datetime.utcnow()) db.session.add(entry) db.session.commit() return redirect(url_for('home')) session['start_time'] = datetime.utcnow() return render_template('logpage.html', form=form)

pageload = datetime.utcnow() before the form validation didn't work because:

    <li>this variable would be local to the scope of the function and wouldn't persist after the function completes</li> <li>even if the variable weren't local to the scope of the function call, the same function is being called for both GET and POST, so it would be overridden when the user posts the form</li> </ul>

    One more thing to be aware of is that you can't trust the user to be using cookies or to allow JavaScript, so you should consider how your program would handle null start times in the database.

Recommend

  • To write a query to display records for last 15 minutes of sessions in the log file
  • Show Woocommerce taxonomy in emails
  • chromium not opening full URL when started with os.system (py)
  • ADO functionality.. copy, filter, paste from closed workbook to active wrokbook
  • Cannot consume scoped service 'MyDbContext' from singleton 'Microsoft.AspNetCore.Host
  • Send CTRL_C/SIGINT to a process from C#
  • flask-login user is set to anonymous after login
  • InProc session data disapearing
  • Sending commands to stdin and sending end of transmit (Ctrl+D)
  • How to filter results with Ransack
  • converting curl call to python requests
  • SoX running slow using a ProcessBuilder
  • current user id saved from _form or controller
  • View Azure WebJob Schedule in Portal?
  • Azure Media Services Shared Access Policy limitations
  • Embedded or referenced relations
  • LINQ to Entities does not recognize the method 'Int64 Max(Int64, Int64)' method, and this
  • How to set infinite shared access signature policy in azure?
  • How to access recipient on sent messages page with mailboxer
  • How to Add Polymorphic Comments to Feed?
  • DateTime.Today for a specific time zone
  • User messaging system
  • Programmatically access files in Document set in sharepoint using Javascript
  • Laravel: Getting Session ID oddly truncates when using foreach
  • How can I extract results of aggregate queries in slick?
  • Needing to do .toArray() to get output of mongodb .find() on key name not value
  • ActiveRecord query for a count of new users by day
  • MongoDB in PHP using aggregate to group by _id is null not working
  • FB SDK and cURL: Unknown SSL protocol error in connection to graph.facebook.com:443
  • Illegal mix of collations for operation for date/time comparison
  • How to make a tree having multiple type of nodes and each node can have multiple child nodes in java
  • How to limit post in wp_query
  • AngularJs get employee from factory
  • Acquiring multiple attributes from .xml file in c#
  • Free memory of cv::Mat loaded using FileStorage API
  • Memory offsets in inline assembly
  • Turn off referential integrity in Derby? is it possible?
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • How can I use threading to 'tick' a timer to be accessed by other threads?
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize