Which Python library should I use to convert my HTML along with css into Docx file using Django? [closed]
I'm developing a Django app where users submit a NOC form. The information is stored in the database, and based on that data, I need to generate a visa application that should be downloadable in .docx
format. I tried using pypandoc
to convert HTML into DOCX, but the problem is that the CSS is not rendering in the output document.
Here is my current approach:
#Code for Generating the DOCX File:
@login_required(login_url='login')
def generate_noc_doc(request, noc_id):
print("Generating NOC DOCX")
# Fetch the NOC instance
noc_instance = get_object_or_404(NOC, id=noc_id)
grade = noc_instance.grade.strip() if noc_instance.grade else ""
# Fetch employee ID and visa type from NOC instance
employee_id = noc_instance.applicant_id
visa_type = noc_instance.type_noc.lower()
additional_travelers = noc_instance.additional_travelers.all()
# Prepare family members text if there are additional travelers
if noc_instance.no_of_travelers > 0:
travelers_list = [f"({traveler.relationship_with_traveler}) named {traveler.additional_passport_name} bearing Passport No. {traveler.additional_passport_no}" for traveler in additional_travelers]
family_members_text = ", ".join(travelers_list)
else:
family_members_text = ""
# Fetch employee data based on applicant_id
employee = Employees.objects.get(EmployeeID=noc_instance.applicant_id)
# Determine pronouns based on gender
if employee.Gender.lower() == 'male':
pronoun_subjectC = 'He'
pronoun_subjectS = 'he'
pronoun_object = 'him'
pronoun_possessive = 'his'
elif employee.Gender.lower() == 'female':
pronoun_subjectC = 'She'
pronoun_subjectS = 'she'
pronoun_object = 'her'
pronoun_possessive = 'her'
else:
pronoun_subjectC = 'They'
pronoun_subjectS = 'they'
pronoun_object = 'them'
pronoun_possessive = 'their'
# Visa type ID dictionary
visa_type_ids = {
'tourist': '294',
'business': '345',
'medical purpose': '556',
'medical attendant': '789'
}
visa_type_id = visa_type_ids.get(visa_type.lower(), '000')
# Reference format
reference_number = f"F & A-HR-VISA-{timezone.now().year}/{visa_type_id}/{employee_id[-4:]}"
# Fetch the concern field for the selected country
selected_country = noc_instance.country_visit
try:
noc_country = NOCCountry.objects.get(country=selected_country)
concern = noc_country.concern
embassy = noc_country.embassy
office_address = noc_country.office_address
except NOCCountry.DoesNotExist:
concern = "Concern not available"
embassy = "Embassy not available"
office_address = "Address not available"
selected_visatype = noc_instance.type_noc
try:
noc_visatype = VisaType.objects.get(visa=selected_visatype)
subject = noc_visatype.subject
cost_provider = noc_visatype.cost_provider
intention = noc_visatype.intention
except VisaType.DoesNotExist:
subject = 'Not Available'
cost_provider = 'None'
intention = 'None'
# Prepare context with data from the NOC instance
context = {
'date': timezone.now().strftime("%d %B %Y"),
'designation': noc_instance.designation,
'applicant_name': noc_instance.applicant_name,
'applicant_id': employee_id,
'passport_no': noc_instance.passport_no,
'passport_name': noc_instance.passport_name,
'joining_date': noc_instance.joining_date.strftime("%d-%b-%Y"),
'country_visit': noc_instance.country_visit,
'travel_date_from': noc_instance.travel_date_from.strftime("%d %B %Y"),
'travel_date_to': noc_instance.travel_date_to.strftime("%d %B %Y"),
'grade': grade,
'reference_number': reference_number,
'visa_type': visa_type,
'concern': concern,
'embassy': embassy,
'subject': subject,
'cost_provider': cost_provider,
'office_address': office_address,
'family_members_text': family_members_text,
'pronoun_subjectC': pronoun_subjectC,
'pronoun_subjectS': pronoun_subjectS,
'pronoun_object': pronoun_object,
'pronoun_possessive': pronoun_possessive,
'intention': intention,
}
# Render HTML template with context data
html_string = render_to_string('profileapp/noc_pdf_template.html', context)
# Path to the custom DOCX template
template_path = os.path.join(settings.BASE_DIR, 'profileapp', 'doc_templates', 'template.docx')
# Create a temporary file for DOCX
with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as tmp:
tmp.close()
# Convert HTML to DOCX using Pandoc
pypandoc.convert_text(
html_string,
'docx',
format='html',
outputfile=tmp.name,
)
# Return DOCX file as response
with open(tmp.name, 'rb') as docx_file:
response = HttpResponse(docx_file.read(), content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
response['Content-Disposition'] = f'attachment; filename="Travel_Recommendation_{noc_instance.id}.docx"'
os.unlink(tmp.name)
return response
#HTML Template (noc_pdf_template.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>NOC PDF</title>
<style>
body {
font-family: Arial, sans-serif;
font-size: 5px;
line-height: 1.6;
color: #000;
}
.header,
.footer {
text-align: left;
margin-top: 20px;
}
.header {
margin-bottom: 20px;
}
.header p,
.footer p {
margin: 0;
padding: 0;
}
.content {
margin: 20px;
}
.content h1 {
font-size: 16px;
text-align: center;
text-decoration: underline;
margin-bottom: 20px;
}
.content p {
margin-bottom: 10px;
}
.info-table {
width: 100%;
margin-bottom: 20px;
}
.info-table td {
padding: 5px;
vertical-align: top;
}
.info-table .label {
font-weight: bold;
width: 150px;
}
.company-name {
font-weight: bold;
}
span {
margin-left: 20px;
}
.ref {
margin-top: 154px;
}
</style>
</head>
<body>
<div class="content">
<p class="ref"><strong>Our Ref: {{ reference_number }}</strong></p>
<p>Date: {{ date }}</p>
<p>To: {{concern}}<br>
<span>{{embassy}}</span><br>
<span>{{office_address}}</span>
</p>
<p>Subject: <span style="font-weight: bold; text-decoration: underline;">{{ subject }}</span></p>
<p>Dear Sir/Madam,</p>
<p>Eskayef Pharmaceuticals Limited is one of the leading pharmaceutical companies of Bangladesh (annual turnover
of Taka 23 billion equivalent to approximately 270 million US dollars) having more than 8500 employees. The
company was incorporated in 1979 as a subsidiary of SmithKline & French, USA and it was acquired by the
leading conglomerate of Bangladesh, Transcom Ltd. in 1990 in the wake of the merger between SmithKline &
French, USA and Beecham, UK. The state-of-the-art pharmaceutical manufacturing facility of Eskayef has
achieved approval from US FDA (United States Food and Drug Administration), UK MHRA (United Kingdom
Medicines and Healthcare products Regulatory Agency), TGA Australia (Therapeutic Goods Administration) and
Brazil ANVISA (Brazilian Health Regulatory Agency). The company has also established a hi-tech insulin
manufacturing plant for contract manufacturing for the world’s largest insulin maker, Novo Nordisk of
Denmark. Eskayef is growing more global and exporting its finished products and bulk pellets to 67 countries
across 6 continents. Presently, Eskayef is also marketing eye care products of Allergan Inc. USA, the global
leader in this specialty area.</p>
<p style="text-align: justify;">The purpose of this letter is to introduce our company's <strong>{{ designation
}}</strong>, <strong>{{ passport_name }}</strong>,
<strong>ID # {{ applicant_id }}</strong> bearing Passport No. <strong>{{ passport_no }}</strong>,
who is working with us since <strong>{{ joining_date }}</strong>. {{pronoun_subjectC}} intends to visit
<strong>{{ country_visit }}</strong>
as a part of {{intention}} {% if family_members_text %}with {{pronoun_possessive}} family
member{{family_members_text }}
{% endif %}
with expected travel date on <strong>{{ travel_date_from }}</strong> to
<strong>{{ travel_date_to }}</strong>. Please note that the entire trip cost will be borne by
{% if cost_provider == 'him'%}
{{pronoun_object}}.
{% else %}
company.
{% endif %}
After the visit,
{{pronoun_subjectS}} will return to Bangladesh and <strong>{{ passport_name }}</strong> will resume
{{pronoun_possessive}} duties in the company.
</p>
<p style="text-align: justify;">In view of the above, your kind assistance in granting <strong>{{ passport_name
}}</strong>'s entry visa would be highly appreciated.</p>
<p>With best regards,</p>
<p>Sincerely yours,<br>
For <strong> Eskayef Pharmaceuticals Limited</strong></p>
<br>
<br>
<br>
<br>
<!-- Conditional Footer based on Grade -->
<div class="footer">
{% if grade == 'ED' %}
<p>(<strong>Mohammad Mostafa Hassan</strong>)<br>
Executive Director - Commercial & HR<br>
Phone: 880 01711543455 (Cell)<br>
E-mail: mmn@skf.transcombd.com</p>
{% else %}
<p>(<strong>K.M. Shirazul Haque</strong>)<br>
Head of Human Resource Operations<br>
Phone: 880 01713065410 (Cell)<br>
E-mail: shiraz@skf.transcombd.com</p>
{% endif %}
</div>
</div>
</body>
</html>