A tutorial on the implementation of data visualization in Python's tornado framework

Source: Internet
Author: User
Tags character set current time date1 datetime in python
This article mainly introduces a tutorial to explain data visualization in the Tornado framework of Python. Tornado is an asynchronous and highly popular development framework. Friends who need it can refer to

Expansion Module Used

    xlrd:

    Python extension tool for reading Excel. Can read the specified form and the specified cell.
    Must be installed before use.
    Download address: https://pypi.python.org/pypi/xlrd
    After decompression, cd to the decompression directory and execute python setup.py install

    datetime:

    Python has built-in modules for manipulating dates and times

Function module to be implemented

    Read xls file and enter database

    Obtain the duty status of the day according to the three parameters of year, month and day

        Pie chart (number of people who completed the task on the day / number of people who did the task on the day)

        Waterfall chart (the duty situation of all the staff on the day)

    Get the duty status of the current month based on the year and month parameters

    Obtain the duty status of the current year according to the annual parameters

Duty system

    There are 6 classes a day:

    8:00-9:45
    9:45-11:20
    13:30-15:10
    15:10-17:00
    17:00-18:35
    19:00-22:00

    Everyone is up to one shift per day.

    Only valid on duty and within half an hour before and after.

    You must check in at work and off time, and the absence of check in is considered unattended.

Analyze Excel Sheets

My Fingerprint Time Attendance Device can export the punch-in records for up to one month at a time. One problem is that this month may span two months or a year. For example: March 21, 2015-April 20, 2015, December 15, 2014-January 05, 2015. So pay attention to this pit when writing the processing method.

The exported table is shown in the figure:




    =. = It looks like almost no one on duty, yes, that's it.
    Everyone is so lazy. T
    Sign ...

A brief analysis,

    Attendance record sheet is the third sheet of the file
    The third line has the start and end time
    The fourth line is the number of all dates
    The next two lines: the first line of user information; the second line of attendance records
Ideas

Decided to use 3 collections to store relevant information:

    user: user information, including id, name, dept
    record: attendance record, including id (user id), y (year), m (month), d (day), check (time card record)
    duty: duty arrangement, including id (week number, example: 1 for Monday), list (duty staff id list), user_id: ["start_time", "end_time"] (user start and end time)
Read the xls file and save the new attendance records and new users into the database.

Query the corresponding record according to the year, month, and day parameters, and query the day's duty arrangement to match and obtain the attendance records of the students on duty on that day. Compare the check-in time of the classmates on duty with the time on duty, determine whether the time is normal, and calculate the actual duty time and the actual duty percentage.

After outputting the data in json format, use echarts to generate charts.

Analyzing the attendance records for the current month and year is similar, but it may be slightly more complicated.

    All explanations and specific ideas are placed in the source code comments, please continue to look at the source code ~

Source code

main.py

#! / usr / bin / env python
#-*-coding: utf-8-*-
import os.path

import tornado.auth
import tornado.escape
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define, options

import pymongo
import time
import datetime
import xlrd

define ("port", default = 8007, help = "run on the given port", type = int)

class Application (tornado.web.Application):
  def __init __ (self):
    handlers = [
      (r "/", MainHandler),
      (r "/ read", ReadHandler),
      (r "/ day", DayHandler),
    ]
    settings = dict (
      template_path = os.path.join (os.path.dirname (__ file__), "templates"),
      static_path = os.path.join (os.path.dirname (__ file__), "static"),
      debug = True,
      )
    conn = pymongo.Connection ("localhost", 27017)
    self.db = conn ["kaoqin"]
    tornado.web.Application .__ init __ (self, handlers, ** settings)


class MainHandler (tornado.web.RequestHandler):
  def get (self):
    pass

class ReadHandler (tornado.web.RequestHandler):
  def get (self):
    #Get collection
    coll_record = self.application.db.record
    coll_user = self.application.db.user
    #Read excel form
    table = xlrd.open_workbook ('/ Users / ant / Webdev / python / excel / data.xls')
    #Read punch card record sheet
    sheet = table.sheet_by_index (2)
    #Read the punch month range
    row3 = sheet.row_values (2)
    m1 = int (row3 [2] [5: 7])
    m2 = int (row3 [2] [18:20])
    #Set the current year
    y = int (row3 [2] [0: 4])
    #Set the current month as the first month
    m = m1
    #Read punch-in date range
    row4 = sheet.row_values (3)
    #Initialize the previous day
    lastday = row4 [0]
    #Iterate through the dates in the fourth line
    for d in row4:
      #If the date is less than the previous date
      #Explanation month increases, then modify the current month to the second month
      if d <lastday:
        m = m2
        #If the current two months are December and January
        # DESCRIPTION New Year, so the year +1
        if m1 == 12 and m2 == 1:
          y = y + 1
      #Count with n, range from 3 to (total number of lines / 2 + 1)
      # (Total Lines / 2 + 1)-3 = Total Users
      #Ie traverse all users
      for n in range (3, sheet.nrows / 2 + 1):
        #Take the first line of the user, that is, the user information line
        row_1 = sheet.row_values (n * 2-2)
        #Get user id
        u_id = row_1 [2]
        #Get user name
        u_name = row_1 [10]
        #Get user department
        u_dept = row_1 [20]
        #Query the user
        user = coll_user.find_one ({"id": u_id})
        #If the user does not exist in the database then create a new user
        if not user:
          user = dict ()
          user ['id'] = u_id
          user ['name'] = u_name
          user ['dept'] = u_dept
          coll_user.insert (user)
        #Take the second line of the user, which is the attendance record line
        row_2 = sheet.row_values (n * 2-1)
        #Get the index of the current date
        idx = row4.index (d)
        #Get the attendance record of the current user's current date
        check_data = row_2 [idx]
        #Initialize empty attendance record list
        check = list ()
        # 5 character set, traverse attendance record and save it to attendance record list
        for i in range (0, len (check_data) / 5):
          check.append (check_data [i * 5: i * 5 + 5])
        #Query the current user's day record
        record = coll_record.find_one ({"y": y, "m": m, "d": d, "id": user ['id']})
        #Update record if record exists
        if record:
          for item in check:
            #Add new attendance record to previous record
            if item not in record ['check']:
              record ['check']. append (item)
              coll_record.save (record)
        #Insert a new record if the record does not exist
        else:
          record = {"y": y, "m": m, "d": d, "id": user ['id'], "check": check}
          coll_record.insert (record)


