You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django REST中通过Pyppeteer登录并生成PDF

Django REST Framework + Pyppeteer 生成受限端点PDF问题解决

问题描述

在Django REST Framework项目中使用Pyppeteer==0.2.6生成PDF:

  • 当视图permission_class设为AllowAny时,PDF生成正常
  • 访问需要登录的受限端点时,控制台提示目标对象不存在(实际对象存在)
  • 尝试通过Pyppeteer登录API页面、后台页面,问题未解决

原代码

async def render_page_as_pdf(self, url, sentinel=SENTINEL):
    page = await self.browser_page()
    await page.emulateMedia('print')

    await page.goto('http://localhost:8000/api/auth/login/?next=/api/rest-auth/user/')
    await page.type('#id_username', 'username@test.com')
    await page.type('#id_password', 'my_pass')
    await page.click('#submit-id-submit')

    try:
        await page.evaluate(f"""() => window.goto("{url}")""")
    except PyppeteerError:
        await page.goto(url)
    try:
        await page.waitFor(sentinel, timeout=self.timeout, visible=True)
        return await page.pdf(
            format=self.page_format,
            timeout=self.timeout,
            printBackground=True,
        )
    except (TimeoutError, PyppeteerError):
        logger.exception(f'error to generate pdf: {url}')
    return None

控制台输出

"GET /document/sale/31/ HTTP/1.1" 200 -
Forbidden: /api/rest-auth/user/
Forbidden: /api/rest-auth/user/
172.19.0.1 - - [01/Jul/2024 13:41:48] "GET /api/rest-auth/user/ HTTP/1.1" 403 -
Not Found: /api/documentsales/31/
Not Found: /api/documentsales/31/
172.19.0.1 - - [01/Jul/2024 13:41:48] "GET /api/documentsales/31/ HTTP/1.1" 404 -

问题分析

  1. 会话未正确建立:登录后未等待页面跳转完成,导致认证cookie未被正确设置就访问目标URL
  2. 错误的页面跳转方法:window.goto不是浏览器原生方法,会触发错误
  3. URL路径不匹配:控制台中出现的/api/documentsales/31/与目标/document/sale/31/路径不一致,可能是参数拼写错误
  4. 权限验证问题:即使登录成功,用户可能没有目标对象的访问权限

解决方案

修正后的代码

async def render_page_as_pdf(self, url, sentinel=SENTINEL):
    page = await self.browser_page()
    await page.emulateMedia('print')

    # 访问登录页,等待页面完全加载
    login_url = 'http://localhost:8000/api/auth/login/'
    await page.goto(login_url, waitUntil='networkidle2')
    
    # 输入账号密码并登录,等待跳转完成确保会话建立
    await page.type('#id_username', 'username@test.com')
    await page.type('#id_password', 'my_pass')
    await Promise.all([
        page.click('#submit-id-submit'),
        page.waitForNavigation(waitUntil='networkidle2')
    ])

    # 访问目标URL,等待页面加载完成
    try:
        await page.goto(url, waitUntil='networkidle2')
        await page.waitFor(sentinel, timeout=self.timeout, visible=True)
        return await page.pdf(
            format=self.page_format,
            timeout=self.timeout,
            printBackground=True,
        )
    except (TimeoutError, PyppeteerError):
        logger.exception(f'error to generate pdf: {url}')
    finally:
        await page.close()  # 释放页面资源
    return None

额外排查步骤

  • 验证URL正确性:确认传入的url参数路径与实际端点一致,避免拼写错误
  • 手动验证权限:登录对应账号后,手动访问目标URL,确认能正常加载内容
  • 检查会话状态:登录后通过await page.cookies()查看是否携带sessionid等认证cookie
  • 确认对象权限:如果使用DRF的对象级权限(如DjangoObjectPermissions),确保用户对目标ID的对象有访问权限

内容的提问来源于stack exchange,提问作者user25455142

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 14:32:10