在 Django 查询集中过滤不存在的 GenericForeignKey 对象
Filter non-existing GenericForeignKey objects in Django queryset
我有一个带有通用外键的简单模型:
class Generic(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
我想过滤此 table 中具有 非空 content_object
的所有条目,即过滤掉 [=] 的所有实例13=] 其 内容对象不再存在 :
Generic.objects.filter(~Q(content_object=None))
这不起作用,给出异常:
django.core.exceptions.FieldError: Field 'content_object' does not
generate an automatic reverse relation and therefore cannot be used
for reverse querying. If it is a GenericForeignKey, consider adding a
GenericRelation.
向引用的内容类型模型添加 GenericRelation
没有任何区别。
任何有关如何实现此目的的帮助将不胜感激,非常感谢。
编辑:我知道我可以级联删除,但是在我的情况下这不是一个选项(我希望保留数据)。
如果要过滤掉一些记录out,通常使用exclude()
方法比较好:
Generic.objects.exclude(object_id__isnull=True)
不过请注意,您的模型现在不允许空 content_object
字段。要更改此行为,use 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))
这可以用作 one-time 脚本,但不是一个可靠的解决方案。如果你绝对想保留数据,我能想到的唯一快速方法是在你的 Generic
模型中有一个 is_deleted
布尔标志并将其设置在 (post|pre)_delete
信号中。
我有一个带有通用外键的简单模型:
class Generic(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
我想过滤此 table 中具有 非空 content_object
的所有条目,即过滤掉 [=] 的所有实例13=] 其 内容对象不再存在 :
Generic.objects.filter(~Q(content_object=None))
这不起作用,给出异常:
django.core.exceptions.FieldError: Field 'content_object' does not generate an automatic reverse relation and therefore cannot be used for reverse querying. If it is a GenericForeignKey, consider adding a GenericRelation.
向引用的内容类型模型添加 GenericRelation
没有任何区别。
任何有关如何实现此目的的帮助将不胜感激,非常感谢。
编辑:我知道我可以级联删除,但是在我的情况下这不是一个选项(我希望保留数据)。
如果要过滤掉一些记录out,通常使用exclude()
方法比较好:
Generic.objects.exclude(object_id__isnull=True)
不过请注意,您的模型现在不允许空 content_object
字段。要更改此行为,use 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))
这可以用作 one-time 脚本,但不是一个可靠的解决方案。如果你绝对想保留数据,我能想到的唯一快速方法是在你的 Generic
模型中有一个 is_deleted
布尔标志并将其设置在 (post|pre)_delete
信号中。