如果我从模型中检索到对象,例如:
obj = Foo.objects.first()
我知道如果我想稍后引用此对象并确保它具有数据库中的当前值,我可以调用:
obj.refresh_from_db()
我的问题是,使用refresh_from_db()
方法而不仅仅是做有什么好处吗?:
obj = Foo.objects.get(id=obj.id)
据我所知,结果将是相同的。 refresh_from_db()
似乎更明确,但在某些情况下,它意味着额外的代码行。假设我更新了value
的{{1}}字段,后来想要测试它已更新为obj
。比较:
False
用这个:
obj = Foo.objects.first()
assert obj.value is True
# value of foo obj is updated somewhere to False and I want to test below
obj.refresh_from_db()
assert obj.value is False
我对讨论两者中哪一个更具pythonic不感兴趣。相反,我想知道一种方法在资源,性能等方面是否具有实际优势。我已阅读this bit of documentation,但我无法确定使用obj = Foo.objects.first()
assert obj.value is True
# value of foo obj is updated somewhere to False and I want to test below
assert Foo.objects.get(id=obj.id).value is False
是否有优势。谢谢!
答案 0 :(得分:4)
Django来源通常比较容易理解。如果我们查看refresh_from_db() implementation,其核心仍然是使用相同的Foo.objects.get(id=obj.id)
方法:
db_instance_qs = self.__class__._default_manager.using(db).filter(pk=self.pk)
...
db_instance_qs = db_instance_qs.only(*fields)
...
db_instance = db_instance_qs.get()
只有几个额外的花里胡哨:
因此,对于日常使用,可以安全地说它们几乎相同,使用你喜欢的任何东西。
答案 1 :(得分:0)
只是添加到@serg的答案中,在某些情况下,从数据库中显式重新获取会有所帮助,而从数据库中进行刷新并不是那么有用。
在向对象添加权限并在此之后立即检查权限时,就是这种情况,您需要清除该对象的缓存权限,以便您的权限检查能够按预期进行。
根据the permission caching section of the django documentation:
第一次需要获取权限检查之后,ModelBackend会在用户对象上缓存权限。这通常适合请求-响应周期,因为通常不会在添加权限后立即检查权限(例如,在管理员中)。如果要添加权限并随后立即检查权限,例如在测试或视图中,最简单的解决方案是从数据库中重新获取用户...
举个例子,考虑一下上面引用的文档中的代码块:
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from smoothies.models import Smoothie
def force_deblend(user, smoothie):
# Any permission check will cache the current set of permissions
if not user.has_perm('smoothies.deblend_smoothie'):
permission = Permission.objects.get(
codename='deblend_smoothie',
content_type=ContentType.objects.get_for_model(Smoothie)
)
user.user_permissions.add(permission)
# Subsequent permission checks hit the cached permission set
print(user.has_perm('smoothies.deblend_smoothie')) # False
# Re-fetch user (explicitly) from db to clear permissions cache
# Be aware that user.refresh_from_db() won't help here
user = get_user_model().objects.get(pk=user.pk)
# Permission cache is now repopulated from the database
print(user.has_perm('smoothies.deblend_smoothie')) # True
...
...
答案 2 :(得分:0)
如果使用缓存的属性,似乎有所不同。
查看此处:
p.roles[0]
<Role: 16888649>
p.refresh_from_db()
p.roles[0]
<Role: 16888649>
p = Person.objects.get(id=p.id)
p.roles[0]
<Role: 16888650>
models.py中的定义:
@cached_property
def roles(self):
return Role.objects.filter(employer__person=self).order_by("id")