Fancyhdr页眉页脚无效。使用PyLatex的LaTeX

0 投票
1 回答
40 浏览
提问于 2025-04-14 16:35

我通过Overleaf创建Latex文件,然后在Django和PyLatex中使用Celery Worker异步编译这些文件。我们使用pdfLaTeX作为编译器。我已经创建了一个.tex文件,然后将其保存为.txt,添加了数据并进行了编译。目前,图像和文本的交换都运行得很好。唯一的问题是PyLatex不接受我设置的fancyhdr页眉和页脚。在页脚的左侧图像显示出来了,但位置完全偏移了。页眉和/或其余页脚中没有渐变的痕迹。你们觉得这可能是什么原因呢?我在本地使用Miktex,并且实际上已经安装了所有必要的包。

这是.tex文件的前言部分:

\documentclass{article}
\usepackage{lipsum} % For dummy text


% ######################################################### IMPORTS ##################
% Basic imports
\usepackage{graphicx} % Images
\usepackage{geometry} % Page Layout
\usepackage{titlesec} % Overwriting Section Style 
\usepackage{xcolor} % Coloring
\usepackage{tcolorbox} % Content Boxing 
\usepackage{tikz}
\usepackage{fancyhdr}


% From customfooter.sty
\newcommand{\setcustomfooter}{%
    \fancyhf{} % Clear all header and footer fields
    \renewcommand{\footrulewidth}{0pt}
    \fancyfoot[C]{%
        \begin{tikzpicture}[overlay, remember picture]
            % Footer area
            \path (current page.south west) rectangle ([yshift=1.5cm]current page.south east);

            % Left image
            \node[anchor=west] at ([yshift=0.75cm, xshift=0.5cm]current page.south west) {
                \includegraphics[height=0.75cm, keepaspectratio]{assets/img/78241ec6-9e96-4a5d-bfd3-55433081368e.png}
            };

            % Right image
            \node[anchor=east] at ([yshift=0.75cm, xshift=-0.5cm]current page.south east) {
                \includegraphics[height=1cm, keepaspectratio]{assets/img/c15f7986-2e57-42b4-b5d5-da8f3257d34a.png}
            };

            % Page number
            \node at ([yshift=0.75cm]current page.south) {\thepage};
        \end{tikzpicture}%
    }
}
\setcustomfooter

% From customheader.sty
\usetikzlibrary{calc}
\definecolor{startcolor}{RGB}{225,8,20}
\definecolor{endcolor}{RGB}{144,14,38}

