Django填充MRZ表时出现400 Bad Request错误排查求助
问题排查:Flutter填充Django MRZ表时400 Bad Request错误
问题描述
在用Flutter移动端填充Django后端的MRZ表时,遇到400 Bad Request错误。所有属性从Flutter获取,仅ccp_account从后端获取(打印无输出)。服务器日志显示各参数已正常获取,但仍返回400错误。
相关代码与日志
MRZ模型代码
class MRZ(models.Model): id_mrz = models.AutoField(primary_key=True) FK_compte_ccp = models.OneToOneField(CompteCcp, on_delete=models.CASCADE) photo_passport = models.ImageField(upload_to='mrz_photos/') birthDate = models.DateField(null=True, blank=True) documentNumber = models.CharField(max_length=100, null=True, blank=True) expiryDate = models.DateField(null=True, blank=True)
视图代码
def remplir_mrz(request): if request.method == 'POST': try: # 从请求头获取JWT token token = request.headers.get('Authorization').split(' ')[1] print("Données reçues :", request.POST) print("Token JWT récupéré :", token) if token: # 解码JWT获取用户ID decoded_token = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256']) print("Token JWT decoder :", decoded_token) user_id = decoded_token['user_id'] print("user id :", user_id) # 获取关联的CCP账户 compte_ccp = get_object_or_404(CompteCcp, FK_compte_app=user_id) if 'photo_passport' in request.FILES: image_file = request.FILES['photo_passport'] # 创建用户专属文件夹 user_folder = os.path.join(settings.MEDIA_ROOT, str(user_id)) if not os.path.exists(user_folder): os.makedirs(user_folder) # 构造文件路径 filename = "MRZ.jpg" filepath = os.path.join(user_folder, filename) # 保存上传的图片 with default_storage.open(filepath, 'wb+') as destination: for chunk in image_file.chunks(): destination.write(chunk) # 处理前端传入的MRZ数据 document_number = request.POST.get('document_number') birth_datetime_str = request.POST.get('birth_date') expiry_datetime_str = request.POST.get('expiry_date') # 转换日期格式 birth_datetime = datetime.strptime(birth_datetime_str, "%Y-%m-%dT%H:%M:%S.%f") expiry_datetime = datetime.strptime(expiry_datetime_str, "%Y-%m-%dT%H:%M:%S.%f") birth_date = birth_datetime.date() expiry_date = expiry_datetime.date() print("documebt_number",document_number) print("birth_date",birth_date) print("expiry_date",expiry_date) print("file path",filepath) print("compte_ccp",compte_ccp) # 保存MRZ数据到数据库 mrz = MRZ.objects.create( FK_compte_ccp=compte_ccp, photo_passport=filepath, document_number=document_number, birth_date=birth_date, expiry_date=expiry_date ) print("MRZ enregistrée avec succès.") return JsonResponse({'message': 'MRZ enregistrée avec succès'}, status=201) else: return JsonResponse({'message': 'Aucune image reçue'}, status=403) else: return JsonResponse({'message': 'Token JWT manquant'}, status=404) except jwt.ExpiredSignatureError: return JsonResponse({'message': 'Token JWT expiré'}, status=401) except jwt.InvalidTokenError: return JsonResponse({'message': 'Token JWT invalide'}, status=401) except CompteCcp.DoesNotExist: return JsonResponse({'message': 'Aucun compte CCP trouvé pour cet utilisateur'}, status=404) except Exception as e: # 添加打印查看具体异常信息 print("Erreur détaillée :", str(e)) return JsonResponse({'message': str(e)}, status=400) else: return JsonResponse({'message': 'Méthode HTTP non autorisée'}, status=405)
服务器日志
Données reçues : <QueryDict: {'document_number': ['308491574'], 'birth_date': ['2001-08-27T00:00:00.000'], 'expiry_date': ['2033-01-08T00:00:00.000']}> Token JWT récupéré : eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMCwidXNlcm5hbWUiOiJyaXNlMkBnbWFpbC5jb20iLCJleHAiOjE3MTQ4MjQ2MDMsImVtYWlsIjoicmlzZTJAZ21haWwuY29tIn0.38Afbpt0HNAbkY_PdXZ5sPN1ObtjFoa5JtkLmGfVwhw Token JWT decoder : {'user_id': 10, 'username': 'rise2@gmail.com', 'exp': 1714824603, 'email': 'rise2@gmail.com'} user id : 10 documebt_number 308491574 birth_date 2001-08-27 expiry_date 2033-01-08 file path C:\Users\morsi\Documents\python\Poste_Projet\media\10\MRZ.jpg Bad Request: /compte/api/remplir_mrz/ [04/May/2024 12:11:17] "POST /compte/api/remplir_mrz/ HTTP/1.1" 400 63
排查与解决方案
1. 模型字段名与视图传入字段不匹配
MRZ模型中日期和文档编号字段为驼峰命名:birthDate、documentNumber、expiryDate,但视图创建对象时使用下划线命名:birth_date、document_number、expiry_date。Django ORM会严格匹配字段名,这会导致字段无法赋值,触发验证错误。
解决方法:
- 方案一:修改模型字段为下划线命名(符合Django惯例):
birth_date = models.DateField(null=True, blank=True) document_number = models.CharField(max_length=100, null=True, blank=True) expiry_date = models.DateField(null=True, blank=True) - 方案二:视图创建对象时使用模型的驼峰字段名:
mrz = MRZ.objects.create( FK_compte_ccp=compte_ccp, photo_passport=photo_relative_path, documentNumber=document_number, birthDate=birth_date, expiryDate=expiry_date )
2. ImageField赋值错误
模型中photo_passport是ImageField,需传入相对MEDIA_ROOT的路径或UploadedFile对象,视图中传入的本地绝对路径filepath会导致Django无法正确处理文件存储,触发字段验证错误。
解决方法:
直接使用上传的文件对象(推荐),或构造相对路径:
# 直接传入UploadedFile对象 mrz = MRZ.objects.create( FK_compte_ccp=compte_ccp, photo_passport=image_file, documentNumber=document_number, birthDate=birth_date, expiryDate=expiry_date )
如果需要自定义存储路径,可修改模型的upload_to为动态路径:
def user_mrz_path(instance, filename): return f'{instance.FK_compte_ccp.FK_compte_app.id}/MRZ.jpg' class MRZ(models.Model): # ...其他字段 photo_passport = models.ImageField(upload_to=user_mrz_path)
3. 查看具体异常信息
当前视图的全局异常捕获仅返回错误信息,但未打印具体内容。建议在except Exception as e块中添加打印语句,快速定位错误点:
except Exception as e: print("Erreur détaillée :", str(e)) return JsonResponse({'message': str(e)}, status=400)
内容的提问来源于stack exchange,提问作者ahmedkr
相关产品推荐
相关产品推荐

