django - 不可散列类型 : 'list' error when trying to add

我的内容模型与标签模型具有多对多关系。当我保存内容对象时,我想动态添加关系。我按照以下方式执行此操作。

def tag_content(obj):
    obj.tags.add([1,2,3])
    obj.is_tagged = True
    obj.save()
    return obj

class Tag(models.Model):
    name = models.CharField(max_length=255)

class Content(models.Model):
    title = models.CharField(max_length=255)
    is_tagged = models.BooleanField(default=False)
    tags = models.ManyToManyField(Tag, blank=True)

    def save(self, *args, **kwargs):
        super(Content, self).save(*args, **kwargs)

@receiver(post_save, sender = Content)
def update_m2m_relationships_on_save(sender, **kwargs):
    if not kwargs['instance'].is_tagged:
        tag_content(kwargs['instance'])

基本上,当保存内容对象时,接收器用于调用 post_save 方法,该方法又调用 tag_content 方法来添加 m2m 关系。但是,我收到此错误:

TypeError
unhashable type: 'list'

它专门引用了 .add() 函数。知道为什么我会收到此错误吗?任何帮助表示赞赏。另外,请注意我在数据库中有 ID = 1、2 和 3 的 Tag 对象。

编辑

好吧,我把我的 tag_content 改成了这样:

def tag_content(obj):
    for tag in Tag.objects.all():
        print tag
        obj.tags.add(tag)

这是因为 add() 方法接收对象实例,而不是 ID。但是,它仍然不起作用:/我没有收到任何错误,但根本没有建立关系。

这特别奇怪,因为 print tag 命令起作用并打印出标签。换句话说,函数正在被调用。有什么帮助吗?顺便说一句,我正在运行 Django 1.9.8。

最佳答案

您不能将列表传递给 add(),这就是您收到错误的原因。您要么需要一次添加一个项目,要么将列表扩展为一系列参数,例如:

obj.tags.add(*[1,2,3]) # The * expands the list into the function arguments

这仍然会导致错误,因为您不能将 ID 传递给 add() - 您必须将 Tag 对象传递给它。所以这样的事情会起作用:

# Get a list of Tag objects
tags_to_add = [Tag.objects.get(id=j) for j in [1, 2, 3]]
# Now pass this to the add() function:
obj.tags.add(*tags_to_add)

关于django - 不可散列类型 : 'list' error when trying to add m2m relationships dynamically using post_save in Django,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39099197/

相关文章:

python - 如何通过 Django 查看上传的文本文件?

python - 如何为使用 gmail 发送的电子邮件添加主题?

html - 隐藏来自 HTML 电子邮件的预览文本的内容

angular - 在 Angular 2 模板中使用普通 POST 表单会导致 : "Templa

SQL - 如何在 UNION 查询中排序

laravel - 为什么在 Laravel 中注销路由不起作用?

scala - Akka 流 : Can not write to file sink

fortran - IF 和 ENDIF 之前的 # 是什么意思

json - 使用 JOLT 转换重命名嵌套数组中的字段

php - 使用 openssl_encrypt 代替 Mcrypt 进行 3DES-ECB 加密