【问题标题】:Django models - assign id instead of objectDjango 模型 - 分配 id 而不是对象
【发布时间】:2012-10-01 22:54:05
【问题描述】:

如果我的问题被证明是愚蠢的,我深表歉意,但我对 Django 很陌生,我无法在任何地方找到答案。

我有以下型号:

class BlackListEntry(models.Model):
  user_banned = models.ForeignKey(auth.models.User,related_name="user_banned")
  user_banning = models.ForeignKey(auth.models.User,related_name="user_banning")

现在,当我尝试创建这样的对象时:

BlackListEntry.objects.create(user_banned=int(user_id),user_banning=int(banning_id))

我收到以下错误:

Cannot assign "1": "BlackListEntry.user_banned" must be a "User" instance.

当然,如果我用这样的东西替换它:

user_banned = User.objects.get(pk=user_id)
user_banning = User.objects.get(pk=banning_id)
BlackListEntry.objects.create(user_banned=user_banned,user_banning=user_banning)

一切正常。问题是:

我的解决方案是否会访问数据库以检索两个用户,如果是,是否可以避免它,只传递 id?

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    您的问题的答案是:是的。

    Django 将访问数据库(至少)3 次,其中 2 次检索两个 User 对象,第三次提交您想要的信息。这将导致绝对不必要的开销。

    试试吧:

    BlackListEntry.objects.create(user_banned_id=int(user_id),user_banning_id=int(banning_id))
    

    这些是 Django ORM 生成的 FK 字段的默认名称模式。这样就可以直接设置信息,避免查询。

    如果要查询已保存的 BlackListEntry 对象,可以使用双下划线导航属性,如下所示:

    BlackListEntry.objects.filter(user_banned__id=int(user_id),user_banning__id=int(banning_id))
    

    这是您在 Django 查询集中访问属性的方式。带有双下划线。然后就可以比较属性的值了。

    虽然非常相似,但它们的工作方式完全不同。第一个直接设置属性,第二个由django解析,在'__'处拆分,并以正确的方式查询数据库,第二部分是属性的名称。

    您始终可以将user_banneduser_banning 与实际的用户对象进行比较,而不是他们的ID。但是,如果您还没有这些物品,那么这样做是没有用的。

    希望对你有帮助。

    【讨论】:

    • 这给了我:'user_banning__id' 是这个函数的无效关键字参数
    • 对不起,我刚刚意识到您正在创建对象。因此,您需要使用单个下划线进行访问。我将编辑我的答案以解释原因。
    • 谢谢,现在可以了。我会加你+1,但我太笨了,还不能这样做。
    • 没问题。很高兴它有帮助。
    【解决方案2】:

    我确实相信,当您获取用户时,它会命中数据库...

    为避免这种情况,您必须编写原始 sql 以使用此处描述的方法进行更新:

    https://docs.djangoproject.com/en/dev/topics/db/sql/

    如果您决定走这条路,请记住您有责任保护自己免受 sql 注入攻击。

    另一种选择是缓存 user_banned 和 user_banning 对象。

    但很可能,简单地抓取用户并创建 BlackListEntry 不会给您带来任何明显的性能问题。缓存或执行原始 sql 只会带来一点好处。在这成为问题之前,您可能会遇到其他问题。

    【讨论】:

      猜你喜欢
      • 2020-12-18
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 2014-12-23
      • 1970-01-01
      • 2016-07-03
      • 2021-09-27
      • 2013-01-18
      相关资源
      最近更新 更多