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

执行makemigrations时Django表单触发AttributeError异常

问题排查:执行makemigrations时触发AttributeError错误

错误回溯信息

File "/Users/luketimothy/Library/Mobile Documents/com~apple~CloudDocs/LifePlanner/LifePlanner/LifePlanner/urls.py", line 20, in <module>
    from . import views
  File "/Users/luketimothy/Library/Mobile Documents/com~apple~CloudDocs/LifePlanner/LifePlanner/LifePlanner/views.py", line 7, in <module>
    from .forms import AppUserForm, IncomeSourceForm, AccountForm, SpouseForm, DependentForm
  File "/Users/luketimothy/Library/Mobile Documents/com~apple~CloudDocs/LifePlanner/LifePlanner/LifePlanner/forms.py", line 32, in <module>
    class AccountForm(forms.ModelForm):
  File "/Users/luketimothy/Library/Mobile Documents/com~apple~CloudDocs/LifePlanner/LifePlanner/ProjectEnv/lib/python3.11/site-packages/django/forms/models.py", line 312, in __new__
    fields = fields_for_model(
             ^^^^^^^^^^^^^^^^^
  File "/Users/luketimothy/Library/Mobile Documents/com~apple~CloudDocs/LifePlanner/LifePlanner/ProjectEnv/lib/python3.11/site-packages/django/forms/models.py", line 237, in fields_for_model
    formfield = f.formfield(**kwargs)
                ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/luketimothy/Library/Mobile Documents/com~apple~CloudDocs/LifePlanner/LifePlanner/ProjectEnv/lib/python3.11/site-packages/django/db/models/fields/related.py", line 1165, in formfield
    "queryset": self.remote_field.model._default_manager.using(using),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'using'

相关代码片段

forms.py 中的 AccountForm

class AccountForm(forms.ModelForm):
    class Meta:
        model = Account
        fields = ['account_name','owner','account_provider','balance']
        labels = {'account_name': 'Name','account_provider': 'Account Provider','balance': 'Balance','owner': 'Owner'}

models.py 相关模型

class Projectable(models.Model):
    class Meta:
        abstract = True

    def project_annual_values(self, years):
        raise NotImplementedError("Subclasses should implement this method.")

    def project_monthly_values(self, months):
        raise NotImplementedError("Subclasses should implement this method.")

class AccountProvider(models.Model):
    name = models.CharField(max_length=64)
    web_url = models.CharField(max_length=256)
    login_url = models.CharField(max_length=256)
    logo_file= models.CharField(max_length=64)
    
    def __str__(self):
        return f"{self.name}"

class Account(Projectable):
    account_name = models.CharField(max_length=100)
    balance = models.DecimalField(max_digits=15, decimal_places=2)
    owner = models.ForeignKey(Agent, on_delete=models.CASCADE)
    account_provider = models.ForeignKey(AccountProvider, on_delete=models.SET_NULL)

    def get_balance(self):
        return self.balance

    def get_account_type(self):
        raise NotImplementedError("Subclasses should implement this method.")

Agent 抽象模型

class Agent(models.Model):
    retirement_age = models.IntegerField()
    date_of_birth = models.DateField()
    name = models.CharField(max_length=100)

    class Meta:
        abstract = True

问题原因

核心问题在于Account模型的owner字段直接关联了抽象模型Agent。Django的外键字段要求关联实际存在的数据表模型,而抽象模型不会生成数据表,也没有对应的模型管理器,导致Django无法解析owner字段的关联目标,最终出现remote_field.model为None的情况,触发AttributeError。

另外,account_provider字段使用了on_delete=models.SET_NULL但未设置null=True,这也是潜在问题,后续迁移时会报错。

解决方法

方案1:将Agent改为非抽象模型

如果Agent需要作为独立的数据表存在,直接移除其Meta类中的abstract = True:

class Agent(models.Model):
    retirement_age = models.IntegerField()
    date_of_birth = models.DateField()
    name = models.CharField(max_length=100)

    # 移除抽象模型设置
    # class Meta:
    #     abstract = True

同时给account_provider字段补充null=True:

account_provider = models.ForeignKey(AccountProvider, on_delete=models.SET_NULL, null=True)

方案2:使用GenericForeignKey关联Agent的子类

如果Agent必须作为抽象模型,供多个子类(如AppUser、Spouse)继承,那么需要用GenericForeignKey来实现关联:

  1. 先导入必要的模块:
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
  1. 修改Account模型的owner字段:
class Account(Projectable):
    account_name = models.CharField(max_length=100)
    balance = models.DecimalField(max_digits=15, decimal_places=2)
    # 替换原有的外键字段
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    owner = GenericForeignKey('content_type', 'object_id')
    # 补充null=True
    account_provider = models.ForeignKey(AccountProvider, on_delete=models.SET_NULL, null=True)

    def get_balance(self):
        return self.balance

    def get_account_type(self):
        raise NotImplementedError("Subclasses should implement this method.")

修改完成后,重新执行makemigrations和migrate命令即可。

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:55:13