为啥我的“多对多” Django 模型中的 Django 的“add()”方法不采用?

Posted

技术标签:

【中文标题】为啥我的“多对多” Django 模型中的 Django 的“add()”方法不采用?【英文标题】:Why is Django's `add()` method in my `many-to-many` Django models not taking?为什么我的“多对多” Django 模型中的 Django 的“add()”方法不采用? 【发布时间】:2017-10-29 02:40:28 【问题描述】:

问题/问题:

我正在构建一个 Django 应用程序,有 2 个模型:UserSecret。秘密可以由用户制作,其他用户可以“喜欢”它们。我已将我的likes 字段设置为ManyToManyField,以便可以将喜欢秘密的用户存储在那里并稍后检索等。但是,当我尝试查询用户和秘密并使用my_secret.likes.add(my_User) 什么都没有发生。我没有收到错误消息,当我打印我的 Secret 的 many-to-many likes 字段时,添加后,我看到:secrets.User.None

为什么我的 add() 方法正在运行,但我没有收到任何错误,为什么我的用户没有正确添加到我的 Secret 点赞中?

注意:我在初始创建时保存了 User 和 Secret 对象。在这个应用程序之外,我可以很好地使用 add() 方法,但在那些场景中,我当时正在创建对象,而不是检索已经存在的对象。

在使用从查询中检索到的数据时,是否有不同的方法来处理 add()?这是我目前唯一的其他推理方式,我完全按照这里的文档进行操作:Django Many-to-Many Docs

如果网站上的其他地方回答了这个问题,我也很抱歉。我确实找到了一个other post here,但没有提供解决方案,因为他们遇到了完全相同的问题。

我的模特:

class User(models.Model):
    """
    Creates instances of a `User`.

    Parameters:
    -`models.Model` - Django's `models.Model` method allows us to create new models.
    """

    first_name = models.CharField(max_length=50) # CharField is field type for characters
    last_name = models.CharField(max_length=50)
    email = models.CharField(max_length=50)
    password = models.CharField(max_length=22)
    created_at = models.DateTimeField(auto_now_add=True) # DateTimeField is field type for date and time
    updated_at = models.DateTimeField(auto_now=True) # note the `auto_now=True` parameter
    objects = UserManager() # Attaches `UserManager` methods to our `User.objects` object.

class Secret(models.Model):
    """
    Creates instances of a `Secret`.

    Parameters:
    -`models.Model` - Django's `models.Model` method allows us to create new models.
    """

    description = models.CharField(max_length=100) # CharField is field type for characters
    user = models.ForeignKey(User, related_name="secrets") # One-to-Many Relationship
    likes = models.ManyToManyField(User) # Many to Many Relationship
    created_at = models.DateTimeField(auto_now_add=True) # DateTimeField is field type for date and time
    updated_at = models.DateTimeField(auto_now=True) # note the `auto_now=True` parameter
    objects = SecretManager() # Attaches `SecretManager` methods to our `Secret.objects` object.

问题示例:

模型迁移得很好,一切似乎都在正确的语法中。但是,当我尝试检索 UserSecret,并将 User 添加到 Secret.likes 时,add() 方法没有给出错误,运行,但没有保存任何对象。

这是一个例子:

tim = User.objects.get(email="tim@tim.com") # Gets a user object
my_secret = Secret.objects.get(id=2) # Gets a secret object
# This is where nothing seems to happen / take:
my_secret.likes.add(tim) # add() method per Django many-to-many docs
print my_secret.likes # returns: `secrets.User.None` -- why?

为什么上面打印my_secret.likes时,什么都没有打印出来?

尤其是在: tim.secret_set.all() 显示了包含id=2 的秘密,如上例所示......所以User 正在记录与Secret 的关系,但Secret 没有记录与User 的任何关系.我做错了什么?

【问题讨论】:

尝试 appendupdate 代替添加 @hansTheFranz 非常感谢您尝试帮助我。我刚才确实尝试使用append() 代替add(),并收到此错误:AttributeError: 'ManyRelatedManager' object has no attribute 'append'。我也尝试使用update() 并收到此错误:TypeError: update() takes exactly 1 argument (2 given)。使用与我的帖子完全相同的格式,只是将 add 方法替换为您描述的方法!可惜还在这里战斗! 【参考方案1】:

您需要调用多对多字段的all方法来查看所有相关的对象:

print my_secret.likes.all()
#                     ^^^^^

【讨论】:

....我的朋友,我为这个 LOL 折磨自己的几个小时,你是来自天空的天使,带着真理的信息!这有效,正是我所缺少的!为我如何错过如此基本的东西而感到愚蠢,非常感谢你!如果可以的话会给你+1^10000!!!

以上是关于为啥我的“多对多” Django 模型中的 Django 的“add()”方法不采用?的主要内容,如果未能解决你的问题,请参考以下文章

模板中的多对多通过模型中的 Django 访问条目

如何以 django 形式过滤多对多字段

使 ModelForm 与 Django 中的中间模型的多对多关系工作的步骤是啥?

Django:按多对多字段订购模型

Django:通过另一个多对多关系访问多对多对象

Django中的多对多查找