Django创建模型对象时外键报错问题求助
外键关联错误导致数据库写入失败的问题解决
问题报错
Field 'building_id' expected a number but got <SimpleLazyObject: <User: Vladimir>>
核心错误点
模型外键关联错误:你的
BuildingFilesVersions模型中,user字段错误关联了Building模型,而非用户模型User。这导致你传入request.user(User对象)时,Django误以为要给关联Building的外键字段赋值,触发类型不匹配报错。视图字段赋值错误:
filename = form.cleaned_data["modification_type"]:错误将修改类型赋值给文件名,应该取表单中对应的文件名字段,或直接用上传文件的原始名称。file = request.FILES['file'].name:FileField需要接收文件对象而非文件名,直接传request.FILES['file']才能完成文件上传。
外键赋值写法冗余:创建对象时,
user_id=request.user可简化为user=request.user(Django会自动处理主键关联);若用_id后缀则需传入主键值,比如user_id=request.user.id。
修正后的代码
模型代码
from django.contrib.auth.models import User from pathlib import Path def upload_path(instance, file): file_dir = Path(file).stem print('usr', instance.user.id) path = '{}/{}/{}/{}'.format(instance.user.id, "projects", file_dir, file) return path class BuildingFilesVersions(models.Model): version_id = models.AutoField(primary_key=True) building_id = models.ForeignKey(Building, on_delete=models.CASCADE, related_name='building_id_file') # 将外键关联改为User模型 user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user_file") created_at = models.DateTimeField(auto_now_add=True, blank=True) description = models.TextField(max_length=200, blank=True, null=True) modification_type = models.CharField(choices=WORK_TYPE_CHOICES, max_length=200, blank=True, null=True) filename = models.CharField(max_length=200, blank=True, null=True) file = models.FileField(upload_to=upload_path, null=True, blank=True)
视图代码
@login_required @owner_required def RegisterFileView(request,pk): form = AddBuildingFileForm() if request.method == 'POST': form = AddBuildingFileForm(request.POST, request.FILES) if form.is_valid(): description = form.cleaned_data["description"] modification_type = form.cleaned_data["modification_type"] # 修正文件名取值,优先取表单输入,否则用上传文件的原始名称 filename = form.cleaned_data.get("filename") or request.FILES['file'].name # 直接传递文件对象给FileField file_obj = request.FILES['file'] BuildingFilesVersions.objects.create( building_id_id=pk, user=request.user, # 直接传入User实例,Django自动处理外键关联 description=description, modification_type=modification_type, filename=filename, file=file_obj ) return redirect('home') # 保留错误表单,方便前端显示校验错误 context = {'form':form} return render(request, 'building_registration/register_file.html', context)
补充说明
- 修正模型的外键关联是解决报错的关键,之前的错误关联让Django把User对象错误对应到了Building的外键字段上。
- 视图中不要在form验证失败时重新实例化表单,否则会丢失已输入的内容和错误提示,直接保留验证后的form即可。
内容的提问来源于stack exchange,提问作者Murcielago
相关产品推荐
相关产品推荐

