Django迁移报错ValueError: Field 'id' expected a number but got 'company'问题求助
解决Django迁移时ValueError: Field 'id' expected a number but got 'company'的问题
嘿,我一眼就瞅出问题出在哪了——你模型里的外键字段全用了字符串默认值,但Django的外键字段本质是存储关联模型的主键ID(整数类型),你给它传个字符串"company"或者"agent",它肯定转不成整数,这不就触发ValueError了嘛!
咱们一步步来修正:
问题定位:所有错误的外键默认值
你这些模型里的外键都犯了同样的错:
Client模型的company = models.ForeignKey(Company, ..., default="company")Leads模型的company、agent字段CallReport模型的company、client_POC、ACTeQ_representative字段Deal模型的project_id、agent、client字段
这些外键的default参数都设成了字符串,但Django需要的是关联模型的主键数字。
解决方案:三种修正方式
根据你的业务需求选一种就行:
方式1:允许外键为空(最简单,适合非必填字段)
如果这些外键不是必填项,直接去掉字符串默认值,加上blank=True, null=True,让字段允许为空:
# 以Client模型为例,其他模型同理 class Client(models.Model): firstname = models.CharField(blank=True, max_length=30) lastname = models.CharField(blank=True, max_length=15) # 修正后的外键字段 company = models.ForeignKey(Company, on_delete=models.CASCADE, blank=True, null=True) position = models.CharField(blank=True, max_length=15) country = CountryField(blank_label='(select country)') email = models.EmailField(blank=True, max_length=100, default="this_is@n_example.com") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) phone = PhoneField(default="(XX)-XXX-XXX") def __str__(self): return f'{self.firstname}'
方式2:指定固定的主键ID作为默认值
如果你需要一个固定的默认关联实例,先在数据库里创建好对应的记录(比如先手动创建一个名为"Default Company"的Company实例),然后把default设为它的主键ID:
# 假设默认Company的id是1 company = models.ForeignKey(Company, on_delete=models.CASCADE, default=1)
⚠️ 注意:必须确保数据库里存在这个ID的记录,否则迁移还是会失败。
方式3:用可调用函数动态获取默认值(最灵活)
这种方式会自动创建默认实例(如果不存在的话),适合需要确保默认实例存在的场景:
# 先定义获取默认Company的函数 def get_default_company(): # 查找或创建默认公司实例,避免重复创建 default_company, created = Company.objects.get_or_create(company="Default Company") return default_company.id class Client(models.Model): # ... company = models.ForeignKey(Company, on_delete=models.CASCADE, default=get_default_company) # ...
同样的逻辑可以用到Profile的外键上,比如创建一个默认的"Agent" Profile实例。
修正后的迁移步骤
- 先运行
python manage.py makemigrations生成新的迁移文件,这次会包含外键默认值的修正; - 再运行
python manage.py migrate,这次就能正常执行迁移了。
额外提醒
- 如果你选了方式1(允许为空),要确保业务逻辑能处理这些字段为空的情况;
- 所有外键字段都要按上面的方式修正,不能只改一个,不然其他字段还是会报错。
内容的提问来源于stack exchange,提问作者Francisco Colina
相关产品推荐
相关产品推荐

