Django上传JPEG图片触发AttributeError错误求助
Django上传JPEG图片触发500错误(PNG正常)
错误日志
Internal Server Error: /publish_offer/ Traceback (most recent call last): File "C:\Users\G-FIVE\Desktop\Projects\revenue\venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\G-FIVE\Desktop\Projects\revenue\venv\Lib\site-packages\django\utils\deprecation.py", line 136, in __call__ response = self.process_response(request, response) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\G-FIVE\Desktop\Projects\revenue\venv\Lib\site-packages\django\middleware\clickjacking.py", line 27, in process_response if response.get("X-Frame-Options") is not None: ^^^^^^^^^^^^ AttributeError: 'SafeString' object has no attribute 'get' [19/Jun/2023 14:08:35] "POST /publish_offer/ HTTP/1.1" 500 66377
相关代码
模型代码
class ImagenesOferta(models.Model): imagen = models.ImageField(verbose_name='Imagen Oferta', blank=False, null=False, upload_to='img_ofertas/') class Meta: verbose_name = 'Imagen de Oferta' verbose_name_plural = 'Imagenes de Ofertas' ordering = ['-id'] class Oferta(models.Model): titulo = models.CharField(verbose_name='Título', max_length=100, null=False, blank=False) descripcion = models.TextField(verbose_name='Descripción', null=True, blank=True) cantidad = models.PositiveSmallIntegerField(verbose_name='Cantidad', null=False, blank=False, default=1) valor = models.DecimalField(verbose_name='Valor', max_digits=3, decimal_places=2, null=False, blank=False) material = models.CharField(verbose_name='Material', max_length=20, null=False, blank=False, choices=MATERIAL_CHOICES) imagenes = models.ManyToManyField(ImagenesOferta, verbose_name='Imagenes de la Oferta', blank=True) usuario = models.ForeignKey(Usuario, verbose_name='Usuario', null=False, blank=False, on_delete=models.CASCADE) is_active = models.BooleanField(verbose_name='Activo/Inactivo', default=True) vendido = models.BooleanField(verbose_name='Vendido', default=False) fecha_creacion = models.DateTimeField(verbose_name='Fecha de Creación', auto_now_add=True) def __str__(self): return self.titulo class Meta: verbose_name = 'Oferta' verbose_name_plural = 'Ofertas', ordering = ['-fecha_creacion']
视图代码
@login_required(login_url='login') def publish_offer(request): form = formOferta() if request.method == 'POST': form = formOferta(request.POST, request.FILES) if form.is_valid(): form.instance.usuario = request.user oferta = form.save() imgs = [ ImagenesOferta(imagen=image) for image in request.FILES.getlist('imagenes') ] ImagenesOferta.objects.bulk_create(imgs) oferta.imagenes.add(*imgs) return redirect('home') else: return form.errors return render(request, 'publicar_oferta.html', { 'form': form })
模板上传输入框
<div class="mb-3"> <h5 class="text-center my-4">Añade Imagenes</h5> <label for="imagenes" class="form-label">Cargar Imagenes</label> <input class="form-control-file" type="file" id="imagenes" name="imagenes" multiple> </div>
问题原因
- 视图返回值类型错误:表单验证失败时,视图直接返回
form.errors,这是SafeString对象,而非Django要求的HttpResponse子类。中间件处理响应时调用response.get()方法,因对象类型不匹配触发AttributeError。 - JPEG验证失败触发错误分支:PNG能正常上传说明流程逻辑无问题,但JPEG可能因缺少图片处理依赖(如Pillow)导致表单验证不通过,进入错误分支触发上述异常。
解决方案
1. 修正视图错误返回逻辑
删除else分支的return form.errors,让验证失败时自动执行到下方的render,模板会自动渲染表单错误信息:
@login_required(login_url='login') def publish_offer(request): form = formOferta() if request.method == 'POST': form = formOferta(request.POST, request.FILES) if form.is_valid(): form.instance.usuario = request.user oferta = form.save() imgs = [ ImagenesOferta(imagen=image) for image in request.FILES.getlist('imagenes') ] ImagenesOferta.objects.bulk_create(imgs) oferta.imagenes.add(*imgs) return redirect('home') # 无论验证成功或失败,都渲染模板 return render(request, 'publicar_oferta.html', { 'form': form })
2. 安装图片处理依赖
Django的ImageField依赖Pillow处理图片格式验证,执行以下命令安装:
pip install pillow
3. 可选:添加图片格式验证
在formOferta中显式限制图片格式,避免非允许格式的图片提交:
from django import forms from .models import Oferta class formOferta(forms.ModelForm): class Meta: model = Oferta fields = ['titulo', 'descripcion', 'cantidad', 'valor', 'material'] def clean_imagenes(self): images = self.files.getlist('imagenes') allowed_types = ['image/jpeg', 'image/png'] for img in images: if img.content_type not in allowed_types: raise forms.ValidationError("仅支持JPEG和PNG格式图片") return images
内容的提问来源于stack exchange,提问作者Angel Daniel Ascanio Salazar
相关产品推荐
相关产品推荐

