Django删除C模型实例触发FieldError:无法解析content_type字段
Django 删除继承模型时 FieldError 问题解决
问题场景
定义了如下Django模型类,执行C实例的delete()方法时抛出字段解析错误:
from django.db import models from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.utils.timezone import now class A(models.Model): created_time = models.DateTimeField(default=now, null=True, blank=True) t = GenericRelation(T, object_id_field='object_id', content_type_field='content_type', related_query_name='a') class B(A): state_path = models.CharField(max_length=256, blank=True, verbose_name="State Path") f = GenericRelation(F, content_type_field='content_type', object_id_field='object_id', related_query_name='b') class C(B): choice = models.BooleanField(default=False, verbose_name="Enabled") class T(models.Model): created_time = models.DateTimeField(auto_now_add=True, verbose_name="Created Time") content_type = models.ForeignKey(ContentType, null=True, blank=True, on_delete=models.DO_NOTHING) object_id = models.PositiveIntegerField(null=True, blank=True) a = GenericForeignKey('content_type', 'object_id') class E(models.Model): username = models.CharField(max_length=128, verbose_name="Username") key = models.TextField(blank=True, verbose_name="Key") class F(E): content_type = models.OneToOneField(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() b = GenericForeignKey('content_type', 'object_id') # 执行删除操作时出错 c = C.objects.get(pk=c_id) c.delete()
错误信息
django.core.exceptions.FieldError: Cannot resolve keyword 'content_type' into field. Choices are: id
原因分析
删除C实例时,Django会自动清理其关联的GenericRelation对象(即B类中定义的f关联)。由于F采用多表继承自E,Django在处理反向关联查询时,错误地使用了父类E的模型进行查询,而E中并没有content_type字段,因此抛出字段解析错误。
解决方案
方案1:将父类E改为抽象基类
把E设置为抽象基类,这样F会直接继承E的字段到自身数据表中,不会生成单独的E表,查询时就能正确找到content_type字段:
class E(models.Model): username = models.CharField(max_length=128, verbose_name="Username") key = models.TextField(blank=True, verbose_name="Key") class Meta: abstract = True # 标记为抽象基类 class F(E): content_type = models.OneToOneField(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() b = GenericForeignKey('content_type', 'object_id')
方案2:调整GenericRelation参数
如果保留多表继承结构,可在B类的GenericRelation中添加for_concrete_model=False参数,确保查询指向子类F而非父类E:
class B(A): state_path = models.CharField(max_length=256, blank=True, verbose_name="State Path") f = GenericRelation( F, content_type_field='content_type', object_id_field='object_id', related_query_name='b', for_concrete_model=False # 指定关联非具体模型 )
两种方案任选其一后,重新执行删除操作即可正常运行。
内容的提问来源于stack exchange,提问作者Jepsenwan
相关产品推荐
相关产品推荐

