I 'm new here. I wrote the following django code. I 'm opening, closing files here and saving them temporarily and deleting them. I tried to use Python's tempfile and was getting Permission Error and I did asked about it on IRC #django but maybe Windows is not a pleasant to use OS for programmers so I couldn't get a good answer. I needed something like render_to_string of django which takes in a html string and replace all templating with the context dict but it seems django is made to treat every .html file as a template.
Purpose of the project : It is to take a visitor's id and return him with a pdf which will be formed by picking up a row from the database by looking at his id. There are 3 kinds of ids here.
How is the pdf being made?
I was given a pdf empty form which I converted to .docx file with the use of online sites. Now I tried to use python-docx to convert docx to pdf but that required libre office/ms word which might not be available on the server (The form can be formed by the client on his local pc and be given to the technical guy to put on the server).
I was suggested to use a html form and the client said that he might change the form.
@ChrisWarrick on #python IRCnode suggested me to use HTML to PDF conversion which could be done by weasyPrint which was cross platform and easier to install. Although he said me to use jinja but since I was using django why install some other library. Now I said to the client to open a .docx file and create whatever form he has to make and put {{NAME}} and other variables wherever he wants some information from the database to be put and save it as .html file and further put it in the /media folder of the django project. Then he has to open the config (.cfg) file and put
NAME=NAME here 'NAME' on left is what is in the .html file(docx form) and on the right is column name of the database table(I got a single table).
Please help me make this code make more maintainable and remove that unnecessary saving file and deleting it. Also there's a problem that on windows when I save the docx file as .html I get the encoding as cp1252 whereas the server has linux as told to me. I have been told on IRCnode #powershell that windows can have a bunch of too many encodings. To do this I will say to the client to convert .html to utf8 using Get-Content word.htm | out-file -encoding utf8 word-1.htm
App name base
base/view.py
from django.shortcuts import render
from .forms import InputData
from . import backend
from django.http import FileResponse, HttpResponse
import configparser
config = configparser.RawConfigParser()
config.read('vars.cfg')
# Create your views here.
def index(request):
if request.method == "POST":
form = InputData(request.POST)
if form.is_valid():
check, data = backend.main(**form.cleaned_data)
if check:
return FileResponse(
data,
as_attachment=True,
filename=config['DOWNLOAD']['DOWNLOAD_FILE_AS'])
else:
return HttpResponse(data)
form = InputData()
return render(request, "base/index.html", {
'forms': form
})
base/backend.py
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
if os.path.exists('temp.pdf'):
os.remove('temp.pdf')
def getConfigObject():
config = configparser.RawConfigParser()
config.optionxform = str
config.read('vars.cfg')
return config
config = getConfigObject()
def load_custom_tags():
html = codecs.open(
config["FILES"]["HTML_FILE_NAME"],
encoding='utf-8').read()
html = "{% load numbersinwords %}" if not html.startswith(
"{% load"
) else "" + html
Html_file = open(config["FILES"]["HTML_FILE_NAME"], "w", encoding="utf-8")
Html_file.write(html)
Html_file.close()
def html2pdf(row):
row = row.to_dict()
load_custom_tags()
html = render_to_string(Path(config["FILES"]["HTML_FILE_NAME"]).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):
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)
HTML(string=html).write_pdf("temp.pdf")
# Code from
# https://stackoverflow.com/questions/47833221/emailing-a-django-pdf-file-without-saving-in-a-filefield
# temp = tempfile.NamedTemporaryFile()
# temp.write(pdf_file)
# temp.seek(0)
########
f = open("temp.pdf", "rb")
return (True, f)
return (False, f"<h1>Invalid credential {opt}: {value}</h1>")
base/templatetags/numbersinwords.py
from django import template
from num2words import num2words
register = template.Library()
@register.filter()
def to_words(value):
return num2words(int(value), lang="en_IN").upper()