You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django创建模型对象时外键报错问题求助

外键关联错误导致数据库写入失败的问题解决

问题报错

Field 'building_id' expected a number but got <SimpleLazyObject: <User: Vladimir>>

核心错误点

  1. 模型外键关联错误:你的BuildingFilesVersions模型中,user字段错误关联了Building模型,而非用户模型User。这导致你传入request.user(User对象)时,Django误以为要给关联Building的外键字段赋值,触发类型不匹配报错。

  2. 视图字段赋值错误:

    • filename = form.cleaned_data["modification_type"]:错误将修改类型赋值给文件名,应该取表单中对应的文件名字段,或直接用上传文件的原始名称。
    • file = request.FILES['file'].name:FileField需要接收文件对象而非文件名,直接传request.FILES['file']才能完成文件上传。
  3. 外键赋值写法冗余:创建对象时,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 08:40:28