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>

   
Back to Top