class DayHandler (tornado.web.RequestHandler):
  def get (self):
    #Get year, month, and day parameters
    y = self.get_argument ("y", None)
    m = self.get_argument ("m", None)
    d = self.get_argument ("d", None)
    #Judging whether the parameters are fully set
    if y and m and d:
      #Convert parameters to integers for easy use
      y = int (y)
      m = int (m)
      d = int (d)
      #Get all records for the day
      coll_record = self.application.db.record
      record = coll_record.find ({"y": y, "m": m, "d": d})
      #Get the day of the week
      weekday = datetime.datetime (y, m, d) .strftime ("% w")
      #Get the watch on the day
      coll_duty = self.application.db.dutyduty = coll_duty.find_one ({"id": int (weekday)})
      #Initialize empty target records (records of personnel on duty on that day)
      target = list ()
      #Iterate through all records for the day
      for item in record:
        #When the user of this record has an on-duty task for the day, calculate and store it in the target array
        if int (item ['id']) in duty ['list']:
          #Get the user's start and end time by user id
          start = duty [item ['id']] [0]
          end = duty [item ['id']] [1]
          #Calculate duty time / second
          date1 = datetime.datetime (y, m, d, int (start [: 2]), int (start [-2:]))
          date2 = datetime.datetime (y, m, d, int (end [: 2]), int (end [-2:]))
          item ['length'] = (date2-date1) .seconds
          #Initial actual duty percentage
          item ['per'] = 0
          #Initial commute time
          item ['start'] = 0
          item ['end'] = 0
          #Iterate through the user's punch card record
          for t in item ['check']:
            #When earlier than the duty time
            if t <start:
              #Calculate time difference
              date1 = datetime.datetime (y, m, d, int (start [: 2]), int (start [-2:]))
              date2 = datetime.datetime (y, m, d, int (t [: 2]), int (t [-2:]))
              dif = (date1-date2) .seconds
              #When the punch time is within half an hour before the duty time
              if dif <= 1800:
                #Go to work successfully
                item ['start'] = start
            elif t <end:
              #If not yet at work
              if not item ['start']:
                # Then record the current time as time to work
                item ['start'] = t
              else:
                #Otherwise record the current time as the punch time
                item ['end'] = t
            else:
              #If you already work
              if item ['start']:
                #Calculate time difference
                date1 = datetime.datetime (y, m, d, int (end [: 2]), int (end [-2:]))
                date2 = datetime.datetime (y, m, d, int (t [: 2]), int (t [-2:]))
                dif = (date1-date2) .seconds
                #When the punch time is within half an hour after the duty time
                if dif <= 1800:
                  #Get off to work successfully
                  item ['end'] = end
          #Punch when you go to work
          if item ['start'] and item ['end']:
            #Calculate actual duty time
            date1 = datetime.datetime (y, m, d, int (item ['start'] [: 2]), int (item ['start'] [-2:]))
            date2 = datetime.datetime (y, m, d, int (item ['end'] [: 2]), int (item ['end'] [-2:]))
            dif = (date2-date1) .seconds
            #Calculate (actual shift duration / duration duration) percentage
            item ['per'] = int (dif / float (item ['length']) * 100)
          else:
            # Don't go to work as normal
            item ['start'] = 0
            item ['end'] = 0
          #Add records to the target array
          target.append (item)
      #Output Data
      self.render ("index.html",
        target = target
        )


def main ():
  tornado.options.parse_command_line ()
  http_server = tornado.httpserver.HTTPServer (Application ())
  http_server.listen (options.port)
  tornado.ioloop.IOLoop.instance (). start ()


if __name__ == "__main__":
  main ()
 

index.html


{
{% for item in target%}
  {
   'id': {{item ['id']}},
   'start': {{item ['start']}},
   'end': {{item ['end']}},
   'length': {{item ['length']}},
   'per': {{item ['per']}}
   }
{% end%}
}
At last

For the time being, I will only read the file and check the duty situation on a certain day, and then I will continue to write this small application according to the previous plan.

Because of the privacy of a bunch of friends, the test file was not sent up. However, if there are students who want to see the actual operation, they can tell me that I will send you the file.

A database insert statement that may be used: db.duty.insert ({"id": 5, "list": [1,2], 1: ["19:00", "22:00"], 2: ["19:00", "22:00"]})

Hope to help beginners like me!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.