skip to Main Content

I am using this script to create pdf file and append images with statistics:

import MySQLdb
from plotly import graph_objs as go
import numpy as np
import os
from plotly.subplots import make_subplots
from PyPDF2 import PdfFileMerger
from datetime import datetime, timedelta
import smtplib
from email.message import EmailMessage
import imghdr

# Database connect
db = MySQLdb.connect(host="localhost",
                     user="root",
                     passwd="****",
                     db="ofasorgu_10_168_1_71")

today = datetime.today().strftime('%Y-%m-%d')
one_week = (datetime.today() - timedelta(days=7)).strftime('%Y-%m-%d')
two_week = (datetime.today() - timedelta(days=14)).strftime('%Y-%m-%d')
three_week = (datetime.today() - timedelta(days=21)).strftime('%Y-%m-%d')
four_week = (datetime.today() - timedelta(days=28)).strftime('%Y-%m-%d')

# Functions
def load_post_views(table, today, one_week, two_week, three_week, four_week):

    product_views_dict = dict()

    cursor = db.cursor()
    cursor.execute(
        "SELECT client_id, product_id, referrer, `date`" +
        " FROM " + table + 
        " WHERE `date`>='"+four_week+"'")

    for x in range(0, cursor.rowcount):

        row = cursor.fetchone()
        network = ""
        period = ""
        client_id = row[0]
        product_id = row[1]
        referrer = row[2]
        date = str(row[3])

        email_cursor = db.cursor()
        email_cursor.execute("SELECT address FROM c8ty_connections_email WHERE entry_id=" + str(client_id))
        email = email_cursor.fetchone()

        product_cursor = db.cursor()
        product_cursor.execute("SELECT post_title FROM c8ty_posts WHERE id=" + str(product_id))
        product_name = product_cursor.fetchone()

        # Add client ID key
        if client_id not in product_views_dict:
            product_views_dict[client_id] = dict()

        # Add product ID key to client ID parent key 
        if product_id not in product_views_dict[client_id]:
            product_views_dict[client_id][product_id] = {
                today + " - " + one_week: {
                    "facebook": 0,
                    "twitter": 0,
                    "instagram": 0,
                    "linkedin": 0,
                    "pinterest": 0,
                    "website": 0,
                },
                one_week + " - " + two_week: {
                    "facebook": 0,
                    "twitter": 0,
                    "instagram": 0,
                    "linkedin": 0,
                    "pinterest": 0,
                    "website": 0,
                },
                two_week + " - " + three_week: {
                    "facebook": 0,
                    "twitter": 0,
                    "instagram": 0,
                    "linkedin": 0,
                    "pinterest": 0,
                    "website": 0,
                },
                three_week + " - " + four_week: {
                    "facebook": 0,
                    "twitter": 0,
                    "instagram": 0,
                    "linkedin": 0,
                    "pinterest": 0,
                    "website": 0,
                }
            }

        # Find referrer
        if "facebook" in referrer:
            network = "facebook"
        elif "twitter" in referrer:
            network = "twitter"
        elif "instagram" in referrer:
            network = "instagram"
        elif "linkedin" in referrer:
            network = "linkedin"
        elif "pinterest" in referrer:
            network = "pinterest"
        else:
            network = "website"

        # Check view period
        if date <= today and date > one_week:
            period = today + " - " + one_week
        if date <= one_week and date > two_week:
            period = one_week + " - " + two_week
        if date <= two_week and date > three_week:
            period = two_week + " - " + three_week
        if date <= three_week and date > four_week:
            period = three_week + " - " + four_week

        product_views_dict[client_id][product_id][period][network] += 1 
        product_views_dict[client_id]["email"] = email[0]
        product_views_dict[client_id][product_id]["product"] = product_name[0]

    return product_views_dict

