Please ignore the comments in the code for the purpose of reviewing. I just require tips on using SOLID principles and how classes can be used in this code.Comments in the code are for mapping the image in my brain to what I want to do in words. Sorry for the mistakes in the comments of the code. I wrote them really fast.
This is a follow-up to Use django engine to fill in a .html file on storage (no template) and use weasyPrint to convert it to PDF.
I followed the instructions and refactored my code as per the suggestions by @Reinderien but recently the client said to me that on the webpage there are n ID's and n different PDF's are to be returned based on which ID the user selects. Currently n=2.
I have a radio select of which the visitor can select any one of the ID's and enter the correct value of input. So basically I get the value of the radio button as opt
and value
as the actual ID value. Now I have to check the database to find the column which is named as opt
and the row where value in that column is value
.
Initially there was just one form/word_document/.html_file that was being converted to PDF but now there are three forms. I know it's easy at the moment but I think I need some ideas on whether use of class
should be done and if so then how? I 'm really interested in refactoring this code and use SOLID principles. Surely, I 'm beginner level with design patterns and SOLID principles but it's just more and more code reviews that will make my eye catch 'how much' 'single responsibility' a function should be and if really if my function is extensible w/o modifying it. Please assume I 'm good enough at decorator,inheritance and class composition.
Also I couldn't get a way to remove the making of temporary files. There is temporary saving of the PDF made by weasyPrint.
I don't want that you code it up for me. Just few lines of explanation or a small UML diagram would be more than sufficient.
vars.cfg
[FILES]
HTML_FILE_NAME_FOL=C:\Users\Dell\Desktop\gjh\formfill\media\mydoc-utf8.htm
HTML_FILE_NAME_DPID=C:\Users\Dell\Desktop\gjh\formfill\media\mydoc-utf8.htm
EXCEL_FILE_NAME=C:\Users\Dell\Desktop\gjh\formfill\media\AM2.CSV
forms.py
from django import forms
class InputData(forms.Form):
opt = forms.ChoiceField(label="Enter Data:", choices=[('FOL', "Folio Number"),
('DPID', 'Dpid')
],
widget=forms.RadioSelect)
value = forms.CharField(label="Value ", widget=forms.TextInput(
attrs={'pattern': '[A-Z0-9]{0,16}'}))
backend.py(improved)
import os
import pandas as pd
import codecs
from weasyprint import HTML
import configparser
import tempfile
from django import template
from django.template.loader import render_to_string
from pathlib import Path
def remove_temp_file():
if os.path.exists('temp.pdf'):
os.remove('temp.pdf')
def get_config_object():
config = configparser.RawConfigParser()
config.optionxform = str
config.read('vars.cfg')
return config
config = get_config_object()
def load_custom_tags(opt):
""" TODO : Django by its nature will only convert a 'template' to HTML.
For that the file is being saved to the default location that is the template folder.
I just observed that I do now need to run this function again and again but once once similar
to like what one would do if one wants to fill the database the first time.
Is this possible anyway? I have to give the project folder to the client. He will place all the forms
paths in the cfg file.
vars.cfg
[FILES]
HTML_FILE_NAME_FOL=C:\Users\Dell\Desktop\gjh\formfill\media\mydoc-utf8.htm
HTML_FILE_NAME_DPID=C:\Users\Dell\Desktop\gjh\formfill\media\mydoc-utf8.htm
EXCEL_FILE_NAME=C:\Users\Dell\Desktop\gjh\formfill\media\AM2.CSV
"""
html = codecs.open(
config["FILES"][f"HTML_FILE_NAME_{opt.upper()}"],
encoding='utf-8').read()
if not html.startswith(r"{% load"):
html += "{% load numbersinwords %}"
with open(config["FILES"][f"HTML_FILE_NAME_{opt.upper()}"], "w", encoding="utf-8") as html_file:
html_file.write(html)
def html2pdf(row, path_form):
row = row.to_dict()
load_custom_tags()
html = render_to_string(Path(path_form).name,
{key: row[value]
for key, value in config._sections["TAGS"].items()})
return html
def get_data():
return pd.read_csv(config["FILES"]["EXCEL_FILE_NAME"],
dtype=str, keep_default_na=False)
def search_row(opt, value):
user_data = get_data()
return user_data[user_data[opt] == value]
def main(opt, value):
remove_temp_file()
row = search_row(opt, value)
if len(row) == 1:
row = row.squeeze()
else:
return (False, f"<h1>Invalid credential :"
" Multiple candidates exists"
"with given credential</h1>")
if not(row.empty):
html = html2pdf(row, Path(config["FILES"][f"HTML_FILE_NAME_{opt.upper()}"]))
HTML(string=html).write_pdf("temp.pdf")
f = open("temp.pdf", "rb")
return (True, f)
return (False, f"<h1>Invalid credential {opt}: {value}</h1>")