Ben*_*Ben 6 python django django-queryset django-generic-views django-contenttypes
我有一个带有通用外键的简单模型:
class Generic(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
Run Code Online (Sandbox Code Playgroud)
我想过滤此表中具有非null content_object的所有条目,即过滤掉Generic其内容对象不再存在的所有实例:
Generic.objects.filter(~Q(content_object=None))
Run Code Online (Sandbox Code Playgroud)
这不起作用,给出例外:
django.core.exceptions.FieldError:字段'content_object'不生成自动反向关系,因此不能用于反向查询.如果是GenericForeignKey,请考虑添加GenericRelation.
添加GenericRelation到引用的内容类型模型没有区别.
如何实现这一点的任何帮助将不胜感激,非常感谢.
编辑:我意识到我可以级联删除,但在我的情况下这不是一个选项(我希望保留数据).
如果你想一些记录筛选出来,它通常最好使用exclude()方法:
Generic.objects.exclude(object_id__isnull=True)
Run Code Online (Sandbox Code Playgroud)
但请注意,您的模型现在不允许空content_object字段.要更改此行为,请使用null=True两者object_id和content_type字段的参数.
好的,既然问题已经从过滤掉空记录转移到确定破坏的RDBMS引用而没有RDBMS本身的帮助,我建议一个(相当慢和内存饥饿)的解决方法:
broken_items = []
for ct in ContentType.objects.all():
broken_items.extend(
Generic.objects
.filter(content_type=ct)
.exclude(object_id__in=ct.model_class().objects.all())
.values_list('pk', flat=True))
Run Code Online (Sandbox Code Playgroud)
这可以作为一次性脚本,但不是一个强大的解决方案.如果你绝对想要保留数据,我能想到的唯一快速方法是is_deleted在Generic模型中使用布尔标志并将其设置为(post|pre)_delete信号.