Django中POST请求无法获取Base64输入值,Tesseract OCR功能提交后页面无响应问题排查
Let's break down why your current setup isn't working and how to fix it:
The Core Problem
You're using Django's CreateView, which has a built-in POST request flow: it validates the form, creates a model instance, then redirects to a success URL. Your OCR logic inside get_context_data never gets properly executed because:
- When you submit the form,
CreateViewprioritizes its own form handling over your custom POST logic inget_context_data. - Even if your code ran, the redirect after form submission would reset the context, so your
textvariable wouldn't persist to the rendered page. - Your form input uses the name
base64, but yourCreateViewspecifiesfields=['input']—this mismatch causes form validation to fail silently, making the view fall back to rendering an empty form.
Solution 1: Switch to TemplateView (If You Don't Need to Save Model Instances)
If storing the OCR input/result in your Ocr model isn't required, TemplateView is simpler and avoids the CreateView form conflicts:
# views.py from django.views.generic import TemplateView from django.http import HttpResponseRedirect from django.urls import reverse import base64 from io import BytesIO from PIL import Image import pytesseract class IndexView(LoginRequiredMixin, TemplateView): template_name = "ocr/ocr.html" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Pull OCR result from session (cleared after display to avoid stale data) context['text'] = self.request.session.get('ocr_text', '') self.request.session.pop('ocr_text', None) return context def post(self, request, *args, **kwargs): imgstring = request.POST.get('base64') text = "" if imgstring: # Process Base64 image imgstring = imgstring.split('base64,')[-1].strip() try: image_string = BytesIO(base64.b64decode(imgstring)) image = Image.open(image_string) text = pytesseract.image_to_string(image) text = text.encode("ascii", "ignore").decode() except Exception as e: # Handle invalid Base64 or image errors (optional) text = f"Error processing image: {str(e)}" # Store result in session to persist through redirect request.session['ocr_text'] = text # Redirect to same page (follows Post/Redirect/Get best practice) return HttpResponseRedirect(reverse('ocr-view'))
Solution 2: Fix CreateView (If You Need to Save Model Data)
If you want to save the input to your Ocr model, adjust the view to work with CreateView's form flow:
First, update your model to include a field for the OCR result (if not already present):
# models.py from django.db import models class Ocr(models.Model): input = models.TextField() # Stores the Base64 string result = models.TextField(blank=True) # Stores OCR text created_at = models.DateTimeField(auto_now_add=True)
Then modify the view to handle form validation and OCR logic correctly:
# views.py from django.views.generic.edit import CreateView from django.urls import reverse_lazy import base64 from io import BytesIO from PIL import Image import pytesseract from .models import Ocr class IndexView(LoginRequiredMixin, CreateView): model = Ocr template_name = "ocr/ocr.html" fields = ['input'] success_url = reverse_lazy('ocr-view') def form_valid(self, form): # Override form_valid to add OCR processing before saving self.object = form.save(commit=False) imgstring = self.object.input imgstring = imgstring.split('base64,')[-1].strip() try: image_string = BytesIO(base64.b64decode(imgstring)) image = Image.open(image_string) ocr_text = pytesseract.image_to_string(image) self.object.result = ocr_text.encode("ascii", "ignore").decode() except Exception as e: self.object.result = f"Error processing image: {str(e)}" self.object.save() # Store result in session for display after redirect self.request.session['ocr_text'] = self.object.result return super().form_valid(form) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['text'] = self.request.session.get('ocr_text', '') self.request.session.pop('ocr_text', None) return context
And update your HTML form to match the model field name (input instead of base64):
<form method="POST" action="{% url 'ocr-view'%}"> {% csrf_token %} <label for="base64"> Input Base64 :</label> <input type="text" class="form-control" id="text" name="input" /> <button type="submit" class="btn btn-primary mt-3" name="submit"> <i class="fas fa-search"></i> Submit </button> </form> <div class="card-body"> <label> Result : </label> <br> <span class="h3">{{text}}</span> </div>
Additional Checks
- Ensure Tesseract OCR engine is installed on your system, and if you're on Windows, set the path in your view:
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' - Verify the Base64 input is well-formed (either with or without the
data:image/xxx;base64,prefix—your code handles both cases). - Clean up your URLs: the second path
<int:pk>/points toIndexView, which is meant for creation, not detail viewing. UseDetailViewfor that route if needed.
内容的提问来源于stack exchange,提问作者HyperactiveSloth