\newcommand{\setgradientheader}[1]{%
    \renewcommand{\headrulewidth}{0pt} 
    \fancyhead[C]{%
        \begin{tikzpicture}[overlay, remember picture]
            % Header area with gradient background
            \fill [left color=startcolor, right color=endcolor] ($(current page.north west)+(0.0cm,-0.5cm)$) rectangle ($(current page.north east)-(0.0cm,2.5cm)$);

            % Header Text
            \node[anchor=east, text=white, font=\LARGE, align=right] at ($(current page.north east)-(1cm,1.5cm)$) {#1};

            % Left side image
            \node[anchor=north west, inner sep=0] at ($(current page.north west)+(1cm,-1cm)$) {
                \includegraphics[height=1cm, keepaspectratio]{assets/img/8c26b223-68a4-4954-a90d-7b37dae90eae.png}
            };
        \end{tikzpicture}
    }
}

\pagestyle{fancy}

% ####################################################################################
% ######################################################### STYLE SETTINGS ###########

% Colors
\definecolor{darkpurple}{HTML}{8C1F3C}
\definecolor{greyish}{HTML}{7F7F7F}
\definecolor{lightgreyish}{HTML}{f4f4f4}
\definecolor{white}{HTML}{FFFFFF}
\definecolor{black}{HTML}{000000}
\definecolor{lightred}{HTML}{E32636}
\definecolor{redish}{HTML}{C00000}

% Set Variables and Layout Definitions
\geometry{
    a4paper, % Paper size
    left=0.5cm, % Left margin
    right=1.5cm, % Right margin
    top=1cm, % Top margin
    bottom=1.5cm, % Bottom margin
    includeheadfoot, % Include space for the header and footer
    headheight=2cm, % Height of the header
    headsep=0.5cm, % Space between header and text
    footskip=1cm % Space between text and footer
    }

% New Section Style
\titleformat{\section}
  {\normalfont\Large\bfseries\color{redish}} % format
  {\thesection}{1em}{} % label and spacing


% Additional Text Field Likert Scale 
\newcommand{\likert}[1]{
    \begin{tikzpicture}[baseline=(current bounding box.center), align=center]
        % Draw the circles/nodes
        \foreach \x in {1,2,3,4,5} {
            % Check if this node is the selected one
            \ifnum\x=#1
                \node[draw=darkpurple, circle, fill=darkpurple, minimum size=1cm] (\x) at (2*\x, 0) {};
            \else
                \node[draw=darkpurple, circle, minimum size=1cm] (\x) at (2*\x, 0) {};
            \fi
        }
        
        % Manually add text labels below each circle
        \node at (2, -1.2) {Very low};
        \node at (4, -1.2) {Low};
        \node at (6, -1.2) {Neutral};
        \node at (8, -1.2) {High};
        \node at (10, -1.2) {Very high};
    \end{tikzpicture}
}

% ####################################################################################




\begin{document}

% ########### START LANDING PAGE 1 
\setgradientheader{} 
\vspace*{\fill}

这是用于编译的包装类:

class LatexCompiler:
    
    def __init__(self, tex_file, replacements={}):
        
        self.temp_dir_pdfs = TEMP_DIR_PDFS
        os.makedirs(self.temp_dir_pdfs, exist_ok=True)
        
        # Setting the tex file 
        self._tex_file = tex_file 
        
        # Setting the replacements
        self._replacements = replacements
       
    def _load_tex_file(self):
        """
        Loading the desired tex (.txt) file.
        """
        script_dir = os.path.dirname(os.path.realpath(__file__))
        cPath = os.path.join(script_dir, 'statics', 'texs', self._tex_file + ".txt")
        cPath = os.path.normpath(cPath)
        
        with open(cPath, "r", encoding="utf-8") as f:
            file = f.read()
    
        self.tex_file = file 
        
        
    def _replace_placeholders(self):
        for key, value in self._replacements.items():            
            self.tex_file = self.tex_file.replace(key, value, -1)         
            
    
    def _get_sequential_name(self):
        return str(int(time.time())) + "_" + str(uuid.uuid4())[:8]       
    
            
    def _split_latex_content(self):
        lines = self.tex_file.splitlines()
        preamble = []
        content = []
        in_preamble = True

        for line in lines:
            
            if "\\documentclass" in line:
                continue 
            
            if '\\begin{document}' in line:
                in_preamble = False
                continue
            elif '\\end{document}' in line:
                break

            if in_preamble:
                preamble.append(line)
            else:
                content.append(line)

        return '\n'.join(preamble), '\n'.join(content)

    def run(self):
        self._load_tex_file() 
        self._replace_placeholders() 
        
        
    def compile(self):
        doc = Document(documentclass='article')
        preamble, content = self._split_latex_content()
        doc.preamble.append(NoEscape(preamble))
        doc.change_page_style("fancy")
        doc.append(NoEscape(content)) 
        
        with tempfile.NamedTemporaryFile(delete=False, dir=self.temp_dir_pdfs) as temp_pdf:
            temp_pdf_path = temp_pdf.name 
            
        doc.generate_pdf(temp_pdf_path, clean_tex=False, clean=False, compiler='pdflatex')
        
        with open(temp_pdf_path + ".pdf", 'rb') as pdf_file:
            pdf_io = BytesIO(pdf_file.read())
            
        # os.remove(temp_pdf_path + ".pdf")
        # os.remove(temp_pdf_path + ".tex")
        # os.remove(temp_pdf_path)
        
        pdf_io.seek(0)
        pdf_bytes = pdf_io.getvalue() 
        pdf_io.close() 
        return pdf_bytes

1 个回答

0

解决方案:当使用[overlay, remember picture]时,.tex文件需要编译多次。使用“latexmk”可以自动处理这个问题,否则你可以把“doc.generate_pdf”放在一个循环里,让它编译几次。

注意:我找不到PyLatex的真正错误日志;所以如果你像我一样使用并替换占位符,记得多检查几次,确保占位符在正确的位置,并且插入的文本转义正确。

撰写回答