在Django中调用Gemini 2.0 Flash Experimental生成角色一致性图片时出现图片识别错误
在Django中调用Gemini 2.0 Flash Experimental生成角色一致性图片时出现图片识别错误
我太懂这种“本地Jupyter跑的顺风顺水,移到Django里就突然卡壳”的憋屈了!咱们先揪出Jupyter和Django代码里的核心差异,很快就能搞定这个图片识别报错的问题。
问题根源:临时文件处理的坑
你在Jupyter里用了tempfile.NamedTemporaryFile来管理临时图片,这个模块会自动处理服务器环境下的权限冲突、文件唯一性,还能确保图片数据被完整写入磁盘;但Django代码里直接用了固定路径temp_reference_image.png,这在多请求并发的服务器场景下很容易出问题:
- 多个请求同时调用时,会互相覆盖这个固定路径的文件,导致PIL读取到不完整的图片数据
- Django运行进程可能没有当前目录的写入权限,导致图片保存失败但没抛出明显错误
- 保存图片时没指定格式,若原参考图不是PNG格式,强行存成
.png后缀会导致格式兼容问题
具体修复方案
把Django里的临时文件逻辑改成和Jupyter一致的安全写法,同时补上格式指定、文件清理的细节:
def generate_image_gemini(prompt, reference_image=None): """ Generate images using Google's Gemini API. Parameters: - prompt (str): Text description of the desired image - reference_image (PIL.Image, optional): Reference image for character consistency Returns: - Generated image as PIL Image object and response text """ try: print(f"Generating image with Gemini: {prompt[:100]}...") temp_image_path = None pil_image = None if reference_image: import tempfile import os from django.core.files.base import ContentFile # 用tempfile创建安全的临时文件,避免多请求冲突 with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as temp_file: # 明确指定保存格式为PNG,确保格式兼容性 reference_image.save(temp_file, format='PNG') temp_image_path = temp_file.name print(f"Reference image saved to {temp_image_path}") # 读取临时图片后立即删除,避免磁盘残留 pil_image = Image.open(temp_image_path) os.unlink(temp_image_path) # 构造Gemini需要的内容 contents = [ f"Generate an illustration based on this description: '{prompt}'. Include this character in the scene.", pil_image ] else: # 纯文本请求逻辑 contents = [f"Generate an illustration based on this description: '{prompt}'"] # 调用Gemini API response = gemini_client.models.generate_content( model="gemini-2.0-flash-exp", contents=contents, config=types.GenerateContentConfig( response_modalities=['Text', 'Image'] ) ) # 处理Gemini响应 generated_image = None response_text = "" for part in response.candidates[0].content.parts: if part.text is not None: response_text += part.text elif part.inline_data is not None: # 先验证返回的是图片类型 if not part.inline_data.mime_type.startswith('image/'): raise ValueError(f"Unexpected data type from Gemini: {part.inline_data.mime_type}") # 解码base64数据并处理 image_data = base64.b64decode(part.inline_data.data) img_io = BytesIO(image_data) img_io.seek(0) # 确保指针在文件开头 generated_image = Image.open(img_io) # 用Django的默认存储保存图片,避免固定路径问题 from django.core.files.storage import default_storage timestamp = int(time.time()) save_path = f'gemini_images/gemini_{timestamp}.png' save_io = BytesIO() generated_image.save(save_io, format='PNG') save_io.seek(0) default_storage.save(save_path, ContentFile(save_io.getvalue())) print(f"Gemini image saved to: {default_storage.url(save_path)}") return generated_image, response_text except Exception as e: print(f"Error generating image with Gemini: {e}") # 兜底清理临时文件 if temp_image_path and os.path.exists(temp_image_path): os.unlink(temp_image_path) return None, f"Error: {str(e)}"
额外排查小技巧
- 版本对齐:确保Django环境的Pillow版本和Jupyter完全一致,版本差异可能导致图片识别逻辑不同
- 数据验证:把Gemini返回的
image_data写入临时文件,手动打开确认是有效图片,排除API返回数据异常的可能 - 权限检查:用
os.access(目标目录, os.W_OK)验证Django进程是否有读写保存目录的权限
备注:内容来源于stack exchange,提问作者user2202738
相关产品推荐
相关产品推荐

