1
+ import traceback
2
+ import warnings
1
3
from django .template import Template , Context
4
+ from django .db import connection
5
+ import logging
2
6
3
- import traceback
7
+ logger = logging .getLogger (__name__ )
8
+
9
+ def _validate_sql (sqltext ):
10
+ """Validate the SQL query."""
11
+ if len (sqltext ) < 8 or ("select" not in sqltext .lower ()):
12
+ return False
13
+ return True
14
+
15
+ def _execute_query (cursor , sqltext ):
16
+ """Execute the SQL query and fetch data."""
17
+ cursor .execute (sqltext )
18
+ desc = cursor .description
19
+ result_as_list = [
20
+ dict (zip ([col [0 ] for col in desc ], row )) for row in cursor .fetchall ()
21
+ ]
22
+ columns = [col [0 ] for col in desc ]
23
+ return columns , result_as_list
24
+
25
+ def _calculate_sums (data , columns , footerCols , totalText ):
26
+ """Calculate sum for specified columns."""
27
+ sumOfColumn = {col : 0 if col in footerCols else "-" for col in columns }
28
+
29
+ for d in data :
30
+ for attr , value in d .items ():
31
+ if attr in footerCols :
32
+ sumOfColumn [attr ] += float (str (value ).replace ("," , "" ))
33
+
34
+ totalColumnSet = False
35
+ for col in sumOfColumn :
36
+ if sumOfColumn [col ] != "-" :
37
+ sumOfColumn [col ] = format (float (str (sumOfColumn [col ])), "," )
38
+ elif not totalColumnSet :
39
+ sumOfColumn [col ] = totalText
40
+ totalColumnSet = True
41
+
42
+ return sumOfColumn
43
+
44
+ def _render_template (context ):
45
+ """Render the HTML table template."""
46
+ template = (
47
+ "<center><table dir=\" {{direction}}\" border=\" 1\" class=\" table table-striped {{htmlClass}}\" "
48
+ "style=\" width:93%;font-family:'{{font}}'\" >"
49
+ " <thead> <tr> <th colspan='{{columns|length|add:'1'}}' style=\" font-family:'{{font}}';font-weight: bold;\" > {{title}} </th> </tr>"
50
+ " <tr style='background-color:{{headerRowColor}}'>{% if rowIndex %} <th align=\" center\" > # </th> {% endif %} {% for c in columns %} <th>{{ c }}</th> {% endfor %} </tr> </thead>"
51
+ " <tbody> {% for d in data %} <tr style='background-color:{% if forloop.counter0|divisibleby:'2' %} {{evenRowColor}} {% else %} {{oddRowColor}} {% endif %} ' >"
52
+ " {% if rowIndex %} <td align=\" center\" >{{ forloop.counter }}</td> {% endif %} {% for attr, value in d.items %} <td align=\" center\" >{{ value }}</td> {% endfor %} </tr> {% endfor %} "
53
+ " {% if sumOfColumn %} <tr style='background-color:#eee;font-weight: bold;'> <td></td> {% for a,v in sumOfColumn.items %} <td align=\" center\" >{{ v }}</td> {% endfor %} </tr> {% endif %}</tbody> </table></center>"
54
+ )
55
+
56
+ return Template (template ).render (Context (context ))
57
+
58
+ def _generate_report (cursor , title , sqltext , footerCols , htmlClass , direction , font , totalText , rowIndex , headerRowColor , evenRowColor , oddRowColor ):
59
+ """Internal method to generate the SQL report."""
60
+ columns , data = _execute_query (cursor , sqltext )
61
+
62
+ sumOfColumn = None
63
+ if footerCols :
64
+ sumOfColumn = _calculate_sums (data , columns , footerCols , totalText )
65
+
66
+ context = {
67
+ 'title' : title ,
68
+ 'data' : data ,
69
+ 'columns' : columns ,
70
+ 'sumOfColumn' : sumOfColumn ,
71
+ 'direction' : direction ,
72
+ 'font' : font ,
73
+ 'totalText' : totalText ,
74
+ 'rowIndex' : rowIndex ,
75
+ 'headerRowColor' : headerRowColor ,
76
+ 'evenRowColor' : evenRowColor ,
77
+ 'oddRowColor' : oddRowColor ,
78
+ 'htmlClass' : htmlClass
79
+ }
80
+
81
+ return _render_template (context )
82
+
83
+ def generate_from_sql (title , sqltext , footerCols = None , htmlClass = "" , direction = "ltr" , font = "Tahoma" , totalText = "Total" , rowIndex = False , headerRowColor = '#eeeeee' , evenRowColor = '#ffffff' , oddRowColor = "#ffffff" ):
84
+ """Generate the SQL report with an internally created cursor."""
85
+ try :
86
+ if not _validate_sql (sqltext ):
87
+ return 'Not Valid SQL'
88
+
89
+ with connection .cursor () as cursor :
90
+ return _generate_report (cursor , title , sqltext , footerCols , htmlClass , direction , font , totalText , rowIndex , headerRowColor , evenRowColor , oddRowColor )
91
+ except Exception as e :
92
+ logger .error (traceback .format_exc ())
93
+ return f"Error: { str (e )} "
94
+
95
+ def generateFromSql (cursor , title , sqltext , footerCols = None , htmlClass = "" , direction = "ltr" , font = "Tahoma" , totalText = "Total" , rowIndex = False , headerRowColor = '#eeeeee' , evenRowColor = '#ffffff' , oddRowColor = "#ffffff" ):
96
+ """Generate the SQL report with a provided cursor."""
97
+ warnings .warn ("generateFromSql is deprecated and will be removed in a future release. Use generate_from_sql instead." , DeprecationWarning )
98
+ try :
99
+ if not _validate_sql (sqltext ):
100
+ return 'Not Valid SQL'
4
101
5
- def generateFromSql (cursor , title , sqltext , footerCols = None , htmlClass = "" , direction = "ltr" , font = "Tahoma" , totalText = "Total" , rowIndex = False , headerRowColor = '#eeeeee' ,evenRowColor = '#ffffff' , oddRowColor = "#ffffff" ) :
6
- sumCols = []
7
- try :
8
- if (len (sqltext ) < 8 or ("select" not in sqltext .lower ())) :
9
- return ('Not Valid SQL' )
10
-
11
- sql_query = sqltext
12
- sumCols = footerCols
13
- # execute sql query and retrieve data from db
14
- cursor .execute (sql_query )
15
-
16
- # retrieve columns of the data
17
- desc = cursor .description
18
-
19
- result_as_list = [
20
- dict (zip ([col [0 ] for col in desc ], row )) for row in cursor .fetchall ()
21
- ]
22
-
23
- columns = [col [0 ] for col in desc ] #result.keys()
24
- data = result_as_list
25
-
26
-
27
-
28
-
29
-
30
- sumOfColumn = None
31
- if (sumCols != None ) :
32
- sumOfColumn = {}
33
-
34
- # initiating footer aggrigation values
35
- for c in columns :
36
- if (c in sumCols ):
37
- sumOfColumn [c ]= 0
38
- else :
39
- sumOfColumn [c ]= "-"
40
-
41
- # travers in rows and aggrigate the values of columns those are in footerCols
42
- for d in data :
43
- for attr , value in dict (d ).items () :
44
- if (attr in sumCols ):
45
- sumOfColumn [attr ]= sumOfColumn [attr ]+ float (str (value ).replace ("," , "" ))
46
-
47
- totalColumnSet = False
48
- if (sumCols != None ) :
49
- for col , val in sumOfColumn .items () :
50
- if (val != "-" ) :
51
- sumOfColumn [col ] = format (float (str (val )),"," )
52
- elif (totalColumnSet == False ) :
53
- sumOfColumn [col ] = totalText
54
- totalColumnSet = True
55
-
56
- # template to generate data from data retrieved from database
57
- template = "<center><table dir=\" {{direction}}\" border=\" 1\" class=\" table table-striped {{htmlClass}}\" style=\" width:93%;font-family:'{{font}}'\" > <thead> <tr> <th colspan='{{columns|length|add:'1'}}' style=\" font-family:'{{font}}';font-weight: bold;\" > {{title}} </th> </tr> <tr style='background-color:{{headerRowColor}}'>{% if rowIndex == True %} <th align=\" center\" > # </th> {% endif %} {% for c in columns %} <th>{{ c }}</th> {% endfor %} </tr> </thead> <tbody> {% for d in data %} <tr style='background-color:{% if forloop.counter0|divisibleby:'2' %} {{evenRowColor}} {% else %} {{oddRowColor}} {% endif %} ' > {% if rowIndex == True %} <td align=\" center\" >{{ forloop.counter }}</td> {% endif %} {% for attr, value in d.items %} <td align=\" center\" >{{ value }}</td> {% endfor %} </tr> {% endfor %} {% if sumOfColumn != None %} <tr style='background-color:#eee;font-weight: bold;'> <td></td> {% for a,v in sumOfColumn.items %} <td align=\" center\" >{{ v }}</td> {% endfor %} </tr> {% endif %}</tbody> </table></center>"
58
-
59
-
60
-
61
- c = Context ({
62
- 'title' :title ,
63
- 'data' :data ,
64
- 'columns' :columns ,
65
- 'sumOfColumn' :sumOfColumn ,
66
- 'direction' :direction ,
67
- 'font' :font ,
68
- 'totalText' :totalText ,
69
- 'rowIndex' : rowIndex ,
70
- 'headerRowColor' :headerRowColor ,
71
- 'evenRowColor' : evenRowColor ,
72
- 'oddRowColor' : oddRowColor ,
73
- 'htmlClass' : htmlClass
74
- })
75
-
76
- return Template (template ).render (c )
77
- except BaseException as e :
78
- #print exception trace to console
79
- print (traceback .format_exc ())
80
- return ("Error :" + str (e ))
102
+ return _generate_report (cursor , title , sqltext , footerCols , htmlClass , direction , font , totalText , rowIndex , headerRowColor , evenRowColor , oddRowColor )
103
+ except Exception as e :
104
+ logger .error (traceback .format_exc ())
105
+ return f"Error: { str (e )} "
0 commit comments