【问题标题】:Django failing to cascade-delete related generic foreign key objectDjango 未能级联删除相关的通用外键对象
【发布时间】:2016-05-05 15:01:18
【问题描述】:

我的模型中定义了以下内容:

class TaskLink(models.Model):
    task = model.ForeignKey(Task)
    link_choices = (
        models.Q(app_label="accounts", model="location"),
        # Other models are also linked to here.
    )
    linked_content_type = \
        models.ForeignKey(
            ContentType,
            limit_choices_to=link_choices
        )
    linked_object_id = models.PositiveIntegerField()
    linked_object = \
        generic.GenericForeignKey(
            'linked_object_content_type',
            'linked_object_id'
        )

此模型将 Task 对象与 link_choices 元组中的任何模型链接。在这种情况下,accounts.Location 模型在此列表中。

当删除Location 对象导致相关TaskLink 对象的级联删除时,我的问题就出现了。删除失败并显示以下错误消息:

django.core.exceptions.FieldError: Cannot resolve keyword 'object_id' into field. Choices are: id, linked_object, linked_object_content_type, linked_object_content_type_id, linked_object_id, task, task_id

视图是django.views.generic.DeleteView 的实例,只有pk_url_kwarg 参数和模型集(以及添加到调度方法的权限装饰器);在我将 TaskLink 模型添加到组合中之前,它已经工作了linked_object_fine。

我错过了什么?

编辑:这似乎是 Django 中的一个错误;当通过通用外键级联删除对象时,Django 会忽略您传递给 GenericForeignKey 字段的构造函数的字段名称字符串,而是寻找 content_typeobject_id 字段,在我的情况下,没有存在。这有效地将模型可能必须的通用外键数量限制为 1,除非您不会遇到级联删除。

我已通过 Django 邮件列表发送此问题,因为该行为可能是故意的。

【问题讨论】:

    标签: django cascade django-class-based-views generic-foreign-key


    【解决方案1】:

    重命名TaskLink的字段名

    linked_content_type >>> content_type
    linked_object_id >>> object_id
    

    或在删除“Location”对象时写入预信号以删除链接对象“TaskLink”

    from django.db.models.signals import pre_delete
    from django.dispatch import receiver
    
    @receiver(pre_delete, sender=Location, dispatch_uid='location_delete_signal')
    def deleted_gfk_TaskLink(sender, instance, using, **kwargs):
        ctype = ContentType.objects.get_for_model(sender)
        obj = TaskLink.objects.get(linked_content_type=ctype, linked_object_id=instance.id)
        obj.delete()
    

    自定义信号参考:
    https://micropyramid.com/blog/using-djangos-built-in-signals-and-writing-custom-signals/

    【讨论】:

    • 标记为答案,因为这解决了我的问题,但我认为重要的是要注意:如果你打算依赖级联,Django 处理通用外键的方式会阻止模型拥有多个-删除。
    猜你喜欢
    • 2020-10-27
    • 2012-09-21
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-23
    • 2011-10-12
    • 1970-01-01
    相关资源
    最近更新 更多