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

在本地部署的Django Web应用中添加自定义功能按钮并通过Python脚本实现文档处理的技术咨询

Hey there! Let's work through that third step you're stuck on—linking your web buttons to those Python scripts and getting downloadable processed documents. I'll walk you through a straightforward, step-by-step implementation with code examples, plus a couple of alternative ideas to fit your workflow.

Core Concept

Django's views act as the bridge between your frontend buttons and backend scripts. When a user clicks a button, we'll send a POST request to a dedicated view, which will:

  1. Retrieve the uploaded temporary file
  2. Call your custom Python script to process it
  3. Generate a downloadable response with the output file

Step 1: Update Your Views (views.py)

First, let's add a view to handle the document processing and download. We'll also tweak your upload view to store the file path in the user's session (so we can access it later when processing):

import os
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.conf import settings
from .forms import DocumentUploadForm
# Import your custom scripts
from .scripts.pdf_compression import compress_pdf
from .scripts.merge_two_pdfs import merge_pdfs

def upload_document(request):
    if request.method == 'POST':
        form = DocumentUploadForm(request.POST, request.FILES)
        if form.is_valid():
            # Save the uploaded file to your temporary directory
            main_doc = request.FILES['document']
            main_file_path = os.path.join(settings.MEDIA_ROOT, main_doc.name)
            
            with open(main_file_path, 'wb+') as dest:
                for chunk in main_doc.chunks():
                    dest.write(chunk)
            
            # Store the file path in session for later processing
            request.session['main_file_path'] = main_file_path
            
            # Handle second file for merge task (if needed)
            if 'second_document' in request.FILES:
                second_doc = request.FILES['second_document']
                second_file_path = os.path.join(settings.MEDIA_ROOT, second_doc.name)
                
                with open(second_file_path, 'wb+') as dest:
                    for chunk in second_doc.chunks():
                        dest.write(chunk)
                
                request.session['second_file_path'] = second_file_path
            
            # Pass uploaded file info to the template
            return render(request, 'document_tool.html', {
                'uploaded_file': main_doc.name,
                'has_second_file': 'second_file_path' in request.session
            })
    else:
        form = DocumentUploadForm()
    
    return render(request, 'document_tool.html', {'form': form})

def process_document(request, task_type):
    if request.method != 'POST':
        return redirect('upload')
    
    # Retrieve file paths from session
    main_file_path = request.session.get('main_file_path')
    if not main_file_path or not os.path.exists(main_file_path):
        return render(request, 'document_tool.html', {
            'error': 'No uploaded file found. Please upload a document first.'
        })
    
    output_file_path = None
    # Execute the corresponding script based on task type
    try:
        if task_type == 'compress':
            output_file_path = compress_pdf(main_file_path)
        elif task_type == 'merge':
            second_file_path = request.session.get('second_file_path')
            if not second_file_path or not os.path.exists(second_file_path):
                return render(request, 'document_tool.html', {
                    'error': 'Need a second file to merge. Upload one first!'
                })
            output_file_path = merge_pdfs(main_file_path, second_file_path)
    except Exception as e:
        return render(request, 'document_tool.html', {
            'error': f'Processing failed: {str(e)}'
        })
    
    # Generate the download response
    if output_file_path and os.path.exists(output_file_path):
        with open(output_file_path, 'rb') as f:
            response = HttpResponse(f.read(), content_type='application/pdf')
            # Set a descriptive filename for the download
            base_name = os.path.basename(main_file_path)
            response['Content-Disposition'] = f'attachment; filename="processed_{base_name}"'
            
            # Optional: Clean up temporary files after download
            # os.remove(main_file_path)
            # if task_type == 'merge':
            #     os.remove(second_file_path)
            # os.remove(output_file_path)
            
            return response
    
    return render(request, 'document_tool.html', {
        'error': 'Could not generate processed file. Please try again.'
    })

Step 2: Create/Update Your Form (forms.py)

Adjust your upload form to optionally accept a second file for merging:

from django import forms

class DocumentUploadForm(forms.Form):
    document = forms.FileField(
        label='Main PDF File',
        accept=".pdf",
        help_text="Upload the primary document you want to process"
    )
    second_document = forms.FileField(
        label='Second PDF File (for merge only)',
        accept=".pdf",
        required=False,
        help_text="Optional: Upload a second file if you want to merge documents"
    )

Step 3: Configure URLs (urls.py)

Add URLs to map your buttons to the processing view:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.upload_document, name='upload'),
    path('process/<str:task_type>/', views.process_document, name='process_document'),
]

Step 4: Update Your Template (document_tool.html)

Add buttons that submit POST requests to your processing view. We'll show these buttons only after the user has uploaded a file:

<!DOCTYPE html>
<html>
<head>
    <title>Local Document Tool</title>
    <style>
        .error { color: red; margin: 10px 0; }
        .button-group { margin-top: 20px; gap: 10px; display: flex; }
    </style>
</head>
<body>
    <h1>Document Processing Tool</h1>
    
    {% if error %}
        <p class="error">{{ error }}</p>
    {% endif %}

    <!-- Upload Form -->
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Upload Files</button>
    </form>

    <!-- Processing Buttons (Show after upload) -->
    {% if uploaded_file %}
        <h3>Uploaded File: {{ uploaded_file }}</h3>
        {% if has_second_file %}
            <p>Second file uploaded for merging</p>
        {% endif %}
        
        <div class="button-group">
            <form method="post" action="{% url 'process_document' task_type='compress' %}">
                {% csrf_token %}
                <button type="submit">Compress PDF</button>
            </form>
            
            {% if has_second_file %}
                <form method="post" action="{% url 'process_document' task_type='merge' %}">
                    {% csrf_token %}
                    <button type="submit">Merge PDFs</button>
                </form>
            {% endif %}
        </div>
    {% endif %}
</body>
</html>

Step 5: Configure Temporary File Storage (settings.py)

Make sure you have a directory for temporary files and configure Django to use it:

import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Temporary file storage
MEDIA_ROOT = os.path.join(BASE_DIR, 'temp_documents')
MEDIA_URL = '/temp/'

# Create the directory if it doesn't exist
if not os.path.exists(MEDIA_ROOT):
    os.makedirs(MEDIA_ROOT)

Key Notes & Improvements

  • Temporary File Cleanup: The code has optional comments to delete files after download. For local deployment, you could also set up a simple cron job (Linux) or Task Scheduler (Windows) to delete old files in temp_documents daily.
  • Error Handling: We added basic try/except blocks to catch script errors and show user-friendly messages. You can expand this to handle invalid file types, large files, etc.
  • Alternative Idea: Async Processing: If you're handling large files, processing might take time. You could use Celery (with Redis/RabbitMQ) to run tasks in the background, and update the frontend with a progress indicator using AJAX.
  • Class-Based Views: For cleaner code, you could refactor the views into Django's Class-Based Views (e.g., FormView for uploads, View for processing).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 09:18:14