Django模板无法展示Amazon S3中已上传PDF的问题求助
解决Django模板无法展示S3中PDF的问题
核心问题分析
你当前的代码存在几个关键问题:
- 缺少返回所有PDF列表的视图,模板依赖的
pdf_documents变量未被传递 DisplayPDFView存在代码错误(变量未定义就打印、异常捕获无返回值)- 若使用私有S3桶,模板直接调用
pdf_file.url无法访问私有文件
分步解决方案
1. 添加PDF列表视图,传递模板所需变量
模板中使用{% for pdf_document in pdf_documents %}循环,但你没有提供对应的列表视图。添加以下代码:
# views.py from django.views.generic import ListView from .models import PDFDocument class PDFListView(ListView): model = PDFDocument template_name = 'viewCVpage.html' context_object_name = 'pdf_documents' # 与模板变量名保持一致
在urls.py中添加对应路由:
path('view-cv/', views.PDFListView.as_view(), name='view_cv'),
2. 修复DisplayPDFView的代码错误
原视图存在变量未定义就打印、异常捕获无返回值的问题,修复后代码:
# views.py from django.http import HttpResponse from django.views import View import boto3 from django.conf import settings class DisplayPDFView(View): def get(self, request, file_key, *args, **kwargs): # 正确初始化S3客户端(需确保settings中配置了密钥和区域) s3 = boto3.client( 's3', aws_access_key_id=settings.AWS_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY, region_name=settings.AWS_S3_REGION_NAME ) bucket_name = settings.AWS_STORAGE_BUCKET_NAME try: response = s3.get_object(Bucket=bucket_name, Key=file_key) pdf_content = response['Body'].read() # 返回PDF响应 response = HttpResponse(pdf_content, content_type='application/pdf') response['Content-Disposition'] = f'inline; filename="{file_key}"' return response except s3.exceptions.NoSuchKey: return HttpResponse('PDF不存在', status=404) except Exception as e: print(f"错误详情: {e}") return HttpResponse('服务器内部错误', status=500)
3. 适配S3桶的访问权限
情况1:公开S3桶
确保settings.py中配置了正确的S3存储后端,这样pdf_file.url会直接生成公开可访问的S3 URL:
# settings.py DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' AWS_ACCESS_KEY_ID = '你的AWS访问密钥ID' AWS_SECRET_ACCESS_KEY = '你的AWS秘密访问密钥' AWS_STORAGE_BUCKET_NAME = '你的S3桶名' AWS_S3_REGION_NAME = '你的桶所在区域(如us-east-1)' AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
此时模板代码无需修改,保持原有的{{ pdf_document.pdf_file.url }}即可。
情况2:私有S3桶
私有桶无法直接通过pdf_file.url访问,需通过DisplayPDFView代理访问,修改模板代码:
{% for pdf_document in pdf_documents %} <div class="col-md-4 col-sm-12"> <div class="card" style="width: 100%; float: left; margin-bottom: 10px;"> <object data="{% url 'display_pdf' pdf_document.pdf_file.name %}" type="application/pdf" style="width: 100%; height: 400px;"> <p>无法显示PDF,请<a href="{% url 'display_pdf' pdf_document.pdf_file.name %}">下载PDF</a>。</p> </object> </div> </div> {% endfor %}
注:pdf_document.pdf_file.name对应S3中的文件键(如pdfs/example.pdf)。
4. 验证数据库记录与模板路径
- 确认Django数据库中存在
PDFDocument对象(可通过Django Admin查看) - 确认
viewCVpage.html放在正确的模板目录下(app的templates文件夹或项目根目录的templates文件夹)
内容的提问来源于stack exchange,提问作者Teh yong xian
相关产品推荐
相关产品推荐