def draw_statistic(data_dict):
    for clinetID, product_info in data_dict.items():

        client_email = product_info["email"]

        for productID, product_data in product_info.items():

            if type(product_data) is dict:

                product_name = product_data['product']
                table_data = [
                    [
                        today      + " - " + one_week,
                        one_week   + " - " + two_week,
                        two_week   + " - " + three_week,
                        three_week + " - " + four_week,
                        today      + " - " + four_week
                    ]
                ]

                total_one = []
                total_two = []
                total_three = []
                total_four = []
                overall_traces = []

                networks_and_positions = [
                    {"network": "website","row": 2,"col": 1},
                    {"network": "linkedin","row": 2,"col": 2},
                    {"network": "facebook","row": 3,"col": 1},
                    {"network": "twitter","row": 3,"col": 2},
                    {"network": "instagram","row": 4,"col": 1},
                    {"network": "pinterest","row": 4,"col": 2}
                ]

                fig = make_subplots(rows=5, cols=2)
                merge_fig = make_subplots(rows=1, cols=1)
                count = 2

                for dictionary in networks_and_positions:

                    network = dictionary['network']
                    row = dictionary['row']
                    col = dictionary['col']

                    total_one.append(product_data[today + " - " + one_week][network])
                    total_two.append(product_data[one_week + " - " + two_week][network])
                    total_three.append(product_data[two_week + " - " + three_week][network])
                    total_four.append(product_data[three_week + " - " + four_week][network])

                    table_data.append([
                        product_data[today + " - " + one_week][network],
                        product_data[one_week + " - " + two_week][network],
                        product_data[two_week + " - " + three_week][network],
                        product_data[three_week + " - " + four_week][network],
                        sum([
                            product_data[today + " - " + one_week][network],
                            product_data[one_week + " - " + two_week][network], 
                            product_data[two_week + " - " + three_week][network], 
                            product_data[three_week + " - " + four_week][network]
                        ])
                    ])

                    xaxis = [
                                today      + " - " + one_week,
                                one_week   + " - " + two_week,
                                two_week   + " - " + three_week,
                                three_week + " - " + four_week,
                            ]

                    yaxis = [
                                product_data[today + " - " + one_week][network],
                                product_data[one_week + " - " + two_week][network],
                                product_data[two_week + " - " + three_week][network],
                                product_data[three_week + " - " + four_week][network]
                            ]

                    chart_name = network.capitalize() + " statistic" 

                    # Create bar chart
                    if (count == 2):
                        social_fig = go.Bar(
                                x=xaxis,
                                y=yaxis,
                                name=chart_name
                            )
                    else:
                        social_fig = go.Bar(
                                x=xaxis,
                                y=yaxis,
                                name=chart_name,
                                yaxis="y"+str(count)
                            ) 

                    # Add chart to fig
                    fig.add_trace(
                            social_fig,
                            row=row,
                            col=col
                        )

                    count += 1

                    trace_name = network.capitalize() + " views"
                    overall_traces.append(
                            go.Scatter(
                                x=xaxis,
                                y=yaxis,
                                name=trace_name
                            )
                        )

                total_column_values_array = [sum(total_one), sum(total_two), sum(total_three), sum(total_four),]

                total_column_values_array.append(
                        sum(total_one)+sum(total_two)+sum(total_three)+sum(total_four)
                    )

                table_data.append(total_column_values_array)

                # Create product table
                fig.add_trace(
                    go.Table(
                        header=dict(values=["Period", "Website", "Facebook", "Twitter", "Instagram", "LinkedIn", "Pinterest", "Total"]),
                        cells=dict(values=table_data)
                    )
                )

                merge_fig.add_traces(overall_traces)

                # Craete folder if doesn't exist
                if not os.path.exists("files"):
                    os.mkdir("files")

                statistic_file = "files/statistic_"+product_name+".pdf"
                overall_file = "files/overall_"+product_name+".pdf"
                out_file = "files/"+product_name+"_statistic.pdf"
                # Create charts file
                fig.update_layout(height=1500, width=1000, title_text="<b>Greetings</b><br />This is statistic from <a href='https://www.cfasuk.co.uk/'>CFAS UK</a> for your product <b>"+product_name+"</b>")
                fig.update_layout(
                        yaxis3=dict(title="Website views", titlefont=dict(color="#636efa")),
                        yaxis4=dict(title="LinkedIn views", titlefont=dict(color="#ef553b")),
                        yaxis5=dict(title="Facebook views", titlefont=dict(color="#00cc96")),
                        yaxis6=dict(title="Twitter views", titlefont=dict(color="#b780f9")),
                        yaxis7=dict(title="Instagram views", titlefont=dict(color="#ffa15a")),
                        yaxis8=dict(title="Pinterest views", titlefont=dict(color="#19d3f3")),
                    )
                fig.write_image(statistic_file)
                # Create overall file
                merge_fig.update_layout(height=700, width=1000, title_text="Overall <b>"+product_name+"</b> statistic")
                merge_fig.write_image(overall_file)
                merge = PdfFileMerger(strict=False)
                # Append charts file to merger
                merge.append(statistic_file)
                # Append overall file to merger
                merge.append(overall_file)
                # Create end statistic file with both charts and overall
                merge.write(out_file)
                merge.close()
                # Delete statistic file
                os.remove(statistic_file)
                # Delete overall file
                os.remove(overall_file)
                # Send email with file
                send_mail(
                    "[email protected]", 
                    "[email protected]", 
                    "CFAS UK, "+product_name+" statistic",
                    "This is automated email. Please, do not reply!<br/>"+
                    "If you find some problem with the statistic or the product is not yours, please contact CFAS UK team.<br/>"+
                    "Best regards!",
                    out_file
                )

def send_mail(send_from, send_to, subject, text, file=None):
    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:

        smtp.login("[email protected]", "zmjquvphuvigqdai")

        msg = EmailMessage()
        msg['Subject'] = subject
        msg['From'] = send_from
        msg['To'] = send_to
        msg.set_content(text)

        with open(file, "rb") as f:
            file_data = f.read()
            file_name = f.name
            msg.add_attachment(file_data, maintype='application/pdf', subtype='pdf', filename=file_name)

        smtp.send_message(msg)

# Init
product_views_dict = load_post_views("an_product_view", today, one_week, two_week, three_week, four_week)
brochure_views_dict = load_post_views("an_brochure_view", today, one_week, two_week, three_week, four_week)

draw_statistic(product_views_dict)
draw_statistic(brochure_views_dict)

db.close()
exit()

It works fine when I test it on my local server. But I need to upload it to shared account on a Centos server. On my hosting provider. There I can’t install anaconda which I need to install orca for static images. Is there an alternative to create images and then add it to pdf file? Thank you in advance!

2

Answers


  1. Yes (you do not need to use any tool backend dependency in your code), there’s a very easy alternative library example as shown below.

    you can use matplotlib integration for this.

    you can import these modules as shown below

    from plotly.offline import init_notebook_mode, plot_mpl
    import matplotlib.pyplot as plt
    

    and you can use them as below:

    init_notebook_mode()
    fig = plt.figure()
    # you can configure you plot here  use below to save it as image
    
    plot_mpl(fig)
    plot_mpl(fig, image='png')
    

    OR if you want to still stick to only plotly and find alternative, you can see beow

    you can use a offline module of plotly to generate static images on the server and use it to generate a PDF. you can import it using from plotly.offline import plot. Once you’ve imported then you use the plot function as below

    fig = go.Figure( data=data, layout=layout )
    plot( fig, filename='your-file-name' , image = 'png')
    
    Login or Signup to reply.
  2. If you are using Plotly you can install kaleido and it will use this instead of orca to generate the static image.

    This is good if you can only install your packages through pip.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